mirror of
https://github.com/Minestom/Minestom.git
synced 2024-09-29 15:07:36 +02:00
219 lines
7.7 KiB
Java
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);
|
||
|
}
|
||
|
}
|
||
|
}
|