<commit_before>package net.galaxygaming.selection;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.logging.Level;

import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;

import com.google.common.collect.Lists;
import net.galaxygaming.dispenser.game.Game;
import net.galaxygaming.dispenser.task.GameRunnable;

/**
 * Used for areas that should be restored
 * sometime during or after the game
 */
public class RegenableSelection {    
    private static final int MAX_BLOCKS_PER_INTERVAL = 250;
    private static final long INTERVAL_LENGTH = 20;
    
    private final Selection selection;
    private final Game game;
    private final String regionName;
    private byte[] blocks;
    private byte[] data;

    /**
     * @param game game this selection belongs to
     * @param regionName name of this region
     * @param selection selection specifying area
     */
    public RegenableSelection(Game game, String regionName, Selection selection) {
        this.selection = selection;
        this.game = game;
        this.regionName = regionName;
        
        reloadBlockData();
    }
    
    private RegenableSelection(Game game, String regionName, Selection selection, byte[] blocks, byte[] data) {
        this.selection = selection;
        this.game = game;
        this.regionName = regionName;
        
        this.blocks = blocks;
        this.data = data;
    }   
    
    /**
     * Updates the blocks saved by this selection with the blocks
     * currently in the world in the selection.
     */
    @SuppressWarnings("deprecation")
    public void reloadBlockData() {
        Location min = selection.getMin();
        Location max = selection.getMax();
        
        int Lx = max.getBlockX() - min.getBlockX() + 1;
        int Ly = max.getBlockY() - min.getBlockY() + 1;
        int Lz = max.getBlockZ() - min.getBlockZ() + 1;
        
        blocks = new byte[Lx*Ly*Lz];
        data = new byte[(int) Math.ceil((double) blocks.length / 2)];
        
        for (int i = 0; i < Lx; i++) {
            int x = i + min.getBlockX();
            for (int j = 0; j < Ly; j++) {
                int y = j + min.getBlockY();
                for (int k = 0; k < Lz; k++) {
                    int z = k + min.getBlockZ();
                    int index = i + j * Lx + k * Lx * Ly;
                    Block b = new Location(min.getWorld(), x, y, z).getBlock();
                    blocks[index] = (byte) b.getTypeId();
                    byte d = data[index / 2];                    
                    data[index / 2] = (byte) (d + (b.getData() << (4 * (index % 2))));
                }
            }
        }
        
        save();
    }
    
    /**
     * Gets the underlying {@link Selection} that defines the volume
     * controlled by this class
     * @return selection
     */
    public Selection getSelection() {
        return selection;
    }
    
    /**
     * Regenerates this selection with the stored block data.
     * This method uses block states in a update fast method
     * meaning no lighting updates are performed. It is also
     * processed over asynchronously over multiple seconds.
     */
    @SuppressWarnings("deprecation")
    public void regen() {
        // TODO: Check thread safety, cannot run at same time as reloadBlockData()
        
        new GameRunnable() {
            @Override
            public void run() {
                Location min = selection.getMin();
                Location max = selection.getMax();
                World world = min.getWorld();
                
                int Lx = max.getBlockX() - min.getBlockX() + 1;
                int Ly = max.getBlockY() - min.getBlockY() + 1;
                int Lz = max.getBlockZ() - min.getBlockZ() + 1;
                
                if (blocks == null || data == null || blocks.length != Lx*Ly*Lz || data.length != Lx*Ly*Lz/2) {
                    game.getLogger().log(Level.WARNING, "Tried to regen but block data is wrong length: " + regionName);
                    return;
                }
                
                List<List<BlockState>> blockUpdates = Lists.newArrayList();
                
                for (int i = 0; i < Math.ceil(((double) blocks.length) / MAX_BLOCKS_PER_INTERVAL); i++) {
                    blockUpdates.add(Lists.<BlockState>newArrayList());
                }
                
                int blockCount = 0;
                for (int i = 0; i < Lx; i++) {
                    int x = i + min.getBlockX();
                    for (int j = 0; j < Ly; j++) {
                        int y = j + min.getBlockY();
                        for (int k = 0; k < Lz; k++) {
                            int updateIndex = (int) Math.floor(blockCount / MAX_BLOCKS_PER_INTERVAL);
                            int z = k + min.getBlockZ();
                            int index = i + j * Lx + k * Lx * Ly;
                            BlockState state = world.getBlockAt(x, y, z).getState();
                            state.setTypeId(blocks[index]);
                            state.setRawData((byte) (data[(int) Math.floor(index / 2)] >> (4 * (index % 2))));
                            blockUpdates.get(updateIndex).add(state);
                            blockCount++;
                        }
                    }
                }
                
                for (int i = 0; i < blockUpdates.size(); i++) {
                    final List<BlockState> states = blockUpdates.get(i);
                    new GameRunnable() {<commit_msg>Convert signed byte to unsigned value<commit_after>package net.galaxygaming.selection;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.logging.Level;

import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;

import com.google.common.collect.Lists;
import net.galaxygaming.dispenser.game.Game;
import net.galaxygaming.dispenser.task.GameRunnable;

/**
 * Used for areas that should be restored
 * sometime during or after the game
 */
public class RegenableSelection {    
    private static final int MAX_BLOCKS_PER_INTERVAL = 250;
    private static final long INTERVAL_LENGTH = 20;
    
    private final Selection selection;
    private final Game game;
    private final String regionName;
    private byte[] blocks;
    private byte[] data;

    /**
     * @param game game this selection belongs to
     * @param regionName name of this region
     * @param selection selection specifying area
     */
    public RegenableSelection(Game game, String regionName, Selection selection) {
        this.selection = selection;
        this.game = game;
        this.regionName = regionName;
        
        reloadBlockData();
    }
    
    private RegenableSelection(Game game, String regionName, Selection selection, byte[] blocks, byte[] data) {
        this.selection = selection;
        this.game = game;
        this.regionName = regionName;
        
        this.blocks = blocks;
        this.data = data;
    }   
    
    /**
     * Updates the blocks saved by this selection with the blocks
     * currently in the world in the selection.
     */
    @SuppressWarnings("deprecation")
    public void reloadBlockData() {
        Location min = selection.getMin();
        Location max = selection.getMax();
        
        int Lx = max.getBlockX() - min.getBlockX() + 1;
        int Ly = max.getBlockY() - min.getBlockY() + 1;
        int Lz = max.getBlockZ() - min.getBlockZ() + 1;
        
        blocks = new byte[Lx*Ly*Lz];
        data = new byte[(int) Math.ceil((double) blocks.length / 2)];
        
        for (int i = 0; i < Lx; i++) {
            int x = i + min.getBlockX();
            for (int j = 0; j < Ly; j++) {
                int y = j + min.getBlockY();
                for (int k = 0; k < Lz; k++) {
                    int z = k + min.getBlockZ();
                    int index = i + j * Lx + k * Lx * Ly;
                    Block b = new Location(min.getWorld(), x, y, z).getBlock();
                    blocks[index] = (byte) b.getTypeId();
                    byte d = data[index / 2];                    
                    data[index / 2] = (byte) (d + (b.getData() << (4 * (index % 2))));
                }
            }
        }
        
        save();
    }
    
    /**
     * Gets the underlying {@link Selection} that defines the volume
     * controlled by this class
     * @return selection
     */
    public Selection getSelection() {
        return selection;
    }
    
    /**
     * Regenerates this selection with the stored block data.
     * This method uses block states in a update fast method
     * meaning no lighting updates are performed. It is also
     * processed over asynchronously over multiple seconds.
     */
    @SuppressWarnings("deprecation")
    public void regen() {
        // TODO: Check thread safety, cannot run at same time as reloadBlockData()
        
        new GameRunnable() {
            @Override
            public void run() {
                Location min = selection.getMin();
                Location max = selection.getMax();
                World world = min.getWorld();
                
                int Lx = max.getBlockX() - min.getBlockX() + 1;
                int Ly = max.getBlockY() - min.getBlockY() + 1;
                int Lz = max.getBlockZ() - min.getBlockZ() + 1;
                
                if (blocks == null || data == null || blocks.length != Lx*Ly*Lz || data.length != Lx*Ly*Lz/2) {
                    game.getLogger().log(Level.WARNING, "Tried to regen but block data is wrong length: " + regionName);
                    return;
                }
                
                List<List<BlockState>> blockUpdates = Lists.newArrayList();
                
                for (int i = 0; i < Math.ceil(((double) blocks.length) / MAX_BLOCKS_PER_INTERVAL); i++) {
                    blockUpdates.add(Lists.<BlockState>newArrayList());
                }
                
                int blockCount = 0;
                for (int i = 0; i < Lx; i++) {
                    int x = i + min.getBlockX();
                    for (int j = 0; j < Ly; j++) {
                        int y = j + min.getBlockY();
                        for (int k = 0; k < Lz; k++) {
                            int updateIndex = (int) Math.floor(blockCount / MAX_BLOCKS_PER_INTERVAL);
                            int z = k + min.getBlockZ();
                            int index = i + j * Lx + k * Lx * Ly;
                            BlockState state = world.getBlockAt(x, y, z).getState();
                            state.setTypeId(blocks[index] & 0xFF);
                            state.setRawData((byte) (data[(int) Math.floor(index / 2)] >> (4 * (index % 2))));
                            blockUpdates.get(updateIndex).add(state);
                            blockCount++;
                        }
                    }
                }
                
                for (int i = 0; i < blockUpdates.size(); i++) {
                    final List<BlockState> states = blockUpdates.get(i);
                    new GameRunnable() {
{'fraction_non_alphanumeric': 0.10901376742575115, 'fraction_numerical': 0.005108667417092389, 'mean_word_length': 1.5792764627065654, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3019585', 'n_tokens_mistral': 3271, 'n_tokens_neox': 3117, 'n_words': 918}