mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-06-11 20:13:55 +00:00
chunk sending / cfi
This commit is contained in:
@ -228,6 +228,8 @@ public enum FaweCache implements Trimable {
|
||||
* Holds data for a palette used in a chunk section
|
||||
*/
|
||||
public final class Palette {
|
||||
public int bitsPerEntry;
|
||||
|
||||
public int paletteToBlockLength;
|
||||
/**
|
||||
* Reusable buffer array, MUST check paletteToBlockLength for actual length
|
||||
@ -319,6 +321,7 @@ public enum FaweCache implements Trimable {
|
||||
|
||||
// Construct palette
|
||||
Palette palette = PALETTE_CACHE.get();
|
||||
palette.bitsPerEntry = bitsPerEntry;
|
||||
palette.paletteToBlockLength = num_palette;
|
||||
palette.paletteToBlock = paletteToBlock;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.boydti.fawe;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.beta.preloader.AsyncPreloader;
|
||||
import com.boydti.fawe.beta.preloader.Preloader;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
@ -54,4 +56,6 @@ public interface IFawe {
|
||||
|
||||
QueueHandler getQueueHandler();
|
||||
|
||||
Preloader getPreloader();
|
||||
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class ChunkFuture implements Future<Void> {
|
||||
|
||||
private final IChunk chunk;
|
||||
private volatile boolean cancelled;
|
||||
private volatile boolean done;
|
||||
|
||||
public ChunkFuture(IChunk chunk) {
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
public IChunk getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
cancelled = true;
|
||||
return !done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get() throws InterruptedException, ExecutionException {
|
||||
synchronized (chunk) {
|
||||
if (!done) {
|
||||
this.wait();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get(long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
synchronized (chunk) {
|
||||
if (!done) {
|
||||
this.wait(unit.toMillis(timeout));
|
||||
if (!done) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
@ -19,5 +20,20 @@ public interface IBlocks extends Trimable {
|
||||
|
||||
BlockState getBlock(int x, int y, int z);
|
||||
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
BiomeType getBiomeType(int x, int z);
|
||||
|
||||
default int getBitMask() {
|
||||
int mask = 0;
|
||||
for (int layer = 0; layer < FaweCache.IMP.CHUNK_LAYERS; layer++) {
|
||||
if (hasSection(layer));
|
||||
mask |= (1 << layer);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
IBlocks reset();
|
||||
}
|
||||
|
@ -28,8 +28,10 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent {
|
||||
|
||||
CompoundTag getTag(int x, int y, int z);
|
||||
|
||||
@Override
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
@Override
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
@Override
|
||||
|
@ -38,8 +38,13 @@ public interface IChunkSet extends IBlocks, OutputExtent {
|
||||
|
||||
BiomeType[] getBiomes();
|
||||
|
||||
@Override
|
||||
BiomeType getBiomeType(int x, int z);
|
||||
|
||||
@Override
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
@Override
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
@Override
|
||||
|
@ -45,16 +45,6 @@ public interface IDelegateQueueExtent extends IQueueExtent {
|
||||
return getParent().isQueueEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void clearBlockUpdates(Player... players) {
|
||||
getParent().clearBlockUpdates(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void sendBlockUpdates(Player... players) {
|
||||
getParent().sendBlockUpdates(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void enableQueue() {
|
||||
getParent().enableQueue();
|
||||
|
@ -31,22 +31,6 @@ public interface IQueueExtent extends Flushable, Trimable, Extent, IBatchProcess
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear any block updates
|
||||
* @param players
|
||||
*/
|
||||
default void clearBlockUpdates(Player... players) {
|
||||
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all the chunks as block updates
|
||||
* @param players
|
||||
*/
|
||||
default void sendBlockUpdates(Player... players) {
|
||||
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
/**
|
||||
* Must ensure that it is enqueued with QueueHandler
|
||||
*/
|
||||
|
@ -0,0 +1,126 @@
|
||||
package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.registry.BlockRegistry;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ChunkPacket implements Function<byte[], byte[]>, Supplier<byte[]> {
|
||||
|
||||
private final boolean full;
|
||||
private final boolean biomes;
|
||||
private final IBlocks chunk;
|
||||
private final int chunkX;
|
||||
private final int chunkZ;
|
||||
|
||||
public ChunkPacket(int chunkX, int chunkZ, IBlocks chunk, boolean replaceAllSections, boolean sendBiomeData) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
this.chunk = chunk;
|
||||
this.full = replaceAllSections;
|
||||
this.biomes = sendBiomeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public byte[] get() {
|
||||
System.out.println("TODO deprecated, use buffer");
|
||||
return apply(new byte[8192]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] apply(byte[] buffer) {
|
||||
try {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
FaweOutputStream fos = new FaweOutputStream(baos);
|
||||
|
||||
fos.writeInt(this.chunkX);
|
||||
fos.writeInt(this.chunkZ);
|
||||
|
||||
fos.writeBoolean(this.full);
|
||||
|
||||
fos.writeVarInt(this.chunk.getBitMask()); // writeVarInt
|
||||
|
||||
// TODO write NBTTagCompound of HeightMaps
|
||||
fos.writeVarInt(0); // (Entities / NBT)
|
||||
|
||||
// TODO write chunk data to byte[]
|
||||
{
|
||||
BlockRegistry registry = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry();
|
||||
try (FastByteArrayOutputStream sectionByteArray = new FastByteArrayOutputStream(buffer); FaweOutputStream sectionWriter = new FaweOutputStream(sectionByteArray)) {
|
||||
for (int layer = 0; layer < FaweCache.IMP.CHUNK_LAYERS; layer++) {
|
||||
if (!this.chunk.hasSection(layer)) continue;
|
||||
char[] ids = this.chunk.getArray(layer);
|
||||
FaweCache.Palette palette = FaweCache.IMP.toPalette(0, ids);
|
||||
|
||||
int nonEmpty = 0; // TODO optimize into same loop as toPalette
|
||||
for (char id :ids) {
|
||||
if (id != 0) nonEmpty++;
|
||||
}
|
||||
sectionWriter.writeShort(nonEmpty); // non empty
|
||||
sectionWriter.writeByte(palette.bitsPerEntry); // bits per block
|
||||
sectionWriter.writeVarInt(palette.paletteToBlockLength);
|
||||
for (int i = 0; i < palette.paletteToBlockLength; i++) {
|
||||
int ordinal = palette.paletteToBlock[i];
|
||||
switch (ordinal) {
|
||||
case BlockID.CAVE_AIR:
|
||||
case BlockID.VOID_AIR:
|
||||
case BlockID.AIR:
|
||||
case BlockID.__RESERVED__:
|
||||
sectionWriter.writeByte(0);
|
||||
break;
|
||||
default:
|
||||
BlockState state = BlockState.getFromOrdinal(ordinal);
|
||||
int mcId = registry.getInternalBlockStateId(state).getAsInt();
|
||||
sectionWriter.writeVarInt(mcId);
|
||||
}
|
||||
}
|
||||
sectionWriter.writeVarInt(palette.blockStatesLength);
|
||||
for (int i = 0; i < palette.blockStatesLength; i++) {
|
||||
sectionWriter.writeLong(palette.blockStates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO write biomes
|
||||
// boolean writeBiomes = true;
|
||||
// for (int x = 0; x < 16; x++) {
|
||||
// for (int z = 0; z < 16; z++) {
|
||||
// BiomeType biome = this.chunk.getBiomeType(x, z);
|
||||
// if (biome == null) {
|
||||
// if (writeBiomes) {
|
||||
// break;
|
||||
// } else {
|
||||
// biome = BiomeTypes.FOREST;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (this.full) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
sectionWriter.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
fos.writeVarInt(sectionByteArray.getSize());
|
||||
for (byte[] arr : sectionByteArray.toByteArrays()) {
|
||||
fos.write(arr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO entities / NBT
|
||||
fos.writeVarInt(0); // (Entities / NBT)
|
||||
return baos.toByteArray();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.beta.IBatchProcessor;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.object.extent.NullExtent;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ChunkSendProcessor extends AbstractDelegateExtent implements IBatchProcessor {
|
||||
private final Supplier<Stream<Player>> players;
|
||||
|
||||
public ChunkSendProcessor(Supplier<Stream<Player>> players) {
|
||||
super(new NullExtent());
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
int chunkX = chunk.getX();
|
||||
int chunkZ = chunk.getZ();
|
||||
boolean replaceAll = true;
|
||||
boolean sendBiome = set.getBiomes() != null;
|
||||
ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, set, replaceAll, sendBiome);
|
||||
Supplier<byte[]> packetData = Suppliers.memoize(packet::get);
|
||||
players.get().forEach(plr -> plr.sendFakeChunk(chunkX, chunkZ, packetData));
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent construct(Extent child) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -170,6 +170,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
|
||||
if (vset instanceof Region) {
|
||||
setBlocks((Region) vset, pattern);
|
||||
}
|
||||
// TODO optimize parallel
|
||||
for (BlockVector3 blockVector3 : vset) {
|
||||
pattern.apply(this, blockVector3, blockVector3);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -39,6 +40,7 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
private ForkJoinPool forkJoinPoolSecondary = new ForkJoinPool();
|
||||
private ThreadPoolExecutor blockingExecutor = FaweCache.IMP.newBlockingExecutor();
|
||||
private ConcurrentLinkedQueue<FutureTask> syncTasks = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<FutureTask> syncWhenFree = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private Map<World, WeakReference<IChunkCache<IChunkGet>>> chunkGetCache = new HashMap<>();
|
||||
private CleanableThreadLocal<IQueueExtent> queuePool = new CleanableThreadLocal<>(QueueHandler.this::create);
|
||||
@ -60,53 +62,61 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
throw new IllegalStateException("Not main thread");
|
||||
}
|
||||
if (!syncTasks.isEmpty()) {
|
||||
long now = System.currentTimeMillis();
|
||||
targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0);
|
||||
long diff = 50 + this.last - (this.last = now);
|
||||
long absDiff = Math.abs(diff);
|
||||
if (diff == 0) {
|
||||
allocate = Math.min(50, allocate + 1);
|
||||
} else if (diff < 0) {
|
||||
allocate = Math.max(5, allocate + diff);
|
||||
} else if (!Fawe.get().getTimer().isAbove(targetTPS)) {
|
||||
allocate = Math.max(5, allocate - 1);
|
||||
}
|
||||
long currentAllocate = allocate - absDiff;
|
||||
long currentAllocate = getAllocate();
|
||||
|
||||
if (!MemUtil.isMemoryFree()) {
|
||||
// TODO reduce mem usage
|
||||
// FaweCache trim
|
||||
// Preloader trim
|
||||
}
|
||||
|
||||
boolean wait = false;
|
||||
do {
|
||||
Runnable task = syncTasks.poll();
|
||||
if (task == null) {
|
||||
if (wait) {
|
||||
synchronized (syncTasks) {
|
||||
try {
|
||||
syncTasks.wait(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
task = syncTasks.poll();
|
||||
wait = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (task != null) {
|
||||
task.run();
|
||||
wait = true;
|
||||
}
|
||||
} while (System.currentTimeMillis() - now < currentAllocate);
|
||||
operate(syncTasks, last, currentAllocate);
|
||||
} else if (!syncWhenFree.isEmpty()) {
|
||||
operate(syncWhenFree, last, getAllocate());
|
||||
} else {
|
||||
// trim??
|
||||
}
|
||||
while (!syncTasks.isEmpty()) {
|
||||
final FutureTask task = syncTasks.poll();
|
||||
}
|
||||
|
||||
private long getAllocate() {
|
||||
long now = System.currentTimeMillis();
|
||||
targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0);
|
||||
long diff = 50 + this.last - (this.last = now);
|
||||
long absDiff = Math.abs(diff);
|
||||
if (diff == 0) {
|
||||
allocate = Math.min(50, allocate + 1);
|
||||
} else if (diff < 0) {
|
||||
allocate = Math.max(5, allocate + diff);
|
||||
} else if (!Fawe.get().getTimer().isAbove(targetTPS)) {
|
||||
allocate = Math.max(5, allocate - 1);
|
||||
}
|
||||
return allocate - absDiff;
|
||||
}
|
||||
|
||||
private void operate(Queue<FutureTask> queue, long start, long currentAllocate) {
|
||||
boolean wait = false;
|
||||
do {
|
||||
Runnable task = queue.poll();
|
||||
if (task == null) {
|
||||
if (wait) {
|
||||
synchronized (syncTasks) {
|
||||
try {
|
||||
queue.wait(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
task = queue.poll();
|
||||
wait = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (task != null) {
|
||||
task.run();
|
||||
wait = true;
|
||||
}
|
||||
}
|
||||
} while (System.currentTimeMillis() - start < currentAllocate);
|
||||
}
|
||||
|
||||
public <T extends Future<T>> void complete(Future<T> task) {
|
||||
@ -136,50 +146,83 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Runnable run, T value) {
|
||||
return sync(run, value, syncTasks);
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Runnable run) {
|
||||
return sync(run, syncTasks);
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Callable<T> call) throws Exception {
|
||||
return sync(call, syncTasks);
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Supplier<T> call) {
|
||||
return sync(call, syncTasks);
|
||||
}
|
||||
|
||||
// Lower priorty sync task (runs only when there are no other tasks)
|
||||
public <T> Future<T> syncWhenFree(Runnable run, T value) {
|
||||
return sync(run, value, syncWhenFree);
|
||||
}
|
||||
|
||||
public <T> Future<T> syncWhenFree(Runnable run) {
|
||||
return sync(run, syncWhenFree);
|
||||
}
|
||||
|
||||
public <T> Future<T> syncWhenFree(Callable<T> call) throws Exception {
|
||||
return sync(call, syncWhenFree);
|
||||
}
|
||||
|
||||
public <T> Future<T> syncWhenFree(Supplier<T> call) {
|
||||
return sync(call, syncWhenFree);
|
||||
}
|
||||
|
||||
private <T> Future<T> sync(Runnable run, T value, Queue<FutureTask> queue) {
|
||||
if (Fawe.isMainThread()) {
|
||||
run.run();
|
||||
return Futures.immediateFuture(value);
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(run, value);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Runnable run) {
|
||||
private <T> Future<T> sync(Runnable run, Queue<FutureTask> queue) {
|
||||
if (Fawe.isMainThread()) {
|
||||
run.run();
|
||||
return Futures.immediateCancelledFuture();
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(run, null);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Callable<T> call) throws Exception {
|
||||
private <T> Future<T> sync(Callable<T> call, Queue<FutureTask> queue) throws Exception {
|
||||
if (Fawe.isMainThread()) {
|
||||
return Futures.immediateFuture(call.call());
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(call);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Supplier<T> call) {
|
||||
private <T> Future<T> sync(Supplier<T> call, Queue<FutureTask> queue) {
|
||||
if (Fawe.isMainThread()) {
|
||||
return Futures.immediateFuture(call.get());
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(call::get);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void notifySync() {
|
||||
synchronized (syncTasks) {
|
||||
syncTasks.notifyAll();
|
||||
private void notifySync(Object object) {
|
||||
synchronized (object) {
|
||||
object.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,11 @@ public class BitSetBlocks implements IChunkSet {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return null;
|
||||
|
@ -11,7 +11,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CharBlocks implements IBlocks {
|
||||
public abstract class CharBlocks implements IBlocks {
|
||||
|
||||
public static final Section FULL = new Section() {
|
||||
@Override
|
||||
|
@ -43,6 +43,11 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int z) {
|
||||
return biomes[(z << 4) | x];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return tiles == null ? Collections.emptyMap() : tiles;
|
||||
|
@ -0,0 +1,110 @@
|
||||
package com.boydti.fawe.beta.preloader;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.collection.MutablePair;
|
||||
import com.boydti.fawe.util.FaweTimer;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public class AsyncPreloader implements Preloader, Runnable {
|
||||
private final ConcurrentHashMap<UUID, MutablePair<World, Set<BlockVector2>>> update;
|
||||
|
||||
public AsyncPreloader() {
|
||||
this.update = new ConcurrentHashMap<>();
|
||||
Fawe.get().getQueueHandler().async(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(Player player) {
|
||||
cancelAndGet(player);
|
||||
}
|
||||
|
||||
private MutablePair<World, Set<BlockVector2>> cancelAndGet(Player player) {
|
||||
MutablePair<World, Set<BlockVector2>> existing = update.get(player.getUniqueId());
|
||||
if (existing != null) {
|
||||
existing.setValue(null);
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Player player) {
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().getIfPresent(player);
|
||||
if (session == null) return;
|
||||
World world = player.getWorld();
|
||||
MutablePair<World, Set<BlockVector2>> existing = cancelAndGet(player);
|
||||
try {
|
||||
Region region = session.getSelection(world);
|
||||
if (!(region instanceof CuboidRegion) || region.getArea() > 50466816) {
|
||||
// TOO LARGE or NOT CUBOID
|
||||
return;
|
||||
}
|
||||
if (existing == null) {
|
||||
MutablePair<World, Set<BlockVector2>> previous = update.putIfAbsent(player.getUniqueId(), existing = new MutablePair<>());
|
||||
if (previous != null) {
|
||||
existing = previous;
|
||||
}
|
||||
synchronized (existing) { // Ensure key & value are mutated together
|
||||
existing.setKey(world);
|
||||
existing.setValue(region.getChunks());
|
||||
}
|
||||
synchronized (update) {
|
||||
update.notify();
|
||||
}
|
||||
}
|
||||
} catch (IncompleteRegionException ignore){}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FaweTimer timer = Fawe.get().getTimer();
|
||||
try {
|
||||
while (true) {
|
||||
if (!update.isEmpty()) {
|
||||
if (timer.getTPS() > 19) {
|
||||
Iterator<Map.Entry<UUID, MutablePair<World, Set<BlockVector2>>>> plrIter = update.entrySet().iterator();
|
||||
Map.Entry<UUID, MutablePair<World, Set<BlockVector2>>> entry = plrIter.next();
|
||||
MutablePair<World, Set<BlockVector2>> pair = entry.getValue();
|
||||
World world = pair.getKey();
|
||||
Set<BlockVector2> chunks = pair.getValue();
|
||||
if (chunks != null) {
|
||||
Iterator<BlockVector2> chunksIter = chunks.iterator();
|
||||
while (chunksIter.hasNext() && pair.getValue() == chunks) { // Ensure the queued load is still valid
|
||||
BlockVector2 chunk = chunksIter.next();
|
||||
queueLoad(world, chunk);
|
||||
}
|
||||
}
|
||||
plrIter.remove();
|
||||
} else {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} else {
|
||||
synchronized (update) {
|
||||
update.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void queueLoad(World world, BlockVector2 chunk) {
|
||||
world.checkLoadedChunk(BlockVector3.at(chunk.getX() << 4, 0, chunk.getZ() << 4));
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.boydti.fawe.beta.preloader;
|
||||
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
|
||||
public interface Preloader {
|
||||
void cancel(Player player);
|
||||
|
||||
void update(Player player);
|
||||
}
|
@ -432,7 +432,7 @@ public class CFICommands {
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
boolean[] ids = new boolean[BlockTypes.size()];
|
||||
for (BlockVector3 pt : clipboard.getRegion()) {
|
||||
ids[clipboard.getBlock(pt).getInternalBlockTypeId()] = true;
|
||||
ids[clipboard.getBlock(pt).getBlockType().getInternalId()] = true;
|
||||
}
|
||||
blocks = new HashSet<>();
|
||||
for (int combined = 0; combined < ids.length; combined++) {
|
||||
@ -606,7 +606,7 @@ public class CFICommands {
|
||||
@CommandPermissions("worldedit.anvil.cfi")
|
||||
public void waterId(Player fp, BlockStateHolder block) throws WorldEditException {
|
||||
CFISettings settings = assertSettings(fp);
|
||||
settings.getGenerator().setWaterId(block.getBlockType().getInternalId());
|
||||
settings.getGenerator().setWater(block.toImmutableState());
|
||||
|
||||
fp.print("Set water id!");
|
||||
settings.resetComponent();
|
||||
@ -621,7 +621,7 @@ public class CFICommands {
|
||||
@CommandPermissions("worldedit.anvil.cfi")
|
||||
public void baseId(Player fp, BlockStateHolder block) throws WorldEditException {
|
||||
CFISettings settings = assertSettings(fp);
|
||||
settings.getGenerator().setBedrockId(block.getBlockType().getInternalId());
|
||||
settings.getGenerator().setBedrock(block.toImmutableState());
|
||||
fp.print(TextComponent.of("Set base id!"));
|
||||
settings.resetComponent();
|
||||
component(fp);
|
||||
|
@ -0,0 +1,8 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Lazy<T> extends Supplier<T> {
|
||||
Supplier<T> init();
|
||||
public default T get() { return init().get(); }
|
||||
}
|
@ -47,7 +47,7 @@ public class VisualExtent extends AbstractDelegateExtent {
|
||||
@Override
|
||||
public Operation commit() {
|
||||
IQueueExtent queue = (IQueueExtent) getExtent();
|
||||
queue.sendBlockUpdates(this.player);
|
||||
System.out.println("Send block updates");
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ public class VisualExtent extends AbstractDelegateExtent {
|
||||
|
||||
public void clear() {
|
||||
IQueueExtent queue = (IQueueExtent) getExtent();
|
||||
queue.clearBlockUpdates(player);
|
||||
System.out.println("Clear");
|
||||
queue.cancel();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
package com.boydti.fawe.object.brush.visualization.cfi;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class CFIDrawer {
|
||||
private final HeightMapMCAGenerator gen;
|
||||
private final TextureUtil tu;
|
||||
private final ForkJoinPool pool;
|
||||
|
||||
public CFIDrawer(HeightMapMCAGenerator generator, TextureUtil textureUtil) {
|
||||
this.gen = generator;
|
||||
this.tu = textureUtil;
|
||||
this.pool = new ForkJoinPool();
|
||||
}
|
||||
|
||||
public CFIDrawer(HeightMapMCAGenerator generator) {
|
||||
this(generator, Fawe.get().getCachedTextureUtil(false, 0, 100));
|
||||
}
|
||||
|
||||
public BufferedImage draw() {
|
||||
BufferedImage img = new BufferedImage(gen.getWidth(), gen.getLength(), BufferedImage.TYPE_INT_RGB);
|
||||
final char[] overlay = gen.overlay == null ? gen.floor.get() : gen.overlay.get();
|
||||
final char[] floor = gen.floor.get();
|
||||
final char[] main = gen.main.get();
|
||||
final byte[] heights = gen.heights.get();
|
||||
final byte[] biomes = gen.biomes.get();
|
||||
final int waterHeight = gen.primitives.waterHeight;
|
||||
final int width = gen.getWidth();
|
||||
final int length = gen.getLength();
|
||||
|
||||
int[] raw = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
|
||||
|
||||
int parallelism = pool.getParallelism();
|
||||
int size = (heights.length + parallelism - 1) / parallelism;
|
||||
for (int i = 0; i < parallelism; i++) {
|
||||
int start = i * size;
|
||||
int end = Math.min(heights.length, start + size);
|
||||
pool.submit((Runnable) () -> {
|
||||
for (int index = start; index < end; index ++) {
|
||||
int height = (heights[index] & 0xFF);
|
||||
char ordinal;
|
||||
if ((ordinal = overlay[index]) == 0) {
|
||||
height--;
|
||||
ordinal = floor[index];
|
||||
if (ordinal == 0) {
|
||||
height--;
|
||||
ordinal = main[index];
|
||||
}
|
||||
}
|
||||
// draw ordinal
|
||||
int color;
|
||||
switch (ordinal >> 4) {
|
||||
case 2:
|
||||
color = getAverageBiomeColor(biomes, width, index);
|
||||
break;
|
||||
case 78:
|
||||
color = (0xDD << 16) + (0xDD << 8) + (0xDD << 0);
|
||||
break;
|
||||
default:
|
||||
color = tu.getColor(BlockTypes.getFromStateOrdinal(ordinal));
|
||||
break;
|
||||
}
|
||||
int slope = getSlope(heights, width, index, height);
|
||||
if (slope != 0) {
|
||||
slope = (slope << 3) + (slope << 2);
|
||||
int r = MathMan.clamp(((color >> 16) & 0xFF) + slope, 0, 255);
|
||||
int g = MathMan.clamp(((color >> 8) & 0xFF) + slope, 0, 255);
|
||||
int b = MathMan.clamp(((color >> 0) & 0xFF) + slope, 0, 255);
|
||||
color = (r << 16) + (g << 8) + (b << 0);
|
||||
}
|
||||
if (height + 1 < waterHeight) {
|
||||
char waterId = gen.primitives.waterOrdinal;
|
||||
int waterColor = 0;
|
||||
switch (waterId) {
|
||||
case BlockID.WATER:
|
||||
color = tu.averageColor((0x11 << 16) + (0x66 << 8) + (0xCC), color);
|
||||
break;
|
||||
case BlockID.LAVA:
|
||||
color = (0xCC << 16) + (0x33 << 8) + (0);
|
||||
break;
|
||||
default:
|
||||
color = tu.getColor(BlockTypes.getFromStateOrdinal(waterId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
raw[index] = color;
|
||||
}
|
||||
});
|
||||
}
|
||||
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
pool.shutdownNow();
|
||||
return img;
|
||||
}
|
||||
|
||||
private final int getAverageBiomeColor(byte[] biomes, int width, int index) {
|
||||
int c0 = tu.getBiome(biomes[index] & 0xFF).grassCombined;
|
||||
int c2 = getBiome(biomes, index + 1 + width, index);
|
||||
int c1 = getBiome(biomes, index - 1 - width, index);
|
||||
// int c3 = getBiome(biomes, index + width, index);
|
||||
// int c4 = getBiome(biomes, index - width, index);
|
||||
int r = ((c0 >> 16) & 0xFF) + ((c1 >> 16) & 0xFF) + ((c2 >> 16) & 0xFF);// + ((c3 >> 16) & 0xFF) + ((c4 >> 16) & 0xFF);
|
||||
int g = ((c0 >> 8) & 0xFF) + ((c1 >> 8) & 0xFF) + ((c2 >> 8) & 0xFF);// + ((c3 >> 8) & 0xFF) + ((c4 >> 8) & 0xFF);
|
||||
int b = ((c0) & 0xFF) + ((c1) & 0xFF) + ((c2) & 0xFF);// + ((c3) & 0xFF) + ((c4) & 0xFF);
|
||||
r = r * 85 >> 8;
|
||||
g = g * 85 >> 8;
|
||||
b = b * 85 >> 8;
|
||||
return (r << 16) + (g << 8) + (b);
|
||||
}
|
||||
|
||||
private final int getBiome(byte[] biomes, int newIndex, int index) {
|
||||
if (newIndex < 0 || newIndex >= biomes.length) newIndex = index;
|
||||
int biome = biomes[newIndex] & 0xFF;
|
||||
return tu.getBiome(biome).grassCombined;
|
||||
}
|
||||
|
||||
private int getSlope(byte[] heights, int width, int index, int height) {
|
||||
return (
|
||||
+ getHeight(heights, index + 1, height)
|
||||
// + getHeight(heights, index + width, height)
|
||||
+ getHeight(heights, index + width + 1, height)
|
||||
- getHeight(heights, index - 1, height)
|
||||
// - getHeight(heights, index - width, height)
|
||||
- getHeight(heights, index - width - 1, height)
|
||||
);
|
||||
}
|
||||
|
||||
private int getHeight(byte[] heights, int index, int height) {
|
||||
if (index < 0 || index >= heights.length) return height;
|
||||
return heights[index] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package com.boydti.fawe.object.brush.visualization.cfi;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.ChunkPacket;
|
||||
import com.boydti.fawe.beta.implementation.FallbackChunkGet;
|
||||
import com.boydti.fawe.object.FaweInputStream;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
@ -15,7 +17,6 @@ import com.boydti.fawe.object.collection.DifferentialBlockBuffer;
|
||||
import com.boydti.fawe.object.collection.LocalBlockVector2DSet;
|
||||
import com.boydti.fawe.object.collection.SummedAreaTable;
|
||||
import com.boydti.fawe.object.exception.FaweChunkLoadException;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.object.schematic.Schematic;
|
||||
import com.boydti.fawe.util.CachedTextureUtil;
|
||||
import com.boydti.fawe.util.RandomTextureUtil;
|
||||
@ -23,6 +24,7 @@ import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
import com.boydti.fawe.util.image.Drawable;
|
||||
import com.boydti.fawe.util.image.ImageViewer;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
@ -64,6 +66,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// TODO FIXME
|
||||
@ -73,9 +76,9 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
private final DifferentialBlockBuffer blocks;
|
||||
protected final DifferentialArray<byte[]> heights;
|
||||
protected final DifferentialArray<byte[]> biomes;
|
||||
protected final DifferentialArray<int[]> floor;
|
||||
protected final DifferentialArray<int[]> main;
|
||||
protected DifferentialArray<int[]> overlay;
|
||||
protected final DifferentialArray<char[]> floor;
|
||||
protected final DifferentialArray<char[]> main;
|
||||
protected DifferentialArray<char[]> overlay;
|
||||
|
||||
protected final CFIPrimitives primitives = new CFIPrimitives();
|
||||
private CFIPrimitives oldPrimitives = new CFIPrimitives();
|
||||
@ -86,8 +89,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int worldThickness;
|
||||
boolean randomVariation = true;
|
||||
int biomePriority;
|
||||
int waterId = BlockID.WATER;
|
||||
int bedrockId = BlockID.BEDROCK;
|
||||
char waterOrdinal = BlockID.WATER;
|
||||
char bedrockOrdinal = BlockID.BEDROCK;
|
||||
boolean modifiedMain;
|
||||
|
||||
@Override
|
||||
@ -225,13 +228,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
blocks = new DifferentialBlockBuffer(width, length);
|
||||
heights = new DifferentialArray<>(new byte[getArea()]);
|
||||
biomes = new DifferentialArray<>(new byte[getArea()]);
|
||||
floor = new DifferentialArray<>(new int[getArea()]);
|
||||
main = new DifferentialArray<>(new int[getArea()]);
|
||||
floor = new DifferentialArray<>(new char[getArea()]);
|
||||
main = new DifferentialArray<>(new char[getArea()]);
|
||||
|
||||
int stone = BlockID.STONE;
|
||||
int grass = BlockTypes.GRASS_BLOCK.getDefaultState().with(PropertyKey.SNOWY, false).getInternalId();
|
||||
Arrays.fill(main.getIntArray(), stone);
|
||||
Arrays.fill(floor.getIntArray(), grass);
|
||||
char stone = BlockID.STONE;
|
||||
char grass = BlockTypes.GRASS_BLOCK.getDefaultState().with(PropertyKey.SNOWY, false).getOrdinalChar();
|
||||
Arrays.fill(overlay.getCharArray(), stone);
|
||||
Arrays.fill(overlay.getCharArray(), grass);
|
||||
}
|
||||
|
||||
public Metadatable getMetaData() {
|
||||
@ -259,10 +262,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return player;
|
||||
}
|
||||
|
||||
private int[][][] getChunkArray(int x, int z) {
|
||||
int[][][][][] blocksData = blocks.get();
|
||||
private char[][][] getChunkArray(int x, int z) {
|
||||
char[][][][][] blocksData = blocks.get();
|
||||
if (blocksData == null) return null;
|
||||
int[][][][] arr = blocksData[z];
|
||||
char[][][][] arr = blocksData[z];
|
||||
return arr != null ? arr[x] : null;
|
||||
}
|
||||
|
||||
@ -320,8 +323,20 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int X, int Z, int mask) {
|
||||
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED"); // add method to adapter to send custom chunk
|
||||
public void refreshChunk(int chunkX, int chunkZ) {
|
||||
IChunkSet chunk = getChunk(chunkX, chunkZ);
|
||||
ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, chunk, true, true);
|
||||
player.sendFakeChunk(chunkX, chunkZ, packet::get);
|
||||
}
|
||||
|
||||
public IChunkSet getChunk(int chunkX, int chunkZ) {
|
||||
// TODO don't generate new Writeable MCA chunk
|
||||
System.out.println("TODO don't generate new Writeable MCA chunk");
|
||||
WritableMCAChunk tmp = new WritableMCAChunk();
|
||||
int bx = chunkX << 4;
|
||||
int bz = chunkZ << 4;
|
||||
write(tmp, bx, bx + 15, bz, bz + 15);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public TextureUtil getRawTextureUtil() {
|
||||
@ -349,8 +364,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
|
||||
public void setBedrockId(int bedrockId) {
|
||||
this.primitives.bedrockId = bedrockId;
|
||||
public void setBedrock(BlockState bedrock) {
|
||||
this.primitives.bedrockOrdinal = bedrock.getOrdinalChar();
|
||||
}
|
||||
|
||||
public void setFloorThickness(int floorThickness) {
|
||||
@ -365,8 +380,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
this.primitives.waterHeight = waterHeight;
|
||||
}
|
||||
|
||||
public void setWaterId(int waterId) {
|
||||
this.primitives.waterId = waterId;
|
||||
public void setWater(BlockState water) {
|
||||
this.primitives.waterOrdinal = water.getOrdinalChar();
|
||||
}
|
||||
|
||||
public void setTextureRandomVariation(boolean randomVariation) {
|
||||
@ -390,10 +405,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
public void smooth(BlockVector2 min, BlockVector2 max, int radius, int iterations) {
|
||||
int snowLayer = BlockTypes.SNOW.getInternalId();
|
||||
int snowBlock = BlockTypes.SNOW_BLOCK.getInternalId();
|
||||
int snowLayer = BlockTypes.SNOW.getDefaultState().getOrdinalChar();
|
||||
int snowBlock = BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar();
|
||||
|
||||
int[] floor = this.floor.get();
|
||||
char[] floor = this.floor.get();
|
||||
byte[] heights = this.heights.get();
|
||||
|
||||
int width = getWidth();
|
||||
@ -421,7 +436,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int index = zIndex + minX;
|
||||
for (int x = minX; x <= maxX; x++, index++, localIndex++) {
|
||||
int combined = floor[index];
|
||||
if (BlockTypes.getFromStateId(combined) == BlockTypes.SNOW) {
|
||||
if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) {
|
||||
layers[localIndex] = (char) (((heights[index] & 0xFF) << 3) + (floor[index] >> BlockTypes.BIT_OFFSET) - 7);
|
||||
} else {
|
||||
layers[localIndex] = (char) ((heights[index] & 0xFF) << 3);
|
||||
@ -453,16 +468,15 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
private final void setLayerHeight(int index, int blockHeight, int layerHeight) {
|
||||
int floorState = floor.get()[index];
|
||||
BlockType type = BlockTypes.getFromStateId(floorState);
|
||||
switch (type.getInternalId()) {
|
||||
switch (floorState) {
|
||||
case BlockID.SNOW:
|
||||
case BlockID.SNOW_BLOCK:
|
||||
if (layerHeight != 0) {
|
||||
this.heights.setByte(index, (byte) (blockHeight + 1));
|
||||
this.floor.setInt(index, BlockTypes.SNOW.getInternalId() + layerHeight);
|
||||
this.floor.setInt(index, BlockTypes.SNOW.getDefaultState().getOrdinalChar() + layerHeight);
|
||||
} else {
|
||||
this.heights.setByte(index, (byte) blockHeight);
|
||||
this.floor.setInt(index, BlockTypes.SNOW_BLOCK.getInternalId());
|
||||
this.floor.setInt(index, BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -479,16 +493,15 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
private final void setLayerHeightRaw(int index, int blockHeight, int layerHeight) {
|
||||
int floorState = floor.get()[index];
|
||||
BlockType type = BlockTypes.getFromStateId(floorState);
|
||||
switch (type.getInternalId()) {
|
||||
switch (floorState) {
|
||||
case BlockID.SNOW:
|
||||
case BlockID.SNOW_BLOCK:
|
||||
if (layerHeight != 0) {
|
||||
this.heights.getByteArray()[index] = (byte) (blockHeight + 1);
|
||||
this.floor.getIntArray()[index] = BlockTypes.SNOW.getInternalId() + layerHeight;
|
||||
this.overlay.getCharArray()[index] = (char) (BlockTypes.SNOW.getDefaultState().getOrdinalChar() + layerHeight);
|
||||
} else {
|
||||
this.heights.getByteArray()[index] = (byte) blockHeight;
|
||||
this.floor.getIntArray()[index] = BlockTypes.SNOW_BLOCK.getInternalId();
|
||||
this.overlay.getCharArray()[index] = BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -498,7 +511,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
private void smooth(BufferedImage img, Mask mask, boolean white, int radius, int iterations) {
|
||||
int[] floor = this.floor.get();
|
||||
char[] floor = this.floor.get();
|
||||
byte[] heights = this.heights.get();
|
||||
|
||||
long[] copy = new long[heights.length];
|
||||
@ -511,7 +524,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
for (int j = 0; j < iterations; j++) {
|
||||
for (int i = 0; i < heights.length; i++) {
|
||||
int combined = floor[i];
|
||||
if (BlockTypes.getFromStateId(combined) == BlockTypes.SNOW) {
|
||||
if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) {
|
||||
layers[i] = (char) (((heights[i] & 0xFF) << 3) + (floor[i] >> BlockTypes.BIT_OFFSET) - 7);
|
||||
} else {
|
||||
layers[i] = (char) ((heights[i] & 0xFF) << 3);
|
||||
@ -704,7 +717,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block);
|
||||
}
|
||||
|
||||
private boolean setBlock(int x, int y, int z, int combined) {
|
||||
private boolean setBlock(int x, int y, int z, char combined) {
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= getArea()) return false;
|
||||
int height = heights.getByte(index) & 0xFF;
|
||||
@ -713,8 +726,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
floor.setInt(index, combined);
|
||||
return true;
|
||||
case 1:
|
||||
int mainId = main.getInt(index);
|
||||
int floorId = floor.getInt(index);
|
||||
char mainId = overlay.getChar(index);
|
||||
char floorId = overlay.getChar(index);
|
||||
floor.setInt(index, combined);
|
||||
|
||||
byte currentHeight = heights.getByte(index);
|
||||
@ -870,7 +883,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
for (int cz = scz; cz <= ecz; cz++) {
|
||||
for (int cx = scx; cx <= ecx; cx++) {
|
||||
world.sendChunk(cx + OX, cz + OZ, 0);
|
||||
world.refreshChunk(cx + OX, cz + OZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -890,20 +903,19 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return BiomeTypes.get(biomes.getByte(index));
|
||||
}
|
||||
|
||||
// @Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweChunkLoadException {
|
||||
public int getOrdinal(int x, int y, int z) throws FaweChunkLoadException {
|
||||
int index = z * getWidth() + x;
|
||||
if (y < 0) return 0;
|
||||
if (index < 0 || index >= getArea() || x < 0 || x >= getWidth()) return 0;
|
||||
int height = heights.getByte(index) & 0xFF;
|
||||
if (y > height) {
|
||||
if (y == height + 1) {
|
||||
return overlay != null ? overlay.getInt(index) : 0;
|
||||
return overlay != null ? overlay.getChar(index) : 0;
|
||||
}
|
||||
if (blocks != null) {
|
||||
short chunkX = (short) (x >> 4);
|
||||
short chunkZ = (short) (z >> 4);
|
||||
int[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
char[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
if (map != null) {
|
||||
int combined = get(map, x, y, z);
|
||||
if (combined != 0) {
|
||||
@ -912,16 +924,16 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
if (y <= primitives.waterHeight) {
|
||||
return primitives.waterId << 4;
|
||||
return primitives.waterOrdinal;
|
||||
}
|
||||
return 0;
|
||||
} else if (y == height) {
|
||||
return floor.getInt(index);
|
||||
return overlay.getChar(index);
|
||||
} else {
|
||||
if (blocks != null) {
|
||||
short chunkX = (short) (x >> 4);
|
||||
short chunkZ = (short) (z >> 4);
|
||||
int[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
char[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
if (map != null) {
|
||||
int combined = get(map, x, y, z);
|
||||
if (combined != 0) {
|
||||
@ -929,13 +941,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
}
|
||||
return main.getInt(index);
|
||||
return overlay.getChar(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
|
||||
return this.setBlock(x, y, z, block.getInternalId());
|
||||
return this.setBlock(x, y, z, block.getOrdinalChar());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -950,7 +962,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public BlockState getFloor(int x, int z) {
|
||||
int index = z * getWidth() + x;
|
||||
return BlockState.getFromInternalId(floor.getInt(index));
|
||||
return BlockState.getFromOrdinal(overlay.getChar(index));
|
||||
}
|
||||
|
||||
public int getHeight(int x, int z) {
|
||||
@ -964,19 +976,19 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(int x, int z, BlockStateHolder block) {
|
||||
int index = z * getWidth() + x;
|
||||
floor.setInt(index, block.getInternalId());
|
||||
floor.setInt(index, block.getOrdinalChar());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return BlockState.getFromInternalId(getCombinedId4Data(x, y, z));
|
||||
return BlockState.getFromOrdinal(getOrdinal(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= getArea()) index = Math.floorMod(index, getArea());
|
||||
return ((heights.getByte(index) & 0xFF) << 3) + (floor.getInt(index) & 0xFF) + 1;
|
||||
return ((heights.getByte(index) & 0xFF) << 3) + (overlay.getChar(index) & 0xFF) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1017,9 +1029,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
@Override
|
||||
public BufferedImage draw() {
|
||||
// TODO NOT IMPLEMENTED
|
||||
// return new HeightMapMCADrawer(this).draw();
|
||||
return null;
|
||||
return new CFIDrawer(this).draw();
|
||||
}
|
||||
|
||||
public void setBiomePriority(int value) {
|
||||
@ -1044,12 +1054,12 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int maxIndex = getArea() - 1;
|
||||
|
||||
biomes.record(() -> floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
byte[] biomesArr = biomes.get();
|
||||
|
||||
int index = 0;
|
||||
int[] buffer = new int[2];
|
||||
char[] buffer = new char[2];
|
||||
for (int z = 0; z < img.getHeight(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < img.getWidth(); x++, index++) {
|
||||
@ -1065,7 +1075,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
int color = img.getRGB(x, z);
|
||||
if (textureUtil.getIsBlockCloserThanBiome(buffer, color, primitives.biomePriority)) {
|
||||
int combined = buffer[0];
|
||||
char combined = buffer[0];
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1079,23 +1089,20 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
int widthIndex = img.getWidth() - 1;
|
||||
int heightIndex = img.getHeight() - 1;
|
||||
int maxIndex = getArea() - 1;
|
||||
|
||||
biomes.record(() -> floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
byte[] biomesArr = biomes.get();
|
||||
|
||||
int[] buffer = new int[2];
|
||||
char[] buffer = new char[2];
|
||||
int index = 0;
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
boolean yBiome = y > 0 && y < heightIndex;
|
||||
for (int x = 0; x < img.getWidth(); x++, index++) {
|
||||
int color = img.getRGB(x, y);
|
||||
if (textureUtil.getIsBlockCloserThanBiome(buffer, color, primitives.biomePriority)) {
|
||||
int combined = buffer[0];
|
||||
char combined = buffer[0];
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1135,8 +1142,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
@ -1147,7 +1154,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, z);
|
||||
BlockType block = textureUtil.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
int combined = block.getInternalId();
|
||||
char combined = block.getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1165,8 +1172,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
@ -1178,7 +1185,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, z);
|
||||
BlockType block = textureUtil.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
int combined = block.getInternalId();
|
||||
char combined = block.getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
} else {
|
||||
@ -1197,8 +1204,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int z = 0; z < img.getHeight(); z++) {
|
||||
@ -1206,7 +1213,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, z);
|
||||
BlockType block = textureUtil.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
int combined = block.getInternalId();
|
||||
char combined = block.getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
} else {
|
||||
@ -1224,8 +1231,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
@ -1233,8 +1240,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, y);
|
||||
BlockType[] layer = textureUtil.getNearestLayer(color);
|
||||
if (layer != null) {
|
||||
floorArr[index] = layer[0].getInternalId();
|
||||
mainArr[index] = layer[1].getInternalId();
|
||||
floorArr[index] = layer[0].getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = layer[1].getDefaultState().getOrdinalChar();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
@ -1260,18 +1267,18 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setOverlay(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setOverlay(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setOverlay(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else if (pattern instanceof BlockType) {
|
||||
setOverlay(img, ((BlockType) pattern).getInternalId(), white);
|
||||
setOverlay(img, ((BlockType) pattern).getDefaultState().getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) {
|
||||
overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
}
|
||||
|
||||
overlay.record(() -> {
|
||||
int[] overlayArr = overlay.get();
|
||||
char[] overlayArr = overlay.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1281,7 +1288,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
overlayArr[index] = pattern.apply(mutable).getInternalId();
|
||||
overlayArr[index] = pattern.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1292,14 +1299,14 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setMain(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setMain(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setMain(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
|
||||
main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1309,7 +1316,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
mainArr[index] = pattern.apply(mutable).getInternalId();
|
||||
mainArr[index] = pattern.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1319,13 +1326,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setFloor(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setFloor(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
|
||||
floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
char[] floorArr = floor.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1335,7 +1342,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
floorArr[index] = pattern.apply(mutable).getInternalId();
|
||||
floorArr[index] = pattern.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1345,15 +1352,15 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setColumn(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setColumn(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setColumn(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
|
||||
main.record(() -> floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
int[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1363,7 +1370,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
int combined = pattern.apply(mutable).getInternalId();
|
||||
char combined = pattern.apply(mutable).getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1375,10 +1382,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setOverlay(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setOverlay(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setOverlay(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
int index = 0;
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
@ -1386,7 +1393,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
overlay.setInt(index, pattern.apply(mutable).getInternalId());
|
||||
overlay.setInt(index, pattern.apply(mutable).getOrdinalChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1395,7 +1402,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setFloor(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setFloor(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
@ -1405,7 +1412,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
floor.setInt(index, pattern.apply(mutable).getInternalId());
|
||||
floor.setInt(index, pattern.apply(mutable).getOrdinalChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1414,7 +1421,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setMain(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setMain(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setMain(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
primitives.modifiedMain = true;
|
||||
int index = 0;
|
||||
@ -1425,7 +1432,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
main.setInt(index, pattern.apply(mutable).getInternalId());
|
||||
main.setInt(index, pattern.apply(mutable).getOrdinalChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1434,7 +1441,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setColumn(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setColumn(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setColumn(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
primitives.modifiedMain = true;
|
||||
int index = 0;
|
||||
@ -1445,7 +1452,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
int combined = pattern.apply(mutable).getInternalId();
|
||||
int combined = pattern.apply(mutable).getOrdinalChar();
|
||||
floor.setInt(index, combined);
|
||||
main.setInt(index, combined);
|
||||
}
|
||||
@ -1460,10 +1467,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(Pattern value) {
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setFloor(((BlockStateHolder) value).getInternalId());
|
||||
setFloor(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
char[] floorArr = floor.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1471,7 +1478,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
floorArr[index] = value.apply(mutable).getInternalId();
|
||||
floorArr[index] = value.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1480,11 +1487,11 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setColumn(Pattern value) {
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setColumn(((BlockStateHolder) value).getInternalId());
|
||||
setColumn(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
main.record(() -> floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
int[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1492,7 +1499,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
int combined = value.apply(mutable).getInternalId();
|
||||
char combined = value.apply(mutable).getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1503,10 +1510,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setMain(Pattern value) {
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setMain(((BlockStateHolder) value).getInternalId());
|
||||
setMain(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1514,7 +1521,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
mainArr[index] = value.apply(mutable).getInternalId();
|
||||
mainArr[index] = value.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1522,12 +1529,12 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
public void setOverlay(Pattern value) {
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setOverlay(((BlockStateHolder) value).getInternalId());
|
||||
setOverlay(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
overlay.record(() -> {
|
||||
int[] overlayArr = overlay.get();
|
||||
char[] overlayArr = overlay.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1535,7 +1542,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
overlayArr[index] = value.apply(mutable).getInternalId();
|
||||
overlayArr[index] = value.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1567,16 +1574,16 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
public WritableMCAChunk write(WritableMCAChunk chunk, int csx, int cex, int csz, int cez) {
|
||||
byte[] heights = this.heights.get();
|
||||
byte[] biomes = this.biomes.get();
|
||||
int[] main = this.main.get();
|
||||
int[] floor = this.floor.get();
|
||||
int[] overlay = this.overlay != null ? this.overlay.get() : null;
|
||||
char[] main = this.main.get();
|
||||
char[] floor = this.floor.get();
|
||||
char[] overlay = this.overlay != null ? this.overlay.get() : null;
|
||||
try {
|
||||
int[] indexes = FaweCache.IMP.INDEX_STORE.get();
|
||||
|
||||
int index;
|
||||
int maxY = 0;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int[] heightMap = chunk.biomes;
|
||||
byte[] heightMap = chunk.biomes;
|
||||
int globalIndex;
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
globalIndex = z * getWidth() + csx;
|
||||
@ -1584,7 +1591,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
for (int x = csx; x <= cex; x++, index++, globalIndex++) {
|
||||
indexes[index] = globalIndex;
|
||||
int height = heights[globalIndex] & 0xFF;
|
||||
heightMap[index] = height;
|
||||
heightMap[index] = (byte) height;
|
||||
maxY = Math.max(maxY, height);
|
||||
minY = Math.min(minY, height);
|
||||
}
|
||||
@ -1599,7 +1606,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
if (primitives.waterHeight != 0) {
|
||||
int maxIndex = primitives.waterHeight << 8;
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, primitives.waterId);
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, primitives.waterOrdinal);
|
||||
}
|
||||
|
||||
if (primitives.modifiedMain) { // If the main block is modified, we can't short circuit this
|
||||
@ -1607,7 +1614,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
index = (z & 15) << 4;
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
int mainCombined = main[globalIndex];
|
||||
char mainCombined = main[globalIndex];
|
||||
for (int y = 0; y < minY; y++) {
|
||||
chunk.blocks[index + (y << 8)] = mainCombined;
|
||||
}
|
||||
@ -1615,7 +1622,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
} else {
|
||||
int maxIndex = minY << 8;
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, BlockID.STONE);
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, (char) BlockID.STONE);
|
||||
}
|
||||
|
||||
final boolean hasFloorThickness = primitives.floorThickness != 0 || primitives.worldThickness != 0;
|
||||
@ -1630,13 +1637,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
index = (z & 15) << 4;
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
int height = heightMap[index];
|
||||
int height = heightMap[index] & 0xFF;
|
||||
int maxMainY = height;
|
||||
int minMainY = minY;
|
||||
|
||||
int mainCombined = main[globalIndex];
|
||||
char mainCombined = main[globalIndex];
|
||||
|
||||
int floorCombined = floor[globalIndex];
|
||||
char floorCombined = floor[globalIndex];
|
||||
if (hasFloorThickness) {
|
||||
if (x > 0) maxMainY = Math.min(heights[globalIndex - 1] & 0xFF, maxMainY);
|
||||
if (x < getWidth() - 1) maxMainY = Math.min(heights[globalIndex + 1] & 0xFF, maxMainY);
|
||||
@ -1671,33 +1678,33 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
if (hasOverlay) {
|
||||
int overlayCombined = overlay[globalIndex];
|
||||
char overlayCombined = overlay[globalIndex];
|
||||
int overlayIndex = index + (height + 1 << 8);
|
||||
chunk.blocks[overlayIndex] = overlayCombined;
|
||||
}
|
||||
|
||||
if (primitives.bedrockId != 0) {
|
||||
chunk.blocks[index] = primitives.bedrockId;
|
||||
if (primitives.bedrockOrdinal != 0) {
|
||||
chunk.blocks[index] = primitives.bedrockOrdinal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[][][] localBlocks = getChunkArray(chunk.getX(), chunk.getZ());
|
||||
char[][][] localBlocks = getChunkArray(chunk.getX(), chunk.getZ());
|
||||
if (localBlocks != null) {
|
||||
index = 0;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
int by = layer << 4;
|
||||
int ty = by + 15;
|
||||
for (int y = by; y <= ty; y++, index += 256) {
|
||||
int[][] yBlocks = localBlocks[y];
|
||||
char[][] yBlocks = localBlocks[y];
|
||||
if (yBlocks != null) {
|
||||
chunk.hasSections[layer] = true;
|
||||
for (int z = 0; z < yBlocks.length; z++) {
|
||||
int[] zBlocks = yBlocks[z];
|
||||
char[] zBlocks = yBlocks[z];
|
||||
if (zBlocks != null) {
|
||||
int zIndex = index + (z << 4);
|
||||
for (int x = 0; x < zBlocks.length; x++, zIndex++) {
|
||||
int combined = zBlocks[x];
|
||||
char combined = zBlocks[x];
|
||||
if (combined == 0) continue;
|
||||
chunk.blocks[zIndex] = combined;
|
||||
}
|
||||
@ -1719,24 +1726,24 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return chunk;
|
||||
}
|
||||
|
||||
private void setUnsafe(int[][][] map, int combined, int x, int y, int z) {
|
||||
int[][] yMap = map[y];
|
||||
private void setUnsafe(char[][][] map, char combined, int x, int y, int z) {
|
||||
char[][] yMap = map[y];
|
||||
if (yMap == null) {
|
||||
map[y] = yMap = new int[16][];
|
||||
map[y] = yMap = new char[16][];
|
||||
}
|
||||
int[] zMap = yMap[z];
|
||||
char[] zMap = yMap[z];
|
||||
if (zMap == null) {
|
||||
yMap[z] = zMap = new int[16];
|
||||
yMap[z] = zMap = new char[16];
|
||||
}
|
||||
zMap[x] = combined;
|
||||
}
|
||||
|
||||
private int get(int[][][] map, int x, int y, int z) {
|
||||
int[][] yMap = map[y];
|
||||
private int get(char[][][] map, int x, int y, int z) {
|
||||
char[][] yMap = map[y];
|
||||
if (yMap == null) {
|
||||
return 0;
|
||||
}
|
||||
int[] zMap = yMap[z & 15];
|
||||
char[] zMap = yMap[z & 15];
|
||||
if (zMap == null) {
|
||||
return 0;
|
||||
}
|
||||
@ -1745,7 +1752,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
private void setOverlay(Mask mask, int combined) {
|
||||
int index = 0;
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
@ -1807,29 +1814,29 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
|
||||
private void setFloor(int value) {
|
||||
private void setFloor(char value) {
|
||||
floor.record(() -> Arrays.fill(floor.get(), value));
|
||||
}
|
||||
|
||||
private void setColumn(int value) {
|
||||
private void setColumn(char value) {
|
||||
setFloor(value);
|
||||
setMain(value);
|
||||
}
|
||||
|
||||
private void setMain(int value) {
|
||||
private void setMain(char value) {
|
||||
primitives.modifiedMain = true;
|
||||
main.record(() -> Arrays.fill(main.get(), value));
|
||||
}
|
||||
|
||||
private void setOverlay(int value) {
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
private void setOverlay(char value) {
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
overlay.record(() -> Arrays.fill(overlay.get(), value));
|
||||
}
|
||||
|
||||
private void setOverlay(BufferedImage img, int combined, boolean white) {
|
||||
private void setOverlay(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
|
||||
overlay.record(() -> {
|
||||
int index = 0;
|
||||
@ -1845,7 +1852,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
});
|
||||
}
|
||||
|
||||
private void setMain(BufferedImage img, int combined, boolean white) {
|
||||
private void setMain(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
@ -1864,7 +1871,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
});
|
||||
}
|
||||
|
||||
private void setFloor(BufferedImage img, int combined, boolean white) {
|
||||
private void setFloor(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
|
||||
@ -1882,7 +1889,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
});
|
||||
}
|
||||
|
||||
private void setColumn(BufferedImage img, int combined, boolean white) {
|
||||
private void setColumn(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
|
@ -84,7 +84,7 @@ public abstract class MCAWriter implements Extent {
|
||||
@Override
|
||||
protected WritableMCAChunk initialValue() {
|
||||
WritableMCAChunk chunk = new WritableMCAChunk();
|
||||
Arrays.fill(chunk.blocks, BlockID.AIR);
|
||||
Arrays.fill(chunk.blocks, (char) BlockID.AIR);
|
||||
// Arrays.fill(chunk.skyLight, (byte) 255);
|
||||
return chunk;
|
||||
}
|
||||
@ -142,11 +142,12 @@ public abstract class MCAWriter implements Extent {
|
||||
pool.submit(() -> {
|
||||
try {
|
||||
WritableMCAChunk chunk = chunkStore.get();
|
||||
chunk.clear(fcx, fcz);
|
||||
chunk.reset();
|
||||
chunk.setPosition(fcx, fcz);
|
||||
chunk = write(chunk, csx, cex, csz, cez);
|
||||
if (chunk != null) {
|
||||
// Generation offset
|
||||
chunk.setLoc( fcx + (getOffsetX() >> 4), fcz + (getOffsetZ() >> 4));
|
||||
chunk.setPosition( fcx + (getOffsetX() >> 4), fcz + (getOffsetZ() >> 4));
|
||||
|
||||
// Compress
|
||||
byte[] bytes = chunk.toBytes(byteStore1.get());
|
||||
|
@ -1,39 +1,44 @@
|
||||
package com.boydti.fawe.object.brush.visualization.cfi;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.object.collection.BitArray4096;
|
||||
import com.boydti.fawe.object.collection.BlockVector3ChunkMap;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.NBTConstants;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class WritableMCAChunk {
|
||||
public class WritableMCAChunk implements IChunkSet {
|
||||
public final boolean[] hasSections = new boolean[16];
|
||||
public final byte[] skyLight = new byte[65536];
|
||||
public final byte[] blockLight = new byte[65536];
|
||||
|
||||
public boolean hasBiomes = false;
|
||||
public final int[] biomes = new int[256];
|
||||
public final byte[] biomes = new byte[256];
|
||||
|
||||
public final int[] blocks = new int[65536];
|
||||
public final char[] blocks = new char[65536];
|
||||
|
||||
public Map<Short, CompoundTag> tiles = new HashMap<>();
|
||||
public BlockVector3ChunkMap<CompoundTag> tiles = new BlockVector3ChunkMap<CompoundTag>();
|
||||
public Map<UUID, CompoundTag> entities = new HashMap<>();
|
||||
public long inhabitedTime = System.currentTimeMillis();
|
||||
public long lastUpdate;
|
||||
@ -54,14 +59,18 @@ public class WritableMCAChunk {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
public void setLoc(int X, int Z) {
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return hasSections[layer];
|
||||
}
|
||||
|
||||
public void setPosition(int X, int Z) {
|
||||
this.chunkX = X;
|
||||
this.chunkZ = Z;
|
||||
}
|
||||
|
||||
public void clear(int X, int Z) {
|
||||
this.chunkX = X;
|
||||
this.chunkZ = Z;
|
||||
@Override
|
||||
public IChunkSet reset() {
|
||||
if (!tiles.isEmpty()) {
|
||||
tiles.clear();
|
||||
}
|
||||
@ -76,6 +85,7 @@ public class WritableMCAChunk {
|
||||
blocks[i] = BlockID.AIR;
|
||||
}
|
||||
Arrays.fill(hasSections, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void write(NBTOutputStream nbtOut) throws IOException {
|
||||
@ -192,13 +202,13 @@ public class WritableMCAChunk {
|
||||
}
|
||||
|
||||
|
||||
out.writeNamedTagName("BlockLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
out.writeInt(2048);
|
||||
out.write(blockLight, layer << 11, 1 << 11);
|
||||
|
||||
out.writeNamedTagName("SkyLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
out.writeInt(2048);
|
||||
out.write(skyLight, layer << 11, 1 << 11);
|
||||
// out.writeNamedTagName("BlockLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
// out.writeInt(2048);
|
||||
// out.write(blockLight, layer << 11, 1 << 11);
|
||||
//
|
||||
// out.writeNamedTagName("SkyLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
// out.writeInt(2048);
|
||||
// out.write(skyLight, layer << 11, 1 << 11);
|
||||
|
||||
|
||||
out.writeEndTag();
|
||||
@ -250,6 +260,15 @@ public class WritableMCAChunk {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
if (deleted) return true;
|
||||
for (boolean hasSection : hasSections) {
|
||||
if (hasSection) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return modified != 0;
|
||||
}
|
||||
@ -272,14 +291,17 @@ public class WritableMCAChunk {
|
||||
return bitMask;
|
||||
}
|
||||
|
||||
public void setTile(int x, int y, int z, CompoundTag tile) {
|
||||
@Override
|
||||
public boolean setTile(int x, int y, int z, CompoundTag tile) {
|
||||
setModified();
|
||||
short pair = MathMan.tripleBlockCoord(x, y, z);
|
||||
if (tile != null) {
|
||||
tiles.put(pair, tile);
|
||||
tiles.put(x, y, z, tile);
|
||||
} else {
|
||||
tiles.remove(pair);
|
||||
if (tiles.remove(x, y, z) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setEntity(CompoundTag entityTag) {
|
||||
@ -289,17 +311,39 @@ public class WritableMCAChunk {
|
||||
entities.put(new UUID(most, least), entityTag);
|
||||
}
|
||||
|
||||
public void setBiome(int x, int z, BiomeType biome) {
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int z) {
|
||||
return BiomeTypes.get(this.biomes[(z << 4) | x] & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType[] getBiomes() {
|
||||
BiomeType[] tmp = new BiomeType[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
tmp[i] = BiomeTypes.get(this.biomes[i] & 0xFF);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 pos, BiomeType biome) {
|
||||
return this.setBiome(pos.getX(), 0, pos.getZ(), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||
setModified();
|
||||
biomes[x + (z << 4)] = biome.getInternalId();
|
||||
biomes[x + (z << 4)] = (byte) biome.getInternalId();
|
||||
return true;
|
||||
}
|
||||
|
||||
public Set<CompoundTag> getEntities() {
|
||||
return new HashSet<>(entities.values());
|
||||
}
|
||||
|
||||
public Map<Short, CompoundTag> getTiles() {
|
||||
return tiles == null ? new HashMap<>() : tiles;
|
||||
@Override
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return tiles == null ? Collections.emptyMap() : tiles;
|
||||
}
|
||||
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
@ -310,94 +354,51 @@ public class WritableMCAChunk {
|
||||
return tiles.get(pair);
|
||||
}
|
||||
|
||||
public boolean doesSectionExist(int cy) {
|
||||
return hasSections[cy];
|
||||
}
|
||||
|
||||
private final int getIndex(int x, int y, int z) {
|
||||
return x | (z << 4) | (y << 8);
|
||||
}
|
||||
|
||||
public int getBlockCombinedId(int x, int y, int z) {
|
||||
public int getBlockOrdinal(int x, int y, int z) {
|
||||
return blocks[x | (z << 4) | (y << 8)];
|
||||
}
|
||||
|
||||
public BiomeType[] getBiomeArray() {
|
||||
return null;
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
int ordinal = getBlockOrdinal(x, y, z);
|
||||
return BlockState.getFromOrdinal(ordinal);
|
||||
}
|
||||
|
||||
public Set<UUID> getEntityRemoves() {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
public void setSkyLight(int x, int y, int z, int value) {
|
||||
setNibble(getIndex(x, y, z), skyLight, value);
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BlockStateHolder holder) {
|
||||
setBlock(x, y, z, holder.getOrdinalChar());
|
||||
holder.applyTileEntity(this, x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBlockLight(int x, int y, int z, int value) {
|
||||
setNibble(getIndex(x, y, z), blockLight, value);
|
||||
}
|
||||
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
if (!hasSections[y >> 4]) {
|
||||
return 0;
|
||||
}
|
||||
return getNibble(getIndex(x, y, z), skyLight);
|
||||
}
|
||||
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
if (!hasSections[y >> 4]) {
|
||||
return 0;
|
||||
}
|
||||
return getNibble(getIndex(x, y, z), blockLight);
|
||||
}
|
||||
|
||||
public void setFullbright() {
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (hasSections[layer]) {
|
||||
Arrays.fill(skyLight, layer << 7, ((layer + 1) << 7), (byte) 255);
|
||||
}
|
||||
@Override
|
||||
public void setBlocks(int layer, char[] data) {
|
||||
int offset = layer << 12;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
blocks[offset + i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void removeLight() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
removeLight(i);
|
||||
@Override
|
||||
public char[] getArray(int layer) {
|
||||
char[] tmp = FaweCache.IMP.SECTION_BITS_TO_CHAR.get();
|
||||
int offset = layer << 12;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
tmp[i] = blocks[offset + i];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public void removeLight(int i) {
|
||||
if (hasSections[i]) {
|
||||
Arrays.fill(skyLight, i << 7, ((i + 1) << 7), (byte) 0);
|
||||
Arrays.fill(blockLight, i << 7, ((i + 1) << 7), (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int getNibble(int index, byte[] array) {
|
||||
int indexShift = index >> 1;
|
||||
if ((index & 1) == 0) {
|
||||
return array[indexShift] & 15;
|
||||
} else {
|
||||
return array[indexShift] >> 4 & 15;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNibble(int index, byte[] array, int value) {
|
||||
int indexShift = index >> 1;
|
||||
byte existing = array[indexShift];
|
||||
int valueShift = value << 4;
|
||||
if (existing == value + valueShift) {
|
||||
return;
|
||||
}
|
||||
if ((index & 1) == 0) {
|
||||
array[indexShift] = (byte) (existing & 240 | value);
|
||||
} else {
|
||||
array[indexShift] = (byte) (existing & 15 | valueShift);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, int combinedId) {
|
||||
blocks[getIndex(x, y, z)] = combinedId;
|
||||
public void setBlock(int x, int y, int z, char ordinal) {
|
||||
blocks[getIndex(x, y, z)] = ordinal;
|
||||
}
|
||||
|
||||
public void setBiome(BiomeType biome) {
|
||||
@ -407,4 +408,9 @@ public class WritableMCAChunk {
|
||||
public void removeEntity(UUID uuid) {
|
||||
entities.remove(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,11 @@ public class BlockVector3ChunkMap<T> implements Map<BlockVector3, T>, IAdaptedMa
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
public T remove(int x, int y, int z) {
|
||||
short key = MathMan.tripleBlockCoord(x, y, z);
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
public boolean contains(int x, int y, int z) {
|
||||
short key = MathMan.tripleBlockCoord(x, y, z);
|
||||
return map.containsKey(key);
|
||||
|
@ -265,9 +265,9 @@ public final class DifferentialArray<T> implements DifferentialCollection<T> {
|
||||
return dataBytes[index];
|
||||
}
|
||||
|
||||
// public char getChar(int index) {
|
||||
// return dataChars[index];
|
||||
// }
|
||||
public char getChar(int index) {
|
||||
return dataChars[index];
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return dataInts[index];
|
||||
|
@ -9,12 +9,12 @@ import java.lang.reflect.Array;
|
||||
* Records changes made through the {@link #set(int, int, int, int)} method<br/>
|
||||
* Changes are not recorded if you edit the raw data
|
||||
*/
|
||||
public final class DifferentialBlockBuffer implements DifferentialCollection<int[][][][][]> {
|
||||
public final class DifferentialBlockBuffer implements DifferentialCollection<char[][][][][]> {
|
||||
|
||||
private final int width, length;
|
||||
private final int t1, t2;
|
||||
private int[][][][][] data;
|
||||
private int[][][][][] changes;
|
||||
private char[][][][][] data;
|
||||
private char[][][][][] changes;
|
||||
|
||||
public DifferentialBlockBuffer(int width, int length) {
|
||||
this.width = width;
|
||||
@ -24,7 +24,7 @@ public final class DifferentialBlockBuffer implements DifferentialCollection<int
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][][][][] get() {
|
||||
public char[][][][][] get() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -116,72 +116,72 @@ public final class DifferentialBlockBuffer implements DifferentialCollection<int
|
||||
changes = null;
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z, int combined) {
|
||||
public void set(int x, int y, int z, char combined) {
|
||||
if (combined == 0) combined = 1;
|
||||
int localX = x & 15;
|
||||
int localZ = z & 15;
|
||||
int chunkX = x >> 4;
|
||||
int chunkZ = z >> 4;
|
||||
if (data == null) {
|
||||
data = new int[t1][][][][];
|
||||
changes = new int[0][][][][];
|
||||
data = new char[t1][][][][];
|
||||
changes = new char[0][][][][];
|
||||
}
|
||||
|
||||
int[][][][] arr = data[chunkZ];
|
||||
char[][][][] arr = data[chunkZ];
|
||||
if (arr == null) {
|
||||
arr = data[chunkZ] = new int[t2][][][];
|
||||
arr = data[chunkZ] = new char[t2][][][];
|
||||
}
|
||||
int[][][] arr2 = arr[chunkX];
|
||||
char[][][] arr2 = arr[chunkX];
|
||||
if (arr2 == null) {
|
||||
arr2 = arr[chunkX] = new int[256][][];
|
||||
arr2 = arr[chunkX] = new char[256][][];
|
||||
}
|
||||
|
||||
int[][] yMap = arr2[y];
|
||||
char[][] yMap = arr2[y];
|
||||
if (yMap == null) {
|
||||
arr2[y] = yMap = new int[16][];
|
||||
arr2[y] = yMap = new char[16][];
|
||||
}
|
||||
boolean newSection;
|
||||
int current;
|
||||
int[] zMap = yMap[localZ];
|
||||
char[] zMap = yMap[localZ];
|
||||
if (zMap == null) {
|
||||
yMap[localZ] = zMap = new int[16];
|
||||
yMap[localZ] = zMap = new char[16];
|
||||
|
||||
if (changes == null) {
|
||||
changes = new int[t1][][][][];
|
||||
changes = new char[t1][][][][];
|
||||
} else if (changes != null && changes.length != 0) {
|
||||
initialChange(changes, chunkX, chunkZ, localX, localZ, y, (int) -combined);
|
||||
initialChange(changes, chunkX, chunkZ, localX, localZ, y, (char) -combined);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (changes == null || changes.length == 0) changes = new int[t1][][][][];
|
||||
appendChange(changes, chunkX, chunkZ, localX, localZ, y, (int) (zMap[localX] - combined));
|
||||
if (changes == null || changes.length == 0) changes = new char[t1][][][][];
|
||||
appendChange(changes, chunkX, chunkZ, localX, localZ, y, (char) (zMap[localX] - combined));
|
||||
}
|
||||
|
||||
zMap[localX] = combined;
|
||||
}
|
||||
|
||||
private void initialChange(int[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, int combined) {
|
||||
int[][][][] arr = src[chunkZ];
|
||||
private void initialChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
|
||||
char[][][][] arr = src[chunkZ];
|
||||
if (arr == null) {
|
||||
src[chunkZ] = new int[0][][][];
|
||||
src[chunkZ] = new char[0][][][];
|
||||
return;
|
||||
} else if (arr.length == 0) return;
|
||||
|
||||
int[][][] arr2 = arr[chunkX];
|
||||
char[][][] arr2 = arr[chunkX];
|
||||
if (arr2 == null) {
|
||||
arr[chunkX] = new int[0][][];
|
||||
arr[chunkX] = new char[0][][];
|
||||
return;
|
||||
} else if (arr2.length == 0) return;
|
||||
|
||||
int[][] yMap = arr2[y];
|
||||
char[][] yMap = arr2[y];
|
||||
if (yMap == null) {
|
||||
arr2[y] = new int[0][];
|
||||
arr2[y] = new char[0][];
|
||||
return;
|
||||
} else if (yMap.length == 0) return;
|
||||
|
||||
int[] zMap = yMap[localZ];
|
||||
char[] zMap = yMap[localZ];
|
||||
if (zMap == null) {
|
||||
yMap[localZ] = new int[0];
|
||||
yMap[localZ] = new char[0];
|
||||
return;
|
||||
} else if (zMap.length == 0) return;
|
||||
|
||||
@ -189,23 +189,23 @@ public final class DifferentialBlockBuffer implements DifferentialCollection<int
|
||||
zMap[localX] = combined;
|
||||
}
|
||||
|
||||
private void appendChange(int[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, int combined) {
|
||||
int[][][][] arr = src[chunkZ];
|
||||
private void appendChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
|
||||
char[][][][] arr = src[chunkZ];
|
||||
if (arr == null || arr.length == 0) {
|
||||
arr = src[chunkZ] = new int[t2][][][];
|
||||
arr = src[chunkZ] = new char[t2][][][];
|
||||
}
|
||||
int[][][] arr2 = arr[chunkX];
|
||||
char[][][] arr2 = arr[chunkX];
|
||||
if (arr2 == null || arr2.length == 0) {
|
||||
arr2 = arr[chunkX] = new int[256][][];
|
||||
arr2 = arr[chunkX] = new char[256][][];
|
||||
}
|
||||
|
||||
int[][] yMap = arr2[y];
|
||||
char[][] yMap = arr2[y];
|
||||
if (yMap == null || yMap.length == 0) {
|
||||
arr2[y] = yMap = new int[16][];
|
||||
arr2[y] = yMap = new char[16][];
|
||||
}
|
||||
int[] zMap = yMap[localZ];
|
||||
char[] zMap = yMap[localZ];
|
||||
if (zMap == null || zMap.length == 0) {
|
||||
yMap[localZ] = zMap = new int[16];
|
||||
yMap[localZ] = zMap = new char[16];
|
||||
}
|
||||
zMap[localX] = combined;
|
||||
}
|
||||
|
@ -220,4 +220,15 @@ public class FastByteArrayOutputStream extends OutputStream {
|
||||
size += index;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
Arrays.fill(buffer, (byte) 0);
|
||||
index = 0;
|
||||
size = 0;
|
||||
buffers.clear();
|
||||
}
|
||||
}
|
@ -122,7 +122,7 @@ public class FaweLocalBlockQueue extends LocalBlockQueue {
|
||||
|
||||
@Override
|
||||
public void refreshChunk(int x, int z) {
|
||||
world.sendChunk(x, z, 0);
|
||||
world.refreshChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,7 +51,7 @@ public class DelegateTextureUtil extends TextureUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
return parent.getIsBlockCloserThanBiome(blockAndBiomeIdOutput, color, biomePriority);
|
||||
}
|
||||
|
||||
|
@ -10,11 +10,11 @@ import java.util.Base64;
|
||||
|
||||
public enum Jars {
|
||||
|
||||
MM_v1_4_0("https://github.com/InventivetalentDev/MapManager/releases/download/1.4.0-SNAPSHOT/MapManager_v1.4.0-SNAPSHOT.jar",
|
||||
"AEO5SKBUGN4YJRS8XGGNLBM2QRZPTI1KF0/1W1URTGA=", 163279),
|
||||
MM_v1_4_0("https://github.com/InventivetalentDev/MapManager/releases/download/1.7.3-SNAPSHOT/MapManager_v1.7.3-SNAPSHOT.jar",
|
||||
"M3YLUQZZ66K2DMVDCYLEU38U3ZKRKHRAXQGGPVKFO6G=", 554831),
|
||||
|
||||
PL_v3_6_0("https://github.com/InventivetalentDev/PacketListenerAPI/releases/download/3.6.0-SNAPSHOT/PacketListenerAPI_v3.6.0-SNAPSHOT.jar",
|
||||
"OYBE75VIU+NNWHRVREBLDARWA+/TBDQZ1RC562QULBA=", 166508),
|
||||
PL_v3_6_0("https://github.com/InventivetalentDev/PacketListenerAPI/releases/download/3.7.3-SNAPSHOT/PacketListenerAPI_v3.7.3-SNAPSHOT.jar",
|
||||
"ETDBRZLN5PRVDFR/MSQDPM6JJER3WQOKHCN8FUXO5ZM=", 167205),
|
||||
|
||||
;
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class RandomTextureUtil extends CachedTextureUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
BlockType block = getNearestBlock(color);
|
||||
int[] mix = biomeMixes.getOrDefault(color, null);
|
||||
if (mix == null) {
|
||||
@ -55,8 +55,8 @@ public class RandomTextureUtil extends CachedTextureUtil {
|
||||
int biomeId = mix[index];
|
||||
int biomeAvColor = mix[3];
|
||||
int blockColor = getColor(block);
|
||||
blockAndBiomeIdOutput[0] = block.getInternalId();
|
||||
blockAndBiomeIdOutput[1] = biomeId;
|
||||
blockAndBiomeIdOutput[0] = block.getDefaultState().getOrdinalChar();
|
||||
blockAndBiomeIdOutput[1] = (char) biomeId;
|
||||
if (colorDistance(biomeAvColor, color) - biomePriority > colorDistance(blockColor, color)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -497,13 +497,13 @@ public class TextureUtil implements TextureHolder {
|
||||
return biomes[biome];
|
||||
}
|
||||
|
||||
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color,
|
||||
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color,
|
||||
int biomePriority) {
|
||||
BlockType block = getNearestBlock(color);
|
||||
TextureUtil.BiomeColor biome = getNearestBiome(color);
|
||||
int blockColor = getColor(block);
|
||||
blockAndBiomeIdOutput[0] = block.getDefaultState().getOrdinalChar();
|
||||
blockAndBiomeIdOutput[1] = biome.id;
|
||||
blockAndBiomeIdOutput[1] = (char) biome.id;
|
||||
if (colorDistance(biome.grassCombined, color) - biomePriority > colorDistance(blockColor,
|
||||
color)) {
|
||||
return true;
|
||||
|
@ -235,8 +235,8 @@ public class WorldWrapper extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int X, int Z, int mask) {
|
||||
parent.sendChunk(X, Z, mask);
|
||||
public void refreshChunk(int X, int Z) {
|
||||
parent.refreshChunk(X, Z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -682,7 +682,12 @@ public class LocalSession implements TextureHolder {
|
||||
public Region getSelection(World world) throws IncompleteRegionException {
|
||||
checkNotNull(world);
|
||||
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
||||
throw new IncompleteRegionException();
|
||||
throw new IncompleteRegionException() {
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
return selector.getRegion();
|
||||
}
|
||||
@ -1288,6 +1293,8 @@ public class LocalSession implements TextureHolder {
|
||||
public void describeCUI(Actor actor) {
|
||||
checkNotNull(actor);
|
||||
|
||||
// TODO preload
|
||||
|
||||
if (!hasCUISupport) {
|
||||
return;
|
||||
}
|
||||
|
@ -74,7 +74,8 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
|
||||
private Location getTarget(Player player) {
|
||||
Location target;
|
||||
Mask mask = getTraceMask();
|
||||
if (this.range < MAX_RANGE) {
|
||||
int range = getRange();
|
||||
if (range < MAX_RANGE) {
|
||||
target = player.getBlockTrace(getRange(), true, mask);
|
||||
} else {
|
||||
target = player.getBlockTrace(MAX_RANGE, false, mask);
|
||||
|
@ -23,6 +23,10 @@ public interface MapMetadatable extends Metadatable {
|
||||
return !getRawMeta().isEmpty();
|
||||
}
|
||||
|
||||
default Object putIfAbsent(String key, Object value) {
|
||||
return getRawMeta().putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metadata for a key.
|
||||
*
|
||||
|
@ -20,7 +20,6 @@
|
||||
package com.sk89q.worldedit.entity;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.brush.visualization.VirtualWorld;
|
||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||
@ -39,7 +38,6 @@ import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
@ -49,11 +47,10 @@ import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
import java.io.File;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import java.io.File;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Represents a player
|
||||
@ -324,6 +321,8 @@ public interface Player extends Entity, Actor {
|
||||
*/
|
||||
<B extends BlockStateHolder<B>> void sendFakeBlock(BlockVector3 pos, @Nullable B block);
|
||||
|
||||
void sendFakeChunk(int chunkX, int chunkZ, Supplier<byte[]> data);
|
||||
|
||||
public Region[] getCurrentRegions();
|
||||
|
||||
Region[] getCurrentRegions(FaweMaskManager.MaskType type);
|
||||
|
@ -41,6 +41,7 @@ import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PlayerProxy extends AbstractPlayerActor {
|
||||
|
||||
@ -211,6 +212,11 @@ public class PlayerProxy extends AbstractPlayerActor {
|
||||
basePlayer.sendFakeBlock(pos, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendFakeChunk(int chunkX, int chunkZ, Supplier<byte[]> data) {
|
||||
basePlayer.sendFakeChunk(chunkX, chunkZ, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String sub) {
|
||||
basePlayer.sendTitle(title, sub);
|
||||
|
@ -148,7 +148,7 @@ public class NullWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int X, int Z, int mask) {
|
||||
public void refreshChunk(int X, int Z) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ public interface World extends Extent, Keyed, IChunkCache<IChunkGet> {
|
||||
* @param chunkZ
|
||||
* @param bitMask
|
||||
*/
|
||||
void sendChunk(final int X, final int Z, final int mask);
|
||||
void refreshChunk(final int X, final int Z);
|
||||
|
||||
@Override
|
||||
IChunkGet get(int x, int z);
|
||||
|
Reference in New Issue
Block a user