Search in sources :

Example 1 with MinecraftPlayer

use of org.valkyrienskies.mod.common.util.MinecraftPlayer in project Valkyrien-Skies-2 by ValkyrienSkies.

the class MixinServerWorld method updateVSPlayerWrappers.

@Unique
private void updateVSPlayerWrappers() {
    // First add new player objects
    players.forEach(player -> {
        final UUID playerID = player.getUuid();
        if (!vsPlayerWrappers.containsKey(playerID)) {
            final MinecraftPlayer playerWrapper = new MinecraftPlayer(player, playerID);
            vsPlayerWrappers.put(playerID, playerWrapper);
        }
    });
    // Then remove removed player objects
    // First make a set of all current player IDs, so we can check if a player is online in O(1) time.
    final Set<UUID> currentPlayerIDs = new HashSet<>();
    players.forEach(player -> currentPlayerIDs.add(player.getUuid()));
    // Then remove any old player wrappers whose players are no longer here.
    vsPlayerWrappers.entrySet().removeIf(entry -> !currentPlayerIDs.contains(entry.getKey()));
}
Also used : MinecraftPlayer(org.valkyrienskies.mod.common.util.MinecraftPlayer) UUID(java.util.UUID) HashSet(java.util.HashSet) Unique(org.spongepowered.asm.mixin.Unique)

Example 2 with MinecraftPlayer

use of org.valkyrienskies.mod.common.util.MinecraftPlayer in project Valkyrien-Skies-2 by ValkyrienSkies.

the class MixinServerWorld method postTick.

@Inject(method = "tick", at = @At("TAIL"))
private void postTick(final BooleanSupplier shouldKeepTicking, final CallbackInfo ci) {
    // First update the IPlayer wrapper list
    updateVSPlayerWrappers();
    // Find newly loaded chunks
    final List<ChunkHolder> loadedChunksList = Lists.newArrayList(((ThreadedAnvilChunkStorageAccessor) serverChunkManager.threadedAnvilChunkStorage).callEntryIterator());
    // Create DenseVoxelShapeUpdate for new loaded chunks
    final List<IVoxelShapeUpdate> newLoadedChunks = new ArrayList<>();
    for (final ChunkHolder chunkHolder : loadedChunksList) {
        final Optional<WorldChunk> worldChunkOptional = chunkHolder.getTickingFuture().getNow(ChunkHolder.UNLOADED_WORLD_CHUNK).left();
        if (worldChunkOptional.isPresent()) {
            final WorldChunk worldChunk = worldChunkOptional.get();
            final int chunkX = worldChunk.getPos().x;
            final int chunkZ = worldChunk.getPos().z;
            final ChunkSection[] chunkSections = worldChunk.getSectionArray();
            // For now just assume chunkY goes from 0 to 16
            for (int chunkY = 0; chunkY < 16; chunkY++) {
                final ChunkSection chunkSection = chunkSections[chunkY];
                final Vector3ic chunkPos = new Vector3i(chunkX, chunkY, chunkZ);
                if (!knownChunkRegions.contains(chunkPos)) {
                    if (chunkSection != null) {
                        // Add this chunk to the ground rigid body
                        final DenseVoxelShapeUpdate voxelShapeUpdate = VSGameUtilsKt.toDenseVoxelUpdate(chunkSection, chunkPos);
                        newLoadedChunks.add(voxelShapeUpdate);
                    } else {
                        final EmptyVoxelShapeUpdate emptyVoxelShapeUpdate = new EmptyVoxelShapeUpdate(chunkPos.x(), chunkPos.y(), chunkPos.z(), false, false);
                        newLoadedChunks.add(emptyVoxelShapeUpdate);
                    }
                    knownChunkRegions.add(chunkPos);
                }
            }
        }
    }
    // Then tick the ship world
    shipObjectWorld.tickShips(newLoadedChunks);
    // Send ships to clients
    final IVSPacket shipDataPacket = VSPacketShipDataList.Companion.create(shipObjectWorld.getQueryableShipData().iterator());
    for (final ServerPlayerEntity playerEntity : players) {
        VSNetworking.shipDataPacketToClientSender.sendToClient(shipDataPacket, playerEntity);
    }
    // Then determine the chunk watch/unwatch tasks, and then execute them
    final ImmutableList<IPlayer> playersToTick = ImmutableList.copyOf(vsPlayerWrappers.values());
    final Pair<Spliterator<ChunkWatchTask>, Spliterator<ChunkUnwatchTask>> chunkWatchAndUnwatchTasksPair = shipObjectWorld.tickShipChunkLoading(playersToTick);
    // Use Spliterator instead of iterators so that we can multi thread the execution of these tasks
    final Spliterator<ChunkWatchTask> chunkWatchTasks = chunkWatchAndUnwatchTasksPair.getFirst();
    final Spliterator<ChunkUnwatchTask> chunkUnwatchTasks = chunkWatchAndUnwatchTasksPair.getSecond();
    // But for now just do it single threaded
    chunkWatchTasks.forEachRemaining(chunkWatchTask -> {
        System.out.println("Watch task for " + chunkWatchTask.getChunkX() + " : " + chunkWatchTask.getChunkZ());
        final Packet<?>[] chunkPacketBuffer = new Packet[2];
        final ChunkPos chunkPos = new ChunkPos(chunkWatchTask.getChunkX(), chunkWatchTask.getChunkZ());
        // TODO: Move this somewhere else
        serverChunkManager.setChunkForced(chunkPos, true);
        for (final IPlayer player : chunkWatchTask.getPlayersNeedWatching()) {
            final MinecraftPlayer minecraftPlayer = (MinecraftPlayer) player;
            final ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity) minecraftPlayer.getPlayerEntityReference().get();
            if (serverPlayerEntity != null) {
                ((ThreadedAnvilChunkStorageAccessor) serverChunkManager.threadedAnvilChunkStorage).callSendWatchPackets(serverPlayerEntity, chunkPos, chunkPacketBuffer, false, true);
            }
        }
        chunkWatchTask.onExecuteChunkWatchTask();
    });
    chunkUnwatchTasks.forEachRemaining(chunkUnwatchTask -> {
        System.out.println("Unwatch task for " + chunkUnwatchTask.getChunkX() + " : " + chunkUnwatchTask.getChunkZ());
        chunkUnwatchTask.onExecuteChunkUnwatchTask();
    });
}
Also used : IPlayer(org.valkyrienskies.core.game.IPlayer) ChunkWatchTask(org.valkyrienskies.core.chunk_tracking.ChunkWatchTask) ChunkHolder(net.minecraft.server.world.ChunkHolder) EmptyVoxelShapeUpdate(org.valkyrienskies.physics_api.voxel_updates.EmptyVoxelShapeUpdate) ArrayList(java.util.ArrayList) ChunkUnwatchTask(org.valkyrienskies.core.chunk_tracking.ChunkUnwatchTask) WorldChunk(net.minecraft.world.chunk.WorldChunk) Vector3ic(org.joml.Vector3ic) MinecraftPlayer(org.valkyrienskies.mod.common.util.MinecraftPlayer) IVoxelShapeUpdate(org.valkyrienskies.physics_api.voxel_updates.IVoxelShapeUpdate) ChunkPos(net.minecraft.util.math.ChunkPos) ThreadedAnvilChunkStorageAccessor(org.valkyrienskies.mod.mixin.accessors.server.world.ThreadedAnvilChunkStorageAccessor) Spliterator(java.util.Spliterator) DenseVoxelShapeUpdate(org.valkyrienskies.physics_api.voxel_updates.DenseVoxelShapeUpdate) Packet(net.minecraft.network.Packet) IVSPacket(org.valkyrienskies.core.networking.IVSPacket) ServerPlayerEntity(net.minecraft.server.network.ServerPlayerEntity) Vector3i(org.joml.Vector3i) IVSPacket(org.valkyrienskies.core.networking.IVSPacket) ChunkSection(net.minecraft.world.chunk.ChunkSection) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 3 with MinecraftPlayer

use of org.valkyrienskies.mod.common.util.MinecraftPlayer in project Valkyrien-Skies-2 by ValkyrienSkies.

the class MixinThreadedAnvilChunkStorage method postGetPlayersWatchingChunk.

/**
 * Force the game send chunk update packets to players watching ship chunks.
 *
 * @author Tri0de
 */
@Inject(method = "getPlayersWatchingChunk", at = @At("TAIL"), cancellable = true)
private void postGetPlayersWatchingChunk(final ChunkPos chunkPos, final boolean onlyOnWatchDistanceEdge, final CallbackInfoReturnable<Stream<ServerPlayerEntity>> cir) {
    final Iterator<IPlayer> playersWatchingShipChunk = VSGameUtilsKt.getShipObjectWorld(world).getIPlayersWatchingShipChunk(chunkPos.x, chunkPos.z);
    if (!playersWatchingShipChunk.hasNext()) {
        // No players watching this ship chunk, so we don't need to modify anything
        return;
    }
    final Stream<ServerPlayerEntity> oldReturnValue = cir.getReturnValue();
    final Set<ServerPlayerEntity> watchingPlayers = new HashSet<>();
    oldReturnValue.forEach(watchingPlayers::add);
    playersWatchingShipChunk.forEachRemaining(iPlayer -> {
        final MinecraftPlayer minecraftPlayer = (MinecraftPlayer) iPlayer;
        final ServerPlayerEntity playerEntity = (ServerPlayerEntity) minecraftPlayer.getPlayerEntityReference().get();
        if (playerEntity != null) {
            watchingPlayers.add(playerEntity);
        }
    });
    final Stream<ServerPlayerEntity> newReturnValue = watchingPlayers.stream();
    cir.setReturnValue(newReturnValue);
}
Also used : IPlayer(org.valkyrienskies.core.game.IPlayer) MinecraftPlayer(org.valkyrienskies.mod.common.util.MinecraftPlayer) ServerPlayerEntity(net.minecraft.server.network.ServerPlayerEntity) HashSet(java.util.HashSet) Inject(org.spongepowered.asm.mixin.injection.Inject)

Aggregations

MinecraftPlayer (org.valkyrienskies.mod.common.util.MinecraftPlayer)3 HashSet (java.util.HashSet)2 ServerPlayerEntity (net.minecraft.server.network.ServerPlayerEntity)2 Inject (org.spongepowered.asm.mixin.injection.Inject)2 IPlayer (org.valkyrienskies.core.game.IPlayer)2 ArrayList (java.util.ArrayList)1 Spliterator (java.util.Spliterator)1 UUID (java.util.UUID)1 Packet (net.minecraft.network.Packet)1 ChunkHolder (net.minecraft.server.world.ChunkHolder)1 ChunkPos (net.minecraft.util.math.ChunkPos)1 ChunkSection (net.minecraft.world.chunk.ChunkSection)1 WorldChunk (net.minecraft.world.chunk.WorldChunk)1 Vector3i (org.joml.Vector3i)1 Vector3ic (org.joml.Vector3ic)1 Unique (org.spongepowered.asm.mixin.Unique)1 ChunkUnwatchTask (org.valkyrienskies.core.chunk_tracking.ChunkUnwatchTask)1 ChunkWatchTask (org.valkyrienskies.core.chunk_tracking.ChunkWatchTask)1 IVSPacket (org.valkyrienskies.core.networking.IVSPacket)1 ThreadedAnvilChunkStorageAccessor (org.valkyrienskies.mod.mixin.accessors.server.world.ThreadedAnvilChunkStorageAccessor)1