345 lines
11 KiB
Java
345 lines
11 KiB
Java
package com.boydti.fawe.nukkit.optimization.queue;
|
|
|
|
import cn.nukkit.Player;
|
|
import cn.nukkit.block.Block;
|
|
import cn.nukkit.blockentity.BlockEntity;
|
|
import cn.nukkit.entity.Entity;
|
|
import cn.nukkit.level.Level;
|
|
import cn.nukkit.level.Position;
|
|
import cn.nukkit.level.format.generic.BaseFullChunk;
|
|
import cn.nukkit.math.Vector3;
|
|
import cn.nukkit.network.protocol.UpdateBlockPacket;
|
|
import com.boydti.fawe.FaweCache;
|
|
import com.boydti.fawe.config.Settings;
|
|
import com.boydti.fawe.example.CharFaweChunk;
|
|
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
|
import com.boydti.fawe.nukkit.core.NBTConverter;
|
|
import com.boydti.fawe.nukkit.optimization.FaweNukkit;
|
|
import com.boydti.fawe.nukkit.optimization.FaweNukkitPlayer;
|
|
import com.boydti.fawe.object.FaweChunk;
|
|
import com.boydti.fawe.object.FawePlayer;
|
|
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
|
|
import com.boydti.fawe.util.MathMan;
|
|
import com.sk89q.jnbt.CompoundTag;
|
|
import com.sk89q.worldedit.world.World;
|
|
import com.sk89q.worldedit.world.biome.BaseBiome;
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
|
|
public class NukkitQueue extends NMSMappedFaweQueue<Level, BaseFullChunk, BaseFullChunk, BaseFullChunk> {
|
|
private FaweNukkit faweNukkit;
|
|
private Level world;
|
|
|
|
public static int ALLOCATE;
|
|
private static int LIGHT_MASK = 0x739C0;
|
|
|
|
public NukkitQueue(FaweNukkit fn, World world) {
|
|
super(world);
|
|
init(fn);
|
|
}
|
|
|
|
public NukkitQueue(FaweNukkit fn, String world) {
|
|
super(world);
|
|
init(fn);
|
|
}
|
|
|
|
private void init(FaweNukkit fn) {
|
|
this.faweNukkit = fn;
|
|
this.world = faweNukkit.getPlugin().getServer().getLevelByName(getWorldName());
|
|
if (Settings.IMP.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
|
|
ALLOCATE = Settings.IMP.QUEUE.EXTRA_TIME_MS;
|
|
Settings.IMP.QUEUE.EXTRA_TIME_MS = Integer.MIN_VALUE;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
|
|
BaseFullChunk forgeChunk = (BaseFullChunk) chunk.getChunk();
|
|
if (forgeChunk != null) {
|
|
int[] otherMap = forgeChunk.getHeightMapArray();
|
|
for (int i = 0; i < heightMap.length; i++) {
|
|
int newHeight = heightMap[i] & 0xFF;
|
|
int currentHeight = otherMap[i];
|
|
if (newHeight > currentHeight) {
|
|
otherMap[i] = newHeight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public FaweNukkit getFaweNukkit() {
|
|
return faweNukkit;
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity(BaseFullChunk section, int x, int y, int z) {
|
|
int id = section.getBlockId(x & 15, y, z & 15);
|
|
return Block.lightFilter[id];
|
|
}
|
|
|
|
@Override
|
|
public int getBrightness(BaseFullChunk section, int x, int y, int z) {
|
|
int id = section.getBlockId(x & 15, y, z & 15);
|
|
return Block.light[id];
|
|
}
|
|
|
|
@Override
|
|
public int getOpacityBrightnessPair(BaseFullChunk section, int x, int y, int z) {
|
|
int id = section.getBlockId(x & 15, y, z & 15);
|
|
int opacity = Block.lightFilter[id];
|
|
int brightness = Block.light[id];
|
|
return MathMan.pair16(opacity, brightness);
|
|
}
|
|
|
|
@Override
|
|
public void sendChunk(int x, int z, int bitMask) {
|
|
Collection<Player> players = faweNukkit.getPlugin().getServer().getOnlinePlayers().values();
|
|
int view = faweNukkit.getPlugin().getServer().getViewDistance();
|
|
for (Player player : players) {
|
|
Position pos = player.getPosition();
|
|
int pcx = pos.getFloorX() >> 4;
|
|
int pcz = pos.getFloorZ() >> 4;
|
|
if (Math.abs(pcx - x) > view || Math.abs(pcz - z) > view) {
|
|
continue;
|
|
}
|
|
world.requestChunk(x, z, player);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void saveChunk(BaseFullChunk baseFullChunk) {
|
|
baseFullChunk.setChanged();
|
|
}
|
|
|
|
@Override
|
|
public void refreshChunk(FaweChunk fs) {
|
|
sendChunk(fs.getX(), fs.getZ(), fs.getBitMask());
|
|
}
|
|
|
|
@Override
|
|
public CharFaweChunk getPrevious(CharFaweChunk fs, BaseFullChunk sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception {
|
|
return fs;
|
|
}
|
|
|
|
private int skip;
|
|
|
|
@Override
|
|
public File getSaveFolder() {
|
|
if (world == null) {
|
|
return new File("worlds" + File.separator + getWorldName() + File.separator + "region");
|
|
}
|
|
return new File("worlds" + File.separator + world.getFolderName() + File.separator + "region");
|
|
}
|
|
|
|
@Override
|
|
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
|
|
try {
|
|
boolean watching = true; // TODO check if player can see chunk
|
|
if (!watching) return;
|
|
final ArrayList<Block> blocks = new ArrayList<>();
|
|
final int bx = chunk.getX() << 4;
|
|
final int bz = chunk.getZ() << 4;
|
|
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
|
|
@Override
|
|
public void run(int localX, int y, int localZ, int combined) {
|
|
Block block = Block.get(FaweCache.getId(combined), FaweCache.getData(combined));
|
|
block.x = bx + localX;
|
|
block.y = y;
|
|
block.z = bz + localZ;
|
|
blocks.add(block);
|
|
}
|
|
});
|
|
Map<Level, List<Player>> playerMap = new HashMap<>();
|
|
for (FawePlayer player : players) {
|
|
Player nukkitPlayer = ((FaweNukkitPlayer) player).parent;
|
|
List<Player> list = playerMap.get(nukkitPlayer.getLevel());
|
|
if (list == null) {
|
|
list = new ArrayList<>();
|
|
playerMap.put(nukkitPlayer.getLevel(), list);
|
|
}
|
|
list.add(nukkitPlayer);
|
|
}
|
|
Block[] blocksArray = blocks.toArray(new Block[blocks.size()]);
|
|
for (Map.Entry<Level, List<Player>> levelListEntry : playerMap.entrySet()) {
|
|
List<Player> playerList = levelListEntry.getValue();
|
|
levelListEntry.getKey().sendBlocks(playerList.toArray(new Player[playerList.size()]), blocksArray, UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
|
}
|
|
} catch (Throwable e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean hasSky() {
|
|
if (world == null) return false;
|
|
return world.getDimension() == 0;
|
|
}
|
|
|
|
@Override
|
|
public void setFullbright(BaseFullChunk sections) {
|
|
for (int y = 0; y < 256; y++) {
|
|
for (int z = 0; z < 16; z++) {
|
|
for (int x = 0; x < 16; x++) {
|
|
sections.setBlockSkyLight(x, y, z, 15);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean removeSectionLighting(BaseFullChunk section, int layer, boolean hasSky) {
|
|
int minY = layer << 4;
|
|
int maxY = minY + 15;
|
|
for (int y = minY; y < maxY; y++) {
|
|
for (int z = 0; z < 16; z++) {
|
|
for (int x = 0; x < 16; x++) {
|
|
section.setBlockSkyLight(x, y, z, 0);
|
|
section.setBlockLight(x, y, z, 0);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean removeLighting(BaseFullChunk sections, RelightMode mode, boolean hasSky) {
|
|
for (int y = 0; y < 256; y++) {
|
|
for (int z = 0; z < 16; z++) {
|
|
for (int x = 0; x < 16; x++) {
|
|
sections.setBlockSkyLight(x, y, z, 0);
|
|
sections.setBlockLight(x, y, z, 0);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private Vector3 mutable = new Vector3();
|
|
private Vector3 getMutable(int x, int y, int z) {
|
|
mutable.x = x;
|
|
mutable.y = y;
|
|
mutable.z = z;
|
|
return mutable;
|
|
}
|
|
|
|
@Override
|
|
public void relight(int x, int y, int z) {
|
|
world.updateAllLight(getMutable(x, y, z));
|
|
}
|
|
|
|
@Override
|
|
public void relightBlock(int x, int y, int z) {
|
|
world.updateBlockLight(x, y, z);
|
|
}
|
|
|
|
@Override
|
|
public void relightSky(int x, int y, int z) {
|
|
world.updateBlockSkyLight(x, y, z);
|
|
}
|
|
|
|
@Override
|
|
public void setSkyLight(BaseFullChunk chunkSection, int x, int y, int z, int value) {
|
|
chunkSection.setBlockSkyLight(x & 15, y, z & 15, value);
|
|
}
|
|
|
|
@Override
|
|
public void setBlockLight(BaseFullChunk chunkSection, int x, int y, int z, int value) {
|
|
chunkSection.setBlockLight(x & 15, y, z & 15, value);
|
|
}
|
|
|
|
@Override
|
|
public CompoundTag getTileEntity(BaseFullChunk baseChunk, int x, int y, int z) {
|
|
BlockEntity entity = baseChunk.getTile(x & 15, y, z & 15);
|
|
if (entity == null) {
|
|
return null;
|
|
}
|
|
cn.nukkit.nbt.tag.CompoundTag nbt = entity.namedTag;
|
|
return NBTConverter.fromNative(nbt);
|
|
}
|
|
|
|
@Override
|
|
public Level getImpWorld() {
|
|
return world;
|
|
}
|
|
|
|
@Override
|
|
public boolean regenerateChunk(Level level, int x, int z, BaseBiome biome, Long seed) {
|
|
Map<Long, Entity> ents = level.getChunkEntities(x, z);
|
|
if (!ents.isEmpty()) {
|
|
Iterator<Map.Entry<Long, Entity>> iter = ents.entrySet().iterator();
|
|
while (iter.hasNext()) {
|
|
Map.Entry<Long, Entity> entry = iter.next();
|
|
Entity entity = entry.getValue();
|
|
iter.remove();
|
|
level.removeEntity(entity);
|
|
}
|
|
}
|
|
level.regenerateChunk(x, z);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public FaweChunk getFaweChunk(int x, int z) {
|
|
return new NukkitChunk(this, x, z);
|
|
}
|
|
|
|
@Override
|
|
public BaseFullChunk loadChunk(Level level, int x, int z, boolean generate) {
|
|
return level.getChunk(x, z, generate);
|
|
}
|
|
|
|
@Override
|
|
public BaseFullChunk getSections(BaseFullChunk baseFullChunk) {
|
|
return baseFullChunk;
|
|
}
|
|
|
|
@Override
|
|
public BaseFullChunk getCachedChunk(Level level, int cx, int cz) {
|
|
return level.getProvider().getChunk(cx, cz);
|
|
}
|
|
|
|
@Override
|
|
public BaseFullChunk getCachedSections(Level level, int cx, int cz) {
|
|
BaseFullChunk chunk = world.getChunk(cx, cz);
|
|
return chunk;
|
|
}
|
|
|
|
@Override
|
|
public int getBiome(BaseFullChunk baseFullChunk, int x, int z) {
|
|
return baseFullChunk.getBiomeId(x & 15, z & 15);
|
|
}
|
|
|
|
@Override
|
|
public BaseFullChunk getCachedSection(BaseFullChunk baseFullChunk, int cy) {
|
|
return baseFullChunk;
|
|
}
|
|
|
|
@Override
|
|
public int getCombinedId4Data(BaseFullChunk chunkSection, int x, int y, int z) {
|
|
int id = chunkSection.getBlockId(x & 15, y, z & 15);
|
|
if (FaweCache.hasData(id)) {
|
|
int data = chunkSection.getBlockData(x & 15, y, z & 15);
|
|
return (id << 4) + data;
|
|
} else {
|
|
return (id << 4);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getSkyLight(BaseFullChunk sections, int x, int y, int z) {
|
|
return sections.getBlockSkyLight(x & 15, y, z & 15);
|
|
}
|
|
|
|
@Override
|
|
public int getEmmittedLight(BaseFullChunk sections, int x, int y, int z) {
|
|
return sections.getBlockLight(x & 15, y, z & 15);
|
|
}
|
|
}
|