<commit_before>package rpgboss.player
import rpgboss.model._
import rpgboss.model.Constants.DirectionMasks._
import rpgboss.model.resource._
import rpgboss.player.entity.Entity
import com.badlogic.gdx.graphics.g2d._
import com.badlogic.gdx.graphics._
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Texture.TextureFilter
import com.badlogic.gdx.math.collision.BoundingBox
import com.badlogic.gdx.math.Vector3

/**
 * This class wraps a map and its assets. It should only be instantiated
 * on the Gdx thread, as it makes calls to OpenGL
 */
class MapAndAssets(project: Project, mapName: String) {
  val map: RpgMap = RpgMap.readFromDisk(project, mapName)
  val mapData: RpgMapData = map.readMapData().get

  /**
   * *
   * This section is all the stuff that finds the graphics and packs it into
   * texture atlases.
   */

  val packerTiles = new PixmapPacker(1024, 1024, Pixmap.Format.RGBA8888, 0, false)

  val autotiles: Array[Autotile] = map.metadata.autotiles.map { name =>
    Autotile.readFromDisk(project, name)
  }

  // Pack all the autotiles
  autotiles.map { autotile =>
    val autotilePix = new Pixmap(
      Gdx.files.absolute(autotile.dataFile.getAbsolutePath()))

    packerTiles.pack("autotile/%s".format(autotile.name), autotilePix)

    autotilePix.dispose()
  }

  val tilesets = map.metadata.tilesets.map(
    name => Tileset.readFromDisk(project, name)).toArray[Tileset]

  // Pack all tilesets
  tilesets.map { tileset =>
    val tilesetPix = new Pixmap(
      Gdx.files.absolute(tileset.dataFile.getAbsolutePath()))

    packerTiles.pack("tileset/%s".format(tileset.name), tilesetPix)

    tilesetPix.dispose()
  }

  def getBlockedDirsOf(xTile: Int, yTile: Int): Byte = {
    import RpgMap._
    import Constants.DirectionMasks._
    val xIdx = xTile * bytesPerTile

    // Test top layer first, as if the top layer provides an answer, there is
    // no need to test subsequent layers
    for (layerAry <- List(mapData.topLayer, mapData.midLayer, mapData.botLayer)) {
      val row = layerAry(yTile)
      val byte1 = row(xIdx)
      val byte2 = row(xIdx + 1)
      val byte3 = row(xIdx + 2)

      if (byte1 < 0) {
        // Empty tile or autotile
        if (byte1 == autotileByte) {
          val tiledata = autotiles(byte2).metadata

          if (tiledata.height == 0)
            return tiledata.blockedDirs
        } else {
          // Empty tile: Do nothing... just continue with next layer
        }
      } else { // tileset tile
        val tiledata = tilesets(byte1).metadata

        if (tiledata.heightAry(byte3)(byte2) == 0)
          return tiledata.blockedDirsAry(byte3)(byte2).toByte
      }
    }

    return NONE.toByte
  }

  /**
   * Test if there is a collision of a box with movement defined by |dx| and
   * |dy|. The re-route result will be for the bigger axis of |dx| and |dy|.
   * If they are equal, it will be for the |dx| axis.
   *
   * @return  (collision, reroute)  |collision| is true if there is a collision.
   *                                |reroute| returns which way the entity is
   *                                recommended to go if it wants to continue
   *                                along its path. For instance, for an entity
   *                                traveling in x-axis, a +1 reroute suggests
   *                                that it is blocked (probably by a corner)
   *                                but could continue by going in the
   *                                y-positive direction. Negative means going
   *                                in the y-negative direction, and a 0 means
   *                                there is no suggested rerouting.
   */
  def getCollisions(entity: Entity, x: Float, y: Float, dx: Float,
                    dy: Float): (Boolean, Int) = {
    if (dx == 0 && dy == 0)
      return (false, 0)

    val changeVector = new Vector3(dx, dy, 0)

    val boundingBox = entity.getBoundingBox()
    val minX = (boundingBox.getMin().x + dx).toInt
    val minY = (boundingBox.getMin().y + dy).toInt
    val maxX = (boundingBox.getMax().x + dx).toInt
    val maxY = (boundingBox.getMax().y + dy).toInt

    // 1. Test for going off map edge
    if (!map.metadata.withinBounds(minX, minY) ||
      !map.metadata.withinBounds(maxX, maxY))
      return (true, 0)

    var blocked = false
    // Being blocked in the positive direction adds -1.
    // Being blocked in the negative direction adds  1.
    var reroute = 0

    if (math.abs(dx) > math.abs(dy)) {
      if (dx >= 0) {
        if (flagged(getBlockedDirsOf(maxX, minY), WEST)) {
          blocked = true
          reroute += 1
        }
        if (flagged(getBlockedDirsOf(maxX, maxY), WEST)) {
          blocked = true
          reroute -= 1
        }
      } else {
        if (flagged(getBlockedDirsOf(minX, minY), EAST)) {
          blocked = true
          reroute += 1
        }
        if (flagged(getBlockedDirsOf(minX, maxY), EAST)) {
          blocked = true
          reroute -= 1
        }
      }
    } else {
      if (dy >= 0) {
        if (flagged(getBlockedDirsOf(minX, maxY), NORTH)) {
          blocked = true
          reroute += 1
        }
        if (flagged(getBlockedDirsOf(maxX, maxY), NORTH)) {
          blocked = true
          reroute -= 1
        }
      } else {
        if (flagged(getBlockedDirsOf(minX, minY), SOUTH)) {
          blocked = true
          reroute += 1
        }
        if (flagged(getBlockedDirsOf(maxX, minY), SOUTH)) {
          blocked = true
          reroute -= 1
        }
      }
    }

    return (blocked, reroute)
  }

  //info("Packed tilesets and autotiles into %d pages".format(
  //    packerTiles.getPages().size))

  // Generate texture atlas, nearest neighbor with no mipmaps
  val atlasTiles = packerTiles.generateTextureAtlas(
    TextureFilter.Nearest, TextureFilter.Nearest, false)

  def dispose() = {
    atlasTiles.dispose()
  }
}<commit_msg>Somehow handles map movement correctly<commit_after>package rpgboss.player
import rpgboss.model._
import rpgboss.model.Constants.DirectionMasks._
import rpgboss.model.resource._
import rpgboss.player.entity.Entity
import com.badlogic.gdx.graphics.g2d._
import com.badlogic.gdx.graphics._
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Texture.TextureFilter
import com.badlogic.gdx.math.collision.BoundingBox
import com.badlogic.gdx.math.Vector3

/**
 * This class wraps a map and its assets. It should only be instantiated
 * on the Gdx thread, as it makes calls to OpenGL
 */
class MapAndAssets(project: Project, mapName: String) {
  val map: RpgMap = RpgMap.readFromDisk(project, mapName)
  val mapData: RpgMapData = map.readMapData().get

  /**
   * *
   * This section is all the stuff that finds the graphics and packs it into
   * texture atlases.
   */

  val packerTiles = new PixmapPacker(1024, 1024, Pixmap.Format.RGBA8888, 0, false)

  val autotiles: Array[Autotile] = map.metadata.autotiles.map { name =>
    Autotile.readFromDisk(project, name)
  }

  // Pack all the autotiles
  autotiles.map { autotile =>
    val autotilePix = new Pixmap(
      Gdx.files.absolute(autotile.dataFile.getAbsolutePath()))

    packerTiles.pack("autotile/%s".format(autotile.name), autotilePix)

    autotilePix.dispose()
  }

  val tilesets = map.metadata.tilesets.map(
    name => Tileset.readFromDisk(project, name)).toArray[Tileset]

  // Pack all tilesets
  tilesets.map { tileset =>
    val tilesetPix = new Pixmap(
      Gdx.files.absolute(tileset.dataFile.getAbsolutePath()))

    packerTiles.pack("tileset/%s".format(tileset.name), tilesetPix)

    tilesetPix.dispose()
  }

  def getBlockedDirsOf(xTile: Int, yTile: Int): Byte = {
    import RpgMap._
    import Constants.DirectionMasks._
    val xIdx = xTile * bytesPerTile

    // Test top layer first, as if the top layer provides an answer, there is
    // no need to test subsequent layers
    for (layerAry <- List(mapData.topLayer, mapData.midLayer, mapData.botLayer)) {
      val row = layerAry(yTile)
      val byte1 = row(xIdx)
      val byte2 = row(xIdx + 1)
      val byte3 = row(xIdx + 2)

      if (byte1 < 0) {
        // Empty tile or autotile
        if (byte1 == autotileByte) {
          val tiledata = autotiles(byte2).metadata

          if (tiledata.height == 0)
            return tiledata.blockedDirs
        } else {
          // Empty tile: Do nothing... just continue with next layer
        }
      } else { // tileset tile
        val tiledata = tilesets(byte1).metadata

        if (tiledata.heightAry(byte3)(byte2) == 0)
          return tiledata.blockedDirsAry(byte3)(byte2).toByte
      }
    }

    return NONE.toByte
  }

  /**
   * Test if there is a collision of a box with movement defined by |dx| and
   * |dy|. The re-route result will be for the bigger axis of |dx| and |dy|.
   * If they are equal, it will be for the |dx| axis.
   *
   * @return  (collision, reroute)  |collision| is true if there is a collision.
   *                                |reroute| returns which way the entity is
   *                                recommended to go if it wants to continue
   *                                along its path. For instance, for an entity
   *                                traveling in x-axis, a +1 reroute suggests
   *                                that it is blocked (probably by a corner)
   *                                but could continue by going in the
   *                                y-positive direction. Negative means going
   *                                in the y-negative direction, and a 0 means
   *                                there is no suggested rerouting.
   */
  def getCollisions(entity: Entity, x: Float, y: Float, dx: Float,
                    dy: Float): (Boolean, Int) = {
    if (dx == 0 && dy == 0)
      return (false, 0)

    val changeVector = new Vector3(dx, dy, 0)

    val boundingBox = entity.getBoundingBox()
    val newX = x + dx
    val newY = y + dy
    val minX = (boundingBox.getMin().x + dx)
    val minY = (boundingBox.getMin().y + dy)
    val maxX = (boundingBox.getMax().x + dx)
    val maxY = (boundingBox.getMax().y + dy)
    boundingBox.set(new Vector3(minX, minY, 0), new Vector3(maxX, maxY, 0))

    val minXTile = minX.toInt
    val minYTile = minY.toInt
    val maxXTile = maxX.toInt
    val maxYTile = maxY.toInt

    // 1. Test for going off map edge
    if (!map.metadata.withinBounds(minXTile, minYTile) ||
      !map.metadata.withinBounds(maxXTile, maxYTile))
      return (true, 0)

    var blocked = false
    // Being blocked in the positive direction adds -1.
    // Being blocked in the negative direction adds  1.
    var reroute = 0f

    def processTile(xTile: Int, yTile: Int, dir: Int,
                    rerouteSign: Int): Unit = {
      val blockedDirs = getBlockedDirsOf(xTile, yTile)

      if (blockedDirs == NONE)
        return

      if (flagged(blockedDirs, dir)) {
        blocked = true
        reroute += rerouteSign
        return
      }

      // Finally, check for blocking due to walls running parallel to direction
      // of movement.
      if ((dir & (EAST | WEST)) > 0) {
        val northWallBlock = flagged(blockedDirs, NORTH) &&
          (boundingBox.contains(new Vector3(xTile, yTile, 0)) ||
            boundingBox.contains(new Vector3(xTile + 1, yTile, 0)))
        val southWallBlock = flagged(blockedDirs, SOUTH) &&
          (boundingBox.contains(new Vector3(xTile, yTile + 1, 0)) ||
            boundingBox.contains(new Vector3(xTile + 1, yTile + 1, 0)))

        if (northWallBlock) {
          blocked = true
          reroute += newY - yTile
        }
        if (southWallBlock) {
          blocked = true
          reroute += newY - (yTile + 1)
        }
      } else {
        val eastWallBlock = flagged(blockedDirs, EAST) &&
          (boundingBox.contains(new Vector3(xTile + 1, yTile, 0)) ||
            boundingBox.contains(new Vector3(xTile + 1, yTile + 1, 0)))
        val westWallBlock = flagged(blockedDirs, WEST) &&
          (boundingBox.contains(new Vector3(xTile, yTile, 0)) ||
            boundingBox.contains(new Vector3(xTile, yTile + 1, 0)))

        if (eastWallBlock) {
          blocked = true
          reroute += newX - (xTile + 1)
        }
        if (westWallBlock) {
          blocked = true
          reroute += newX - xTile
        }
      }
    }

    if (math.abs(dx) > math.abs(dy)) {
      processTile(maxXTile, minYTile, WEST, 1)
      processTile(maxXTile, maxYTile, WEST, -1)
      processTile(minXTile, minYTile, EAST, 1)
      processTile(minXTile, maxYTile, EAST, -1)
    } else {
      processTile(minXTile, maxYTile, NORTH, 1)
      processTile(maxXTile, maxYTile, NORTH, -1)
      processTile(minXTile, minYTile, SOUTH, 1)
      processTile(maxXTile, minYTile, SOUTH, -1)
    }

    return (blocked, math.signum(reroute).toInt)
  }

  //info("Packed tilesets and autotiles into %d pages".format(
  //    packerTiles.getPages().size))

  // Generate texture atlas, nearest neighbor with no mipmaps
  val atlasTiles = packerTiles.generateTextureAtlas(
    TextureFilter.Nearest, TextureFilter.Nearest, false)

  def dispose() = {
    atlasTiles.dispose()
  }
}
{'fraction_non_alphanumeric': 0.10442437580632921, 'fraction_numerical': 0.010245124079836078, 'mean_word_length': 2.180786869418296, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6436064', 'n_tokens_mistral': 4451, 'n_tokens_neox': 4220, 'n_words': 1159}