Guest User

Untitled

a guest
Sep 2nd, 2026
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class_name PackGrid2D extends RefCounted
  2.  
  3.  
  4. var _flat := PackedVector4Array()
  5. const _CONTAINER_MAX_SIZE: int = 4
  6. const _GRID_MAX_SIZE: = 46340 # sqrt(INT32_MAX)
  7. const _MAX_FLOAT_INTEGER = 16777216 # 24^2 ограничение мантиссы float в 64 бита, дальше точность целых чисел не гарантируется.
  8. var _offset: int
  9.  
  10.  
  11. #region API
  12. func setup(size: int) -> PackGrid2D:
  13.     if _badSize(size):
  14.         return
  15.     _offset = size
  16.     _flat.resize(size * size)
  17.     return self
  18.  
  19. static func calcFlatIndex(gridIndex: Vector2i, size: int) -> int:
  20.     return size * gridIndex.y + gridIndex.x
  21.  
  22. func has(index: Vector2i) -> bool:
  23.     return index.x >= 0 and index.y >= 0 and index.x < _offset and index.y < _offset
  24.  
  25.  
  26. func getId(gridIndex: Vector2i, containerIndex: int) -> int:
  27.     if _badContainerIndex(containerIndex):
  28.         return INT32_MIN - 1 #DS: у нас не было исключений, выживали как могли (нужно отдать не валидное INT32, чтобы крашнулось где-то)
  29.     if _badGridIndex(gridIndex):
  30.         return INT32_MIN - 1
  31.     return int(_flat[calcFlatIndex(gridIndex, _offset)][containerIndex])
  32.  
  33.  
  34. func setId(gridIndex: Vector2i, containerIndex: int, ValueId) -> void:
  35.     if _badValueId(ValueId):
  36.         return
  37.     if _badContainerIndex(containerIndex):
  38.         return
  39.     if _badGridIndex(gridIndex):
  40.         return
  41.     _flat[calcFlatIndex(gridIndex, _offset)][containerIndex] = ValueId
  42.  
  43.  
  44. func resetGrid(gridIndex: Vector2i) -> void:
  45.     setId(gridIndex, 0, 0)
  46.     setId(gridIndex, 1, 0)
  47.     setId(gridIndex, 2, 0)
  48.     setId(gridIndex, 3, 0)
  49. #endregion
  50.  
  51.  
  52. #region Error
  53. func _fatalError(msg: String) -> void:
  54.     if __test_isTesting:
  55.         __test_errorResult = msg
  56.         return
  57.  
  58.     push_error(msg)
  59.     breakpoint
  60.  
  61.  
  62. func _badSize(size: int) -> bool:
  63.     if size < 1 or size >= _GRID_MAX_SIZE:
  64.         _fatalError("GAME_ERROR: bad size: {0}".format([size]))
  65.         return true
  66.     return false
  67.  
  68.  
  69. func _badContainerIndex(containerIndex: int) -> bool:
  70.     if containerIndex < 0 or containerIndex >= _CONTAINER_MAX_SIZE:
  71.         _fatalError("GAME_ERROR: container index out of bounds: {0}".format([containerIndex]))
  72.         return true
  73.     return false
  74.  
  75.  
  76. func _badGridIndex(gridIndex: Vector2i) -> bool:
  77.     if not has(gridIndex):
  78.         _fatalError("GAME_ERROR: array index out of bounds: {0}".format([gridIndex]))
  79.         return true
  80.     return false
  81.  
  82.  
  83. func _badValueId(i: int) -> bool:
  84.     if i < 0 or i > _MAX_FLOAT_INTEGER:
  85.         _fatalError("GAME_ERROR: ValueId out of bounds: {0}".format([i]))
  86.         return true
  87.     return false
  88. #endregion
  89.  
  90.  
  91. #region Test
  92. var __test_isTesting := false
  93. var __test_errorResult := ""
  94.  
  95. func __test_init() -> PackGrid2D:
  96.     var t := PackGrid2D.new()
  97.     t.__test_isTesting = true
  98.     return t
  99.  
  100. func __test():
  101.     __test___badSize()
  102.     __test___badContainerIndex()
  103.     __test___badGridIndex()
  104.     __test___badInt32()
  105.     __test___work()
  106.  
  107.     # WARNING: Просто так не раскомментируй. Читай описание метода.
  108.     #__test___integerIntegrityTest()
  109.  
  110.     print("TEST OK")
  111.  
  112.  
  113. func __test___badSize():
  114.     const STATUS = 0
  115.     const ITEM = 1
  116.     const DIRT = 2
  117.     const _RESERVE_ = 3
  118.     var result: int
  119.     var t: PackGrid2D
  120.  
  121.     t = __test_init()
  122.     t.setup(0)
  123.     assert("GAME_ERROR: bad size: 0" == t.__test_errorResult)
  124.  
  125.     t = __test_init()
  126.     t.setup(-1)
  127.     assert("GAME_ERROR: bad size: -1" == t.__test_errorResult)
  128.  
  129.     t = __test_init()
  130.     t.setup(_GRID_MAX_SIZE + 1)
  131.     assert("GAME_ERROR: bad size: 46341" == t.__test_errorResult, t.__test_errorResult)
  132.  
  133.  
  134. func __test___badContainerIndex():
  135.     const STATUS = 0
  136.     const ITEM = 1
  137.     const DIRT = 2
  138.     const _RESERVE_ = 3
  139.     var result: int
  140.     var t: PackGrid2D
  141.  
  142.     t = __test_init()
  143.     t.setup(4)
  144.     result = t.getId(Vector2i(2, 1), 5)
  145.     assert("GAME_ERROR: container index out of bounds: 5" == t.__test_errorResult, t.__test_errorResult)
  146.     #DS: Зафиксируем эту проверку здесь
  147.     assert(result == INT32_MIN - 1)
  148.  
  149.     t = __test_init()
  150.     t.setup(4)
  151.     t.setId(Vector2i(2, 1), 5, 7)
  152.     assert("GAME_ERROR: container index out of bounds: 5" == t.__test_errorResult, t.__test_errorResult)
  153.  
  154.  
  155.     t = __test_init()
  156.     t.setup(4)
  157.     result = t.getId(Vector2i(2, 1), -1)
  158.     assert("GAME_ERROR: container index out of bounds: -1" == t.__test_errorResult, t.__test_errorResult)
  159.  
  160.     t = __test_init()
  161.     t.setup(4)
  162.     t.setId(Vector2i(2, 1), -1, 8)
  163.     assert("GAME_ERROR: container index out of bounds: -1" == t.__test_errorResult, t.__test_errorResult)
  164.  
  165.     t = __test_init()
  166.     t.setup(4)
  167.     result = t.getId(Vector2i(2, 4), ITEM)
  168.     assert("GAME_ERROR: array index out of bounds: (2, 4)" == t.__test_errorResult, t.__test_errorResult)
  169.  
  170.     t = __test_init()
  171.     t.setup(4)
  172.     t.setId(Vector2i(2, 4), ITEM, 401)
  173.     assert("GAME_ERROR: array index out of bounds: (2, 4)" == t.__test_errorResult, t.__test_errorResult)
  174.  
  175.  
  176. func __test___badGridIndex():
  177.     const STATUS = 0
  178.     const ITEM = 1
  179.     const DIRT = 2
  180.     const _RESERVE_ = 3
  181.     var result: int
  182.     var t: PackGrid2D
  183.  
  184.     t = __test_init()
  185.     t.setup(4)
  186.     result = t.getId(Vector2i(2, -1), ITEM)
  187.     assert("GAME_ERROR: array index out of bounds: (2, -1)" == t.__test_errorResult, t.__test_errorResult)
  188.  
  189.     t = __test_init()
  190.     t.setup(4)
  191.     t.setId(Vector2i(2, -1), ITEM, 208)
  192.     assert("GAME_ERROR: array index out of bounds: (2, -1)" == t.__test_errorResult, t.__test_errorResult)
  193.  
  194.     t = __test_init()
  195.     t.setup(4)
  196.     result = t.getId(Vector2i(4, 2), ITEM)
  197.     assert("GAME_ERROR: array index out of bounds: (4, 2)" == t.__test_errorResult, t.__test_errorResult)
  198.  
  199.     t = __test_init()
  200.     t.setup(4)
  201.     t.setId(Vector2i(4, 2), ITEM, 435)
  202.     assert("GAME_ERROR: array index out of bounds: (4, 2)" == t.__test_errorResult, t.__test_errorResult)
  203.  
  204.     t = __test_init()
  205.     t.setup(4)
  206.     result = t.getId(Vector2i(-1, 2), ITEM)
  207.     assert("GAME_ERROR: array index out of bounds: (-1, 2)" == t.__test_errorResult, t.__test_errorResult)
  208.  
  209.     t = __test_init()
  210.     t.setup(4)
  211.     t.setId(Vector2i(-1, 2), ITEM, 3)
  212.     assert("GAME_ERROR: array index out of bounds: (-1, 2)" == t.__test_errorResult, t.__test_errorResult)
  213.  
  214.  
  215. func __test___badInt32():
  216.     const STATUS = 0
  217.     const ITEM = 1
  218.     const DIRT = 2
  219.     const _RESERVE_ = 3
  220.     var result: int
  221.     var t: PackGrid2D
  222.  
  223.     t = __test_init()
  224.     t.setup(4)
  225.     t.setId(Vector2i(1, 2), ITEM, -1)
  226.     assert("GAME_ERROR: ValueId out of bounds: -1" == t.__test_errorResult, t.__test_errorResult)
  227.  
  228.     t = __test_init()
  229.     t.setup(4)
  230.     t.setId(Vector2i(1, 2), ITEM, INT32_MAX + 1)
  231.     assert("GAME_ERROR: ValueId out of bounds: 2147483648" == t.__test_errorResult, t.__test_errorResult)
  232.  
  233.  
  234. func __test___work():
  235.     const STATUS = 0
  236.     const ITEM = 1
  237.     const DIRT = 2
  238.     const _RESERVE_ = 3
  239.     var result: int
  240.     var t: PackGrid2D
  241.  
  242.     # COMM: этот тест слишком долгий. Он создает массив _GRID_MAX_SIZE^2
  243.     #       Оставлен для напоминания
  244.     #t = __test_init()
  245.     #t.setup(_GRID_MAX_SIZE)
  246.     #assert("" == t.__test_errorResult)
  247.  
  248.     t = __test_init()
  249.     t.setup(1)
  250.     assert("" == t.__test_errorResult)
  251.  
  252.     t = __test_init()
  253.     t.setup(4)
  254.     result = t.getId(Vector2i(1,0), ITEM)
  255.     assert(result == 0)
  256.     result = t.getId(Vector2i(1,0), DIRT)
  257.     assert(result == 0)
  258.     result = t.getId(Vector2i(1,0), STATUS)
  259.     assert(result == 0)
  260.     result = t.getId(Vector2i(1,0), _RESERVE_)
  261.     assert(result == 0)
  262.  
  263.     t.setId(Vector2i(3,2), STATUS, 20)
  264.     result = t.getId(Vector2i(3,2), STATUS)
  265.     assert(result == 20)
  266.  
  267.     t.setId(Vector2i(3,2), STATUS, 0)
  268.     result = t.getId(Vector2i(3,2), STATUS)
  269.     assert(result == 0)
  270.  
  271.     t.setId(Vector2i(3,2), _RESERVE_, 20)
  272.     result = t.getId(Vector2i(3,2), _RESERVE_)
  273.     assert(result == 20)
  274.  
  275.     t.setId(Vector2i(3,2), ITEM, 4031)
  276.     result = t.getId(Vector2i(3,2), ITEM)
  277.     assert(result == 4031)
  278.  
  279.     t.setId(Vector2i(3,2), DIRT, 1323)
  280.     result = t.getId(Vector2i(3,2), DIRT)
  281.     assert(result == 1323)
  282.  
  283.     t.setId(Vector2i(3,2), DIRT, _MAX_FLOAT_INTEGER)
  284.     result = t.getId(Vector2i(3,2), DIRT)
  285.     assert(result == _MAX_FLOAT_INTEGER)
  286.  
  287.     t = __test_init()
  288.     t.setup(2)
  289.     t.setId(Vector2i(1,0), ITEM, 1234)
  290.     t.setId(Vector2i(1,0), DIRT, 4321)
  291.     result = t.getId(Vector2i(1,0), ITEM)
  292.     assert(result == 1234)
  293.     result = t.getId(Vector2i(1,0), DIRT)
  294.     assert(result == 4321)
  295.     t.resetGrid(Vector2i(1,0))
  296.     result = t.getId(Vector2i(1,0), ITEM)
  297.     assert(result == 0)
  298.     result = t.getId(Vector2i(1,0), DIRT)
  299.     assert(result == 0)
  300.  
  301.  
  302. ## Это безумно долгий тест (до ~3 минут), чтобы проверить конвертацию и сохранность точности целых чисел при конвертации int -> float -> int
  303. ## Тест может занимать занимает до минут. Лучше один раз запустить в _proccess(). В _ready() может подвиснуть окно и не будет видно вывод итераций.
  304. ## Хотя _MAX_FLOAT_INTEGER гарантирует сохранность целостность целых чисел при точности мантиссы = 24 значащих бита,
  305. ## но в случае магических проблем на какой либо платформе, лучше прогнать тест на этой платформе (для PC проблем не должно быть).
  306. func __test___integerIntegrityTest():
  307.     const ITEM = 1
  308.     var t = __test_init()
  309.     t.setup(2)
  310.     var r: int
  311.     for i in _MAX_FLOAT_INTEGER:
  312.         if i % 100_000 == 0:
  313.             print(i)
  314.         t.setId(Vector2i(1,1), ITEM, i)
  315.         r = t.getId(Vector2i(1,1), ITEM)
  316.         assert(r == i, "{0} == {1}".format([r, i]))
  317. #endregion
  318.  
Advertisement
Add Comment
Please, Sign In to add comment