Minestom/src/main/java/net/minestom/server/snapshot/SnapshotImpl.java
TheMode fdd3e2c53c Seal snapshot interfaces
Signed-off-by: TheMode <themode@outlook.fr>
2022-05-04 13:25:24 +02:00

219 lines
7.7 KiB
Java

package net.minestom.server.snapshot;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.GameMode;
import net.minestom.server.instance.Section;
import net.minestom.server.instance.block.Block;
import net.minestom.server.tag.Tag;
import net.minestom.server.tag.TagReadable;
import net.minestom.server.utils.collection.IntMappedArray;
import net.minestom.server.utils.collection.MappedCollection;
import net.minestom.server.world.DimensionType;
import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.UnknownNullability;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import static net.minestom.server.utils.chunk.ChunkUtils.*;
@ApiStatus.Internal
public final class SnapshotImpl {
public record Server(Collection<InstanceSnapshot> instances,
Int2ObjectOpenHashMap<AtomicReference<EntitySnapshot>> entityRefs) implements ServerSnapshot {
@Override
public @NotNull Collection<EntitySnapshot> entities() {
return MappedCollection.plainReferences(entityRefs.values());
}
@Override
public @UnknownNullability EntitySnapshot entity(int id) {
var ref = entityRefs.get(id);
return ref != null ? ref.getPlain() : null;
}
}
public record Instance(AtomicReference<ServerSnapshot> serverRef,
DimensionType dimensionType, long worldAge, long time,
Map<Long, AtomicReference<ChunkSnapshot>> chunksMap,
int[] entitiesIds,
TagReadable tagReadable) implements InstanceSnapshot {
@Override
public @Nullable ChunkSnapshot chunk(int chunkX, int chunkZ) {
var ref = chunksMap.get(getChunkIndex(chunkX, chunkZ));
return Objects.requireNonNull(ref, "Chunk not found").getPlain();
}
@Override
public @NotNull Collection<@NotNull ChunkSnapshot> chunks() {
return MappedCollection.plainReferences(chunksMap.values());
}
@Override
public @NotNull Collection<EntitySnapshot> entities() {
return new IntMappedArray<>(entitiesIds, id -> server().entity(id));
}
@Override
public @NotNull ServerSnapshot server() {
return serverRef.getPlain();
}
@Override
public <T> @UnknownNullability T getTag(@NotNull Tag<T> tag) {
return tagReadable.getTag(tag);
}
}
public record Chunk(int minSection, int chunkX, int chunkZ,
Section[] sections,
Int2ObjectOpenHashMap<Block> blockEntries,
int[] entitiesIds,
AtomicReference<InstanceSnapshot> instanceRef,
TagReadable tagReadable) implements ChunkSnapshot {
@Override
public @UnknownNullability Block getBlock(int x, int y, int z, @NotNull Condition condition) {
// Verify if the block object is present
if (condition != Condition.TYPE) {
final Block entry = !blockEntries.isEmpty() ?
blockEntries.get(getBlockIndex(x, y, z)) : null;
if (entry != null || condition == Condition.CACHED) {
return entry;
}
}
// Retrieve the block from state id
final Section section = sections[getChunkCoordinate(y) - minSection];
final int blockStateId = section.blockPalette()
.get(toSectionRelativeCoordinate(x), toSectionRelativeCoordinate(y), toSectionRelativeCoordinate(z));
return Objects.requireNonNullElse(Block.fromStateId((short) blockStateId), Block.AIR);
}
@Override
public @NotNull Biome getBiome(int x, int y, int z) {
final Section section = sections[getChunkCoordinate(y) - minSection];
final int id = section.biomePalette()
.get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4);
return MinecraftServer.getBiomeManager().getById(id);
}
@Override
public <T> @UnknownNullability T getTag(@NotNull Tag<T> tag) {
return tagReadable.getTag(tag);
}
@Override
public @NotNull InstanceSnapshot instance() {
return instanceRef.getPlain();
}
@Override
public @NotNull Collection<@NotNull EntitySnapshot> entities() {
return new IntMappedArray<>(entitiesIds, id -> instance().server().entity(id));
}
}
public record Entity(EntityType type, UUID uuid, int id, Pos position, Vec velocity,
AtomicReference<InstanceSnapshot> instanceRef, int chunkX, int chunkZ,
int[] viewersId, int[] passengersId, int vehicleId,
TagReadable tagReadable) implements EntitySnapshot {
@Override
public <T> @UnknownNullability T getTag(@NotNull Tag<T> tag) {
return tagReadable.getTag(tag);
}
@Override
public @NotNull InstanceSnapshot instance() {
return instanceRef.getPlain();
}
@Override
public @NotNull ChunkSnapshot chunk() {
return Objects.requireNonNull(instance().chunk(chunkX, chunkZ));
}
@Override
public @NotNull Collection<@NotNull PlayerSnapshot> viewers() {
return new IntMappedArray<>(viewersId, id -> (PlayerSnapshot) instance().server().entity(id));
}
@Override
public @NotNull Collection<@NotNull EntitySnapshot> passengers() {
return new IntMappedArray<>(passengersId, id -> instance().server().entity(id));
}
@Override
public @Nullable EntitySnapshot vehicle() {
if (vehicleId == -1) return null;
return instance().server().entity(vehicleId);
}
}
public record Player(EntitySnapshot snapshot, String username,
GameMode gameMode) implements PlayerSnapshot {
@Override
public @NotNull EntityType type() {
return snapshot.type();
}
@Override
public @NotNull UUID uuid() {
return snapshot.uuid();
}
@Override
public int id() {
return snapshot.id();
}
@Override
public @NotNull Pos position() {
return snapshot.position();
}
@Override
public @NotNull Vec velocity() {
return snapshot.velocity();
}
@Override
public @NotNull InstanceSnapshot instance() {
return snapshot.instance();
}
@Override
public @NotNull ChunkSnapshot chunk() {
return snapshot.chunk();
}
@Override
public @NotNull Collection<@NotNull PlayerSnapshot> viewers() {
return snapshot.viewers();
}
@Override
public @NotNull Collection<@NotNull EntitySnapshot> passengers() {
return snapshot.passengers();
}
@Override
public @Nullable EntitySnapshot vehicle() {
return snapshot.vehicle();
}
@Override
public <T> @UnknownNullability T getTag(@NotNull Tag<T> tag) {
return snapshot.getTag(tag);
}
}
}