<commit_before>package com.cjburkey.claimchunk.chunk;

import com.cjburkey.claimchunk.ClaimChunk;
import com.cjburkey.claimchunk.data.newdata.IClaimChunkDataHandler;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Player;

public final class ChunkHandler {

    private final IClaimChunkDataHandler dataHandler;
    private final ClaimChunk claimChunk;

    private static final int MAX_FILL_RECUSION = 8;
    private static final int MAX_FILL_AREA = 16;

    public ChunkHandler(IClaimChunkDataHandler dataHandler, ClaimChunk claimChunk) {
        this.dataHandler = dataHandler;
        this.claimChunk = claimChunk;
    }

    /**
     * Claims several chunks at once for a player.
     * This method is very unsafe at it's own as it does not test whether
     * the player can actually claim that chunk. This means that ownership can
     * be overridden. And the player can go over it's quota
     *
     * @param chunks The chunks to claim
     * @param player The player that claims these chunks
     * @return True if the collection was not empty, false otherwise
     */
    private boolean claimAll(Collection<ChunkPos> chunks, UUID player) {
        if (chunks == null) {
            return false;
        }
        boolean b = false;
        for (ChunkPos chunk : chunks) {
            dataHandler.addClaimedChunk(chunk, player);
            b = true;
        }
        return b;
    }

    /**
     * Claims a specific chunk for a player if that chunk is not already owned.
     * This method doesn't do any checks other than previous ownership.
     * It is not generally safe to use this method. Other public API methods
     * should be used to claim chunks.
     *
     * @param world     The current world.
     * @param x         The chunk x-coord.
     * @param z         The chunk z-coord.
     * @param player    The player for whom to claim the chunk.
     * @param floodfill Whether or not flood filling should be attempted
     * @return The chunk position variable or {@code null} if the chunk is already claimed
     */
    public ChunkPos claimChunk(String world, int x, int z, UUID player, boolean floodfill) {
        if (isClaimed(world, x, z)) {
            // If the chunk is already claimed, return null
            return null;
        }

        // Create a chunk position representation
        ChunkPos pos = new ChunkPos(world, x, z);

        // Add the chunk to the claimed chunk
        dataHandler.addClaimedChunk(pos, player);

        if (floodfill) { // Optionally attempt flood filling
            int amountClaimed = 0;
            for (int x2 = -1; x2 <= 1; x2++) {
                for (int y2 = -1; y2 <= 1; y2++) {
                    if (player.equals(getOwner(new ChunkPos(world, x+ x2, z + y2)))) {
                        amountClaimed++;
                    }
                }
            }
            if (amountClaimed > 1
                    && (claimAll(fillClaim(world, x - 1, z, MAX_FILL_AREA, player), player)
                    || claimAll(fillClaim(world, x + 1, z, MAX_FILL_AREA, player), player)
                    || claimAll(fillClaim(world, x, z - 1, MAX_FILL_AREA, player), player)
                    || claimAll(fillClaim(world, x, z + 1, MAX_FILL_AREA, player), player))) {
                // Maybe message the player about this or something
            }
        }

        // Return the chunk position
        return pos;
    }

    private void fillClaimInto(String world, int x, int z, int recursions, int maxSize, UUID player, Collection<ChunkPos> collector) {
        if (recursions == 0 || collector.size() > maxSize) {
            return;
        }
        ChunkPos claimingPosition = new ChunkPos(world, x, z);
        if (collector.contains(claimingPosition) || getOwner(claimingPosition) != null) {
            return;
        }
        collector.add(claimingPosition);
        fillClaimInto(world, x - 1, z, --recursions, maxSize, player, collector);
        fillClaimInto(world, x + 1, z, recursions, maxSize, player, collector);
        fillClaimInto(world, x, z - 1, recursions, maxSize, player, collector);
        fillClaimInto(world, x, z + 1, recursions, maxSize, player, collector);
    }

    private Collection<ChunkPos> fillClaim(String world, int x, int z, int maxFillArea, UUID player) {
        HashSet<ChunkPos> positions = new HashSet<>(maxFillArea);
        fillClaimInto(world, x, z, MAX_FILL_RECUSION, maxFillArea, player, positions);
        if (positions.size() > maxFillArea) {
            return null;
        }
        return positions;
    }

    /**
     * Claims a specific chunk for a player if that chunk is not already owned.
     * This method doesn't do any checks other than previous ownership.
     * It is not generally safe to use this method. Other public API methods<commit_msg>Some improvements to the claim filling<commit_after>package com.cjburkey.claimchunk.chunk;

import com.cjburkey.claimchunk.ClaimChunk;
import com.cjburkey.claimchunk.data.newdata.IClaimChunkDataHandler;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Player;

public final class ChunkHandler {

    private final IClaimChunkDataHandler dataHandler;
    private final ClaimChunk claimChunk;

    private static final int MAX_FILL_RECUSION = 8;
    private static final int MAX_FILL_AREA = 16;

    public ChunkHandler(IClaimChunkDataHandler dataHandler, ClaimChunk claimChunk) {
        this.dataHandler = dataHandler;
        this.claimChunk = claimChunk;
    }

    /**
     * Claims several chunks at once for a player.
     * This method is very unsafe at it's own as it does not test whether
     * the player can actually claim that chunk. This means that ownership can
     * be overridden. And the player can go over it's quota
     *
     * @param chunks The chunks to claim
     * @param player The player that claims these chunks
     * @return True if the collection was not empty, false otherwise
     */
    private boolean claimAll(Collection<ChunkPos> chunks, UUID player) {
        if (chunks == null) {
            return false;
        }
        boolean b = false;
        for (ChunkPos chunk : chunks) {
            dataHandler.addClaimedChunk(chunk, player);
            b = true;
        }
        return b;
    }

    /**
     * Claims a specific chunk for a player if that chunk is not already owned.
     * This method doesn't do any checks other than previous ownership.
     * It is not generally safe to use this method. Other public API methods
     * should be used to claim chunks.
     *
     * @param world     The current world.
     * @param x         The chunk x-coord.
     * @param z         The chunk z-coord.
     * @param player    The player for whom to claim the chunk.
     * @param floodfill Whether or not flood filling should be attempted
     * @return The chunk position variable or {@code null} if the chunk is already claimed
     */
    public ChunkPos claimChunk(String world, int x, int z, UUID player, boolean floodfill) {
        if (isClaimed(world, x, z)) {
            // If the chunk is already claimed, return null
            return null;
        }

        // Create a chunk position representation
        ChunkPos pos = new ChunkPos(world, x, z);

        // Add the chunk to the claimed chunk
        dataHandler.addClaimedChunk(pos, player);

        if (floodfill) { // Optionally attempt flood filling
            int amountClaimed = 0;
            for (int x2 = -1; x2 <= 1; x2++) {
                for (int y2 = -1; y2 <= 1; y2++) {
                    if (player.equals(getOwner(new ChunkPos(world, x+ x2, z + y2)))) {
                        amountClaimed++;
                    }
                }
            }
            if (amountClaimed > 1
                    && (claimAll(fillClaim(world, x - 1, z, MAX_FILL_AREA, player), player)
                    || claimAll(fillClaim(world, x + 1, z, MAX_FILL_AREA, player), player)
                    || claimAll(fillClaim(world, x, z - 1, MAX_FILL_AREA, player), player)
                    || claimAll(fillClaim(world, x, z + 1, MAX_FILL_AREA, player), player))) {
                // Maybe message the player about this or something
            }
        }

        // Return the chunk position
        return pos;
    }

    /**
     * Fills claims near the given positions that are connected to the current claim via unclaimed claims.
     * If it hits a claim that was claimed by any other player, this method will abort and will return "false",
     * but will still have populated the collection to some extent. It will also abort the same way if the
     * maxSize has been reached or when recursions is equal 0. Notes that the chunks are not claimed, this method
     * needs to be performed later
     *
     * @param world The world name, used for claim checking
     * @param x the x-position of the current chunk
     * @param z the z-position of the current chunk
     * @param recursions The maximum amount of recursions remaining
     * @param maxSize The maximum size of the collection until the method aborts
     * @param player The player to claim the chunks for
     * @param collector The collection to drop the chunks into
     * @return Whether the method completed as intended, false if it aborted mid-way
     */
    private boolean fillClaimInto(String world, int x, int z, int recursions, int maxSize, UUID player, Collection<ChunkPos> collector) {
        if (recursions == 0 || collector.size() > maxSize) {
            return false;
        }
        ChunkPos claimingPosition = new ChunkPos(world, x, z);
        if (collector.contains(claimingPosition)) {
            return true;
        }
        UUID owner = getOwner(claimingPosition);
        if (owner != null) {
            if (owner.equals(player)) {
                return true; // Hit player claim, do not claim it
            } else {
                return false; // Hit non-player claim, abort
            }
        }
        collector.add(claimingPosition);
        return fillClaimInto(world, x - 1, z, --recursions, maxSize, player, collector)
                && fillClaimInto(world, x + 1, z, recursions, maxSize, player, collector)
                && fillClaimInto(world, x, z - 1, recursions, maxSize, player, collector)
                && fillClaimInto(world, x, z + 1, recursions, maxSize, player, collector);
    }

    private Collection<ChunkPos> fillClaim(String world, int x, int z, int maxFillArea, UUID player) {
        HashSet<ChunkPos> positions = new HashSet<>(maxFillArea);
        if (!fillClaimInto(world, x, z, MAX_FILL_RECUSION, maxFillArea, player, positions)) {
            return null;
        }
        return positions;
    }

    /**
     * Claims a specific chunk for a player if that chunk is not already owned.
     * This method doesn't do any checks other than previous ownership.
     * It is not generally safe to use this method. Other public API methods
{'fraction_non_alphanumeric': 0.0819158460161146, 'fraction_numerical': 0.0047448522829006265, 'mean_word_length': 2.263511539585159, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4553964', 'n_tokens_mistral': 3120, 'n_tokens_neox': 2974, 'n_words': 1165}