mirror of
https://github.com/Minestom/Minestom.git
synced 2025-03-13 07:09:51 +01:00
Start of rotation, chunkbatch is fine, relative batch is not.
This commit is contained in:
parent
0f080b9dc8
commit
e1e2772f4d
@ -82,6 +82,11 @@ public class AbsoluteBlockBatch implements Batch<Runnable> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbsoluteBlockBatch squareRotate(int degree) {
|
||||
throw new IllegalStateException("Rotation not supported on AbsoluteBlockBatch.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies this batch to the given instance.
|
||||
*
|
||||
|
@ -5,6 +5,7 @@ import net.minestom.server.data.Data;
|
||||
import net.minestom.server.instance.BlockModifier;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.block.CustomBlock;
|
||||
import net.minestom.server.utils.Rotation;
|
||||
import net.minestom.server.utils.thread.MinestomThread;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -67,7 +68,47 @@ public interface Batch<Callback> extends BlockModifier {
|
||||
*/
|
||||
void clear();
|
||||
|
||||
// Batch rotate(? );
|
||||
/**
|
||||
* Creates a new batch with the blocks currently inside this batch,
|
||||
* rotated the given amount of degrees.
|
||||
* <p>
|
||||
* At the moment, only rotations of 90 degree increments may be applied.
|
||||
* All rotations will be rounded down to the nearest 90 degree increment.
|
||||
*
|
||||
* @param degrees The number of degrees to rotate
|
||||
* @return A new batch with the rotation applied
|
||||
*
|
||||
* @see #squareRotate(int)
|
||||
*/
|
||||
default Batch<Callback> rotate(int degrees) {
|
||||
return squareRotate((degrees / 90) % 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new batch with the blocks currently inside this batch,
|
||||
* rotated the given {@link Rotation}.
|
||||
* <p>
|
||||
* At the moment, only rotations of 90 degree increments may be applied.
|
||||
* 45 degree rotations will have undefined behavior.
|
||||
*
|
||||
* @param rotation The rotation to apply
|
||||
* @return A new batch with the rotation applied
|
||||
*/
|
||||
default Batch<Callback> rotate(Rotation rotation) {
|
||||
return squareRotate(rotation.ordinal() / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new batch with the blocks currently inside this batch,
|
||||
* rotated the given 'degree'.
|
||||
* <p>
|
||||
* The 'degree' is the number of 90 degree rotations to apply. For
|
||||
* example: degree of 1 = 90°, 2 = 180°, -2 = -180°
|
||||
*
|
||||
* @param degree The degree to rotate
|
||||
* @return A new batch with the rotation applied
|
||||
*/
|
||||
Batch<Callback> squareRotate(int degree);
|
||||
|
||||
/**
|
||||
* Called to apply the batch to the given instance.
|
||||
|
@ -8,6 +8,8 @@ import net.minestom.server.data.Data;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceContainer;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.Rotation;
|
||||
import net.minestom.server.utils.block.CustomBlockUtils;
|
||||
import net.minestom.server.utils.callback.OptionalCallback;
|
||||
import net.minestom.server.utils.chunk.ChunkCallback;
|
||||
@ -19,6 +21,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import static net.minestom.server.utils.MathUtils.isBetween;
|
||||
|
||||
/**
|
||||
* A Batch used when all of the block changed are contained inside a single chunk.
|
||||
* If more than one chunk is needed, use an {@link AbsoluteBlockBatch} instead.
|
||||
@ -32,6 +36,8 @@ import java.util.concurrent.CountDownLatch;
|
||||
* @see Batch
|
||||
*/
|
||||
public class ChunkBatch implements Batch<ChunkCallback> {
|
||||
private static final int HALF_CHUNK_SIZE = 7;
|
||||
// private static final int HALF_CHUNK_SIZE = Chunk.CHUNK_SIZE_X / 2;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ChunkBatch.class);
|
||||
|
||||
// Need to be synchronized manually
|
||||
@ -106,6 +112,50 @@ public class ChunkBatch implements Batch<ChunkCallback> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkBatch rotate(int degrees) {
|
||||
return squareRotate((degrees / 90) % 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkBatch rotate(Rotation rotation) {
|
||||
return squareRotate(rotation.ordinal() / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkBatch squareRotate(int degree) {
|
||||
if ((degree %= 4) < 0) degree += 4;
|
||||
|
||||
final ChunkBatch rotated = new ChunkBatch(this.options);
|
||||
|
||||
synchronized (blocks) {
|
||||
for (long value : blocks) {
|
||||
final short customBlockId = (short) (value & 0xFFFF);
|
||||
final short blockId = (short) ((value >> 16) & 0xFFFF);
|
||||
final int index = (int) ((value >> 32) & 0xFFFFFFFFL);
|
||||
|
||||
Data data = null;
|
||||
if (!blockDataMap.isEmpty()) {
|
||||
synchronized (blockDataMap) {
|
||||
data = blockDataMap.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
final int x = ChunkUtils.blockIndexToChunkPositionX(index);
|
||||
final int y = ChunkUtils.blockIndexToChunkPositionY(index);
|
||||
final int z = ChunkUtils.blockIndexToChunkPositionZ(index);
|
||||
|
||||
final int newX = MathUtils.squareRotateX(degree, x, z) + (isBetween(degree, 1, 2) ? 15 : 0);
|
||||
final int newZ = MathUtils.squareRotateZ(degree, x, z) + (isBetween(degree, 2, 3) ? 15 : 0);
|
||||
|
||||
rotated.setSeparateBlocks(newX, y, newZ, blockId, customBlockId, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rotated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply this batch to chunk (0, 0).
|
||||
*
|
||||
@ -199,6 +249,10 @@ public class ChunkBatch implements Batch<ChunkCallback> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.options.isFullChunk()) {
|
||||
chunk.reset();
|
||||
}
|
||||
|
||||
synchronized (blocks) {
|
||||
for (long block : blocks) {
|
||||
apply(chunk, block, inverse);
|
||||
|
@ -53,6 +53,11 @@ public class ChunkGenerationBatch extends ChunkBatch {
|
||||
throw new IllegalStateException("#clear is not supported for chunk generation batch.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkBatch squareRotate(int degree) {
|
||||
throw new IllegalStateException("Rotation is not supported for chunk generation batch.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChunkBatch apply(@NotNull Instance instance, @NotNull Chunk chunk, @Nullable ChunkCallback callback, boolean safeCallback) {
|
||||
throw new IllegalStateException("#apply is not supported for chunk generation batch.");
|
||||
|
@ -7,6 +7,8 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.Rotation;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -100,6 +102,53 @@ public class RelativeBlockBatch implements Batch<Runnable> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeBlockBatch rotate(int degrees) {
|
||||
return squareRotate((degrees / 90) % 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeBlockBatch rotate(Rotation rotation) {
|
||||
return squareRotate(rotation.ordinal() / 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeBlockBatch squareRotate(int degree) {
|
||||
if ((degree %= 4) < 0) degree += 4;
|
||||
|
||||
final RelativeBlockBatch rotated = new RelativeBlockBatch();
|
||||
rotated.offsetX = this.offsetX;
|
||||
rotated.offsetY = this.offsetY;
|
||||
rotated.offsetZ = this.offsetZ;
|
||||
|
||||
synchronized (blockIdMap) {
|
||||
for (Long2IntMap.Entry entry : blockIdMap.long2IntEntrySet()) {
|
||||
final long pos = entry.getLongKey();
|
||||
final short relZ = (short) (pos & 0xFFFF);
|
||||
final short relY = (short) ((pos >> 16) & 0xFFFF);
|
||||
final short relX = (short) ((pos >> 32) & 0xFFFF);
|
||||
|
||||
final int ids = entry.getIntValue();
|
||||
final short customBlockId = (short) (ids & 0xFFFF);
|
||||
final short blockStateId = (short) ((ids >> 16) & 0xFFFF);
|
||||
|
||||
Data data = null;
|
||||
if (!blockDataMap.isEmpty()) {
|
||||
synchronized (blockDataMap) {
|
||||
data = blockDataMap.get(pos);
|
||||
}
|
||||
}
|
||||
|
||||
final int finalX = MathUtils.squareRotateX(degree, relX, relZ);
|
||||
final int finalZ = MathUtils.squareRotateZ(degree, relX, relZ);
|
||||
|
||||
rotated.setSeparateBlocks(finalX, relY, finalZ, blockStateId, customBlockId, data);
|
||||
}
|
||||
}
|
||||
|
||||
return rotated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies this batch to the given instance at the origin (0, 0, 0) of the instance.
|
||||
*
|
||||
|
@ -94,4 +94,14 @@ public final class MathUtils {
|
||||
public static double mod(final double a, final double b) {
|
||||
return (a % b + b) % b;
|
||||
}
|
||||
|
||||
private static final int[] MAGIC_TRIG = {0, 1, 0, -1};
|
||||
|
||||
public static int squareRotateX(int degree, int x, int z) {
|
||||
return MAGIC_TRIG[(degree + 1) % 4]*x - MAGIC_TRIG[degree]*z;
|
||||
}
|
||||
|
||||
public static int squareRotateZ(int degree, int x, int z) {
|
||||
return MAGIC_TRIG[degree]*x + MAGIC_TRIG[(degree + 1) % 4]*z;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class CubeBatchCommand extends Command {
|
||||
|
||||
@ -37,8 +39,55 @@ public class CubeBatchCommand extends Command {
|
||||
Player player = sender.asPlayer();
|
||||
InstanceContainer instance = (InstanceContainer) player.getInstance();
|
||||
|
||||
RelativeBlockBatch rotBatch = new RelativeBlockBatch();
|
||||
for (int x = 0; x < 50; x += 2) {
|
||||
for (int y = 0; y < 50; y += 2) {
|
||||
for (int z = 0; z < 10; z += 2) {
|
||||
rotBatch.setBlockStateId(x, y, z, Block.BLUE_CONCRETE.getBlockId());
|
||||
}
|
||||
}
|
||||
}
|
||||
rotBatch.apply(instance, 50, 50, 50, null);
|
||||
rotBatch.rotate(90).apply(instance, 50, 50, 50, null);
|
||||
rotBatch.rotate(180).apply(instance, 50, 50, 50, null);
|
||||
rotBatch.rotate(270).apply(instance, 50, 50, 50, null);
|
||||
|
||||
// ChunkBatch rotBatch = new ChunkBatch(new BatchOption().setFullChunk(true));
|
||||
// for (int x = 0; x < 16; x += 2) {
|
||||
// for (int y = 0; y < 50; y += 2) {
|
||||
// for (int z = 0; z < 8; z += 2) {
|
||||
// rotBatch.setBlockStateId(x, y + 50, z, Block.BLUE_CONCRETE.getBlockId());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// rotBatch.apply(instance, 1, i * 2, null);
|
||||
// rotBatch = rotBatch.squareRotate(1);
|
||||
// }
|
||||
|
||||
// for (int x = 0; x < 10; x++) {
|
||||
// for (int z = 0; z < 10; z++) {
|
||||
// final int chunkX = x - 5;
|
||||
// final int chunkZ = z - 5;
|
||||
//
|
||||
// AtomicReference<ChunkBatch> b = new AtomicReference<>(rotBatch.rotate(0));
|
||||
// MinecraftServer.getSchedulerManager().buildTask(() -> {
|
||||
// final ChunkBatch current = b.get();
|
||||
// final ChunkBatch next = current.rotate(90);
|
||||
// b.set(next);
|
||||
// next.apply(instance, chunkX, chunkZ, null);
|
||||
//
|
||||
// }).delay(10, TimeUnit.TICK).repeat(ThreadLocalRandom.current().nextInt(10) + 1, TimeUnit.TICK).schedule();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// applyChunkShape(instance);
|
||||
applyBlockShape(instance);
|
||||
// applyBlockShape(instance);
|
||||
|
||||
// AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user