diff --git a/WrplatGodot.csproj b/WrplatGodot.csproj
index 8c1e394..dff3bfb 100644
--- a/WrplatGodot.csproj
+++ b/WrplatGodot.csproj
@@ -3,5 +3,6 @@
net8.0
net9.0
true
+ preview
\ No newline at end of file
diff --git a/materials/tilesets/pool.tres b/materials/tilesets/pool.tres
new file mode 100644
index 0000000..c0ee02f
--- /dev/null
+++ b/materials/tilesets/pool.tres
@@ -0,0 +1,9 @@
+[gd_resource type="CanvasTexture" format=3 uid="uid://b78uwnnyovqci"]
+
+[ext_resource type="Texture2D" uid="uid://n6b4udvjt2pt" path="res://sprites/atlas/diffuse/pool.diffuse.png" id="1_v3cld"]
+[ext_resource type="Texture2D" uid="uid://cs2jr54egxwey" path="res://sprites/atlas/normal/pool.normal.png" id="2_srhaa"]
+
+[resource]
+diffuse_texture = ExtResource("1_v3cld")
+normal_texture = ExtResource("2_srhaa")
+specular_shininess = 0.35
diff --git a/objects/animation/frames/player.tres b/objects/animation/frames/player.tres
index d8ec67f..8520b36 100644
--- a/objects/animation/frames/player.tres
+++ b/objects/animation/frames/player.tres
@@ -1,44 +1,44 @@
[gd_resource type="SpriteFrames" format=3 uid="uid://doxc4pl5hvs6k"]
-[ext_resource type="Texture2D" uid="uid://bv4gsgya7wp4d" path="res://sprites/atlas/demoman_walking.png" id="1_1t22f"]
-[ext_resource type="Texture2D" uid="uid://dy7fh0eg6qulr" path="res://sprites/atlas/demoman_idles.png" id="1_c2ath"]
[ext_resource type="Texture2D" uid="uid://cl3uy4d6lgspe" path="res://sprites/man_falls.png" id="1_kdeld"]
+[ext_resource type="Texture2D" uid="uid://dy7fh0eg6qulr" path="res://sprites/atlas/flats/demoman_idles.png" id="2_kdeld"]
[ext_resource type="Texture2D" uid="uid://cr5bdv3hgmd4q" path="res://sprites/man_jumps.png" id="3_a1t44"]
+[ext_resource type="Texture2D" uid="uid://bv4gsgya7wp4d" path="res://sprites/atlas/flats/demoman_walking.png" id="4_a1t44"]
[sub_resource type="AtlasTexture" id="AtlasTexture_w1sc6"]
-atlas = ExtResource("1_c2ath")
+atlas = ExtResource("2_kdeld")
region = Rect2(0, 0, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_mcxxx"]
-atlas = ExtResource("1_c2ath")
+atlas = ExtResource("2_kdeld")
region = Rect2(0, 64, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_nf227"]
-atlas = ExtResource("1_c2ath")
+atlas = ExtResource("2_kdeld")
region = Rect2(32, 0, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_sbabb"]
-atlas = ExtResource("1_c2ath")
+atlas = ExtResource("2_kdeld")
region = Rect2(32, 64, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_c2ath"]
-atlas = ExtResource("1_1t22f")
+atlas = ExtResource("4_a1t44")
region = Rect2(0, 0, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_gwfnt"]
-atlas = ExtResource("1_1t22f")
+atlas = ExtResource("4_a1t44")
region = Rect2(0, 64, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_kdeld"]
-atlas = ExtResource("1_1t22f")
+atlas = ExtResource("4_a1t44")
region = Rect2(32, 0, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_a1t44"]
-atlas = ExtResource("1_1t22f")
+atlas = ExtResource("4_a1t44")
region = Rect2(32, 64, 32, 64)
[sub_resource type="AtlasTexture" id="AtlasTexture_k551e"]
-atlas = ExtResource("1_1t22f")
+atlas = ExtResource("4_a1t44")
region = Rect2(64, 0, 32, 64)
[resource]
diff --git a/project.godot b/project.godot
index 92b52f0..89ec7ac 100644
--- a/project.godot
+++ b/project.godot
@@ -98,6 +98,11 @@ turn_back={
]
}
+[layer_names]
+
+2d_render/layer_1="Backgrounds"
+2d_render/layer_2="Foregrounds"
+
[physics]
3d/physics_engine="Jolt Physics"
diff --git a/sprites/atlas/diffuse/pool.diffuse.png b/sprites/atlas/diffuse/pool.diffuse.png
new file mode 100644
index 0000000..fab92c4
Binary files /dev/null and b/sprites/atlas/diffuse/pool.diffuse.png differ
diff --git a/sprites/atlas/diffuse/pool.diffuse.png.import b/sprites/atlas/diffuse/pool.diffuse.png.import
new file mode 100644
index 0000000..8cf7812
--- /dev/null
+++ b/sprites/atlas/diffuse/pool.diffuse.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://n6b4udvjt2pt"
+path="res://.godot/imported/pool.diffuse.png-f15c5d02eff23304ecfbdd590cdc3504.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://sprites/atlas/diffuse/pool.diffuse.png"
+dest_files=["res://.godot/imported/pool.diffuse.png-f15c5d02eff23304ecfbdd590cdc3504.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/sprites/atlas/demoman_idles.png b/sprites/atlas/flats/demoman_idles.png
similarity index 100%
rename from sprites/atlas/demoman_idles.png
rename to sprites/atlas/flats/demoman_idles.png
diff --git a/sprites/atlas/demoman_idles.png.import b/sprites/atlas/flats/demoman_idles.png.import
similarity index 75%
rename from sprites/atlas/demoman_idles.png.import
rename to sprites/atlas/flats/demoman_idles.png.import
index b36fb49..476f055 100644
--- a/sprites/atlas/demoman_idles.png.import
+++ b/sprites/atlas/flats/demoman_idles.png.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dy7fh0eg6qulr"
-path="res://.godot/imported/demoman_idles.png-a329588d12d5e8eda94ae9b9fc61068e.ctex"
+path="res://.godot/imported/demoman_idles.png-add2b3af5478c463b97d1483e4e33e47.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://sprites/atlas/demoman_idles.png"
-dest_files=["res://.godot/imported/demoman_idles.png-a329588d12d5e8eda94ae9b9fc61068e.ctex"]
+source_file="res://sprites/atlas/flats/demoman_idles.png"
+dest_files=["res://.godot/imported/demoman_idles.png-add2b3af5478c463b97d1483e4e33e47.ctex"]
[params]
diff --git a/sprites/atlas/demoman_walking.png b/sprites/atlas/flats/demoman_walking.png
similarity index 100%
rename from sprites/atlas/demoman_walking.png
rename to sprites/atlas/flats/demoman_walking.png
diff --git a/sprites/atlas/demoman_walking.png.import b/sprites/atlas/flats/demoman_walking.png.import
similarity index 75%
rename from sprites/atlas/demoman_walking.png.import
rename to sprites/atlas/flats/demoman_walking.png.import
index 89ceffe..900471c 100644
--- a/sprites/atlas/demoman_walking.png.import
+++ b/sprites/atlas/flats/demoman_walking.png.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bv4gsgya7wp4d"
-path="res://.godot/imported/demoman_walking.png-9be9634caac03406a9e7d7741131c5f4.ctex"
+path="res://.godot/imported/demoman_walking.png-3b471b54b0862aac29ec2aa6d7d5d5d6.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://sprites/atlas/demoman_walking.png"
-dest_files=["res://.godot/imported/demoman_walking.png-9be9634caac03406a9e7d7741131c5f4.ctex"]
+source_file="res://sprites/atlas/flats/demoman_walking.png"
+dest_files=["res://.godot/imported/demoman_walking.png-3b471b54b0862aac29ec2aa6d7d5d5d6.ctex"]
[params]
diff --git a/sprites/atlas/pool.png b/sprites/atlas/flats/pool.png
similarity index 100%
rename from sprites/atlas/pool.png
rename to sprites/atlas/flats/pool.png
diff --git a/sprites/atlas/pool.png.import b/sprites/atlas/flats/pool.png.import
similarity index 77%
rename from sprites/atlas/pool.png.import
rename to sprites/atlas/flats/pool.png.import
index a6cfe24..8970646 100644
--- a/sprites/atlas/pool.png.import
+++ b/sprites/atlas/flats/pool.png.import
@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cgr7fx5emk037"
-path="res://.godot/imported/pool.png-b13073abd16d5b4aa7f02817fa2d5dca.ctex"
+path="res://.godot/imported/pool.png-9044908d89edc8b0017e06046d331edd.ctex"
metadata={
"vram_texture": false
}
[deps]
-source_file="res://sprites/atlas/pool.png"
-dest_files=["res://.godot/imported/pool.png-b13073abd16d5b4aa7f02817fa2d5dca.ctex"]
+source_file="res://sprites/atlas/flats/pool.png"
+dest_files=["res://.godot/imported/pool.png-9044908d89edc8b0017e06046d331edd.ctex"]
[params]
diff --git a/sprites/atlas/normal/pool.normal.png b/sprites/atlas/normal/pool.normal.png
new file mode 100644
index 0000000..f27cbd3
Binary files /dev/null and b/sprites/atlas/normal/pool.normal.png differ
diff --git a/sprites/atlas/normal/pool.normal.png.import b/sprites/atlas/normal/pool.normal.png.import
new file mode 100644
index 0000000..50fd498
--- /dev/null
+++ b/sprites/atlas/normal/pool.normal.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://cs2jr54egxwey"
+path="res://.godot/imported/pool.normal.png-d715ee8c1699b86312f19adc110615ea.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://sprites/atlas/normal/pool.normal.png"
+dest_files=["res://.godot/imported/pool.normal.png-d715ee8c1699b86312f19adc110615ea.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/sprites/atlas/specular/pool.specular.png b/sprites/atlas/specular/pool.specular.png
new file mode 100644
index 0000000..17b01d2
Binary files /dev/null and b/sprites/atlas/specular/pool.specular.png differ
diff --git a/sprites/atlas/specular/pool.specular.png.import b/sprites/atlas/specular/pool.specular.png.import
new file mode 100644
index 0000000..08b6b76
--- /dev/null
+++ b/sprites/atlas/specular/pool.specular.png.import
@@ -0,0 +1,40 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://p4hfrsl8bbpg"
+path="res://.godot/imported/pool.specular.png-11a7497f1c1ddae08e066a0e33eb2e9b.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://sprites/atlas/specular/pool.specular.png"
+dest_files=["res://.godot/imported/pool.specular.png-11a7497f1c1ddae08e066a0e33eb2e9b.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
diff --git a/sprites/tilesets/pool.tres b/sprites/tilesets/pool.tres
index 6381c72..cfc29f6 100644
--- a/sprites/tilesets/pool.tres
+++ b/sprites/tilesets/pool.tres
@@ -1,9 +1,10 @@
[gd_resource type="TileSet" format=3 uid="uid://bk7cbdppa3j6a"]
-[ext_resource type="Texture2D" uid="uid://cgr7fx5emk037" path="res://sprites/atlas/pool.png" id="1_otsg2"]
+[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_5h5kb"]
+load_path = "res://.godot/imported/pool.png-b13073abd16d5b4aa7f02817fa2d5dca.ctex"
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_blkrv"]
-texture = ExtResource("1_otsg2")
+texture = SubResource("CompressedTexture2D_5h5kb")
texture_region_size = Vector2i(32, 32)
0:0/0 = 0
0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
diff --git a/sprites/tilesets/pool_dyn.tres b/sprites/tilesets/pool_dyn.tres
new file mode 100644
index 0000000..9724c09
--- /dev/null
+++ b/sprites/tilesets/pool_dyn.tres
@@ -0,0 +1,446 @@
+[gd_resource type="TileSet" format=3 uid="uid://cb1bigfqp1l7t"]
+
+[ext_resource type="Texture2D" uid="uid://b78uwnnyovqci" path="res://materials/tilesets/pool.tres" id="1_l670f"]
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_l670f"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_5tlu2"]
+polygon = PackedVector2Array(-6.8571424, -2.2857132, 16, -2.2857132, 16, 16, -6.8571424, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_by4n8"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_0ou5r"]
+polygon = PackedVector2Array(-6.8571424, -16, -6.8571424, 16, 16, 16, 16, -16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_1bmlt"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_g011h"]
+polygon = PackedVector2Array(-6.8571424, -16, -6.8571424, 2.285715, 16, 2.285715, 16, -16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_x4gly"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_uesvo"]
+polygon = PackedVector2Array(-16, -2.2857132, 16, -2.2857132, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_h32fx"]
+polygon = PackedVector2Array(-16, -2.2857132, 16, -2.2857132, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_f0cx1"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_dghjy"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_dc0ws"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_6l2xn"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_blamv"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_f77ak"]
+polygon = PackedVector2Array(-16, 2.285715, 16, 2.285715, 16, -16, -16, -16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_kj7tv"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_ro6yg"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 2.285715, -16, 2.285715)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_ebmht"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_xuple"]
+polygon = PackedVector2Array(-16, -2.2857132, 6.8571434, -2.2857132, 6.8571434, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_ru1yo"]
+polygon = PackedVector2Array(6.8571434, -16, 6.8571434, 16, -16, 16, -16, -16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_vok1k"]
+polygon = PackedVector2Array(6.8571434, -16, 6.8571434, 16, -16, 16, -16, -16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_flqmo"]
+polygon = PackedVector2Array(-16, 2.285715, 6.8571434, 2.285715, 6.8571434, -16, -16, -16, -16, 2.285715, -16, 2.285715)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_8alh0"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_xwwfl"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_njrqr"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_o2foe"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="OccluderPolygon2D" id="OccluderPolygon2D_yfu7p"]
+polygon = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+
+[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_blkrv"]
+texture = ExtResource("1_l670f")
+texture_region_size = Vector2i(32, 32)
+0:0/0 = 0
+0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+1:0/0 = 0
+1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+2:0/0 = 0
+2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+3:0/0 = 0
+3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+4:0/0 = 0
+5:0/0 = 0
+6:0/0 = 0
+7:0/0 = 0
+8:0/0 = 0
+9:0/0 = 0
+10:0/0 = 0
+11:0/0 = 0
+0:1/0 = 0
+0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, -16, -16, 16, -16, 16, 16)
+1:1/0 = 0
+1:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+2:1/0 = 0
+2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+3:1/0 = 0
+3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, 16, 16, 16, 16, -16, -16, -16)
+4:1/0 = 0
+5:1/0 = 0
+6:1/0 = 0
+7:1/0 = 0
+8:1/0 = 0
+9:1/0 = 0
+10:1/0 = 0
+11:1/0 = 0
+0:2/0 = 0
+1:2/0 = 0
+1:2/0/terrain_set = 0
+1:2/0/terrain = 0
+1:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_l670f")
+1:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_5tlu2")
+1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+1:2/0/terrains_peering_bit/right_side = 0
+1:2/0/terrains_peering_bit/bottom_right_corner = 0
+1:2/0/terrains_peering_bit/bottom_side = 0
+2:2/next_alternative_id = 3
+2:2/0 = 0
+2:2/0/terrain_set = 0
+2:2/0/terrain = 0
+2:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_x4gly")
+2:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_uesvo")
+2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+2:2/0/terrains_peering_bit/right_side = 0
+2:2/0/terrains_peering_bit/bottom_right_corner = 0
+2:2/0/terrains_peering_bit/bottom_side = 0
+2:2/0/terrains_peering_bit/bottom_left_corner = 0
+2:2/0/terrains_peering_bit/left_side = 0
+2:2/1 = 1
+2:2/1/flip_h = true
+2:2/1/terrain_set = 0
+2:2/1/terrain = 0
+2:2/1/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_1bmlt")
+2:2/1/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_h32fx")
+2:2/1/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16, -16, -16)
+2:2/1/terrains_peering_bit/right_side = 0
+2:2/1/terrains_peering_bit/bottom_right_corner = 0
+2:2/1/terrains_peering_bit/bottom_side = 0
+2:2/1/terrains_peering_bit/bottom_left_corner = 0
+2:2/1/terrains_peering_bit/left_side = 0
+3:2/0 = 0
+3:2/0/terrain_set = 0
+3:2/0/terrain = 0
+3:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_ebmht")
+3:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_xuple")
+3:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+3:2/0/terrains_peering_bit/bottom_side = 0
+3:2/0/terrains_peering_bit/bottom_left_corner = 0
+3:2/0/terrains_peering_bit/left_side = 0
+4:2/0 = 0
+4:2/0/terrain_set = 0
+4:2/0/terrain = 0
+4:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_8alh0")
+4:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_xwwfl")
+4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+4:2/0/terrains_peering_bit/right_side = 0
+5:2/0 = 0
+5:2/0/terrain_set = 0
+5:2/0/terrain = 0
+5:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_8alh0")
+5:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_xwwfl")
+5:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+5:2/0/terrains_peering_bit/right_side = 0
+5:2/0/terrains_peering_bit/left_side = 0
+6:2/0 = 0
+6:2/0/terrain_set = 0
+6:2/0/terrain = 0
+6:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_8alh0")
+6:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_xwwfl")
+6:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+6:2/0/terrains_peering_bit/left_side = 0
+7:2/0 = 0
+7:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_yfu7p")
+7:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_xwwfl")
+8:2/0 = 0
+8:2/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_yfu7p")
+8:2/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_xwwfl")
+9:2/0 = 0
+10:2/0 = 0
+11:2/0 = 0
+0:3/0 = 0
+1:3/next_alternative_id = 2
+1:3/0 = 0
+1:3/0/terrain_set = 0
+1:3/0/terrain = 0
+1:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_by4n8")
+1:3/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_0ou5r")
+1:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+1:3/0/terrains_peering_bit/right_side = 0
+1:3/0/terrains_peering_bit/bottom_right_corner = 0
+1:3/0/terrains_peering_bit/bottom_side = 0
+1:3/0/terrains_peering_bit/top_side = 0
+1:3/0/terrains_peering_bit/top_right_corner = 0
+1:3/1 = 1
+1:3/1/flip_v = true
+1:3/1/terrain_set = 0
+1:3/1/terrain = 0
+1:3/1/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_1bmlt")
+1:3/1/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_0ou5r")
+1:3/1/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+1:3/1/terrains_peering_bit/right_side = 0
+1:3/1/terrains_peering_bit/bottom_right_corner = 0
+1:3/1/terrains_peering_bit/bottom_side = 0
+1:3/1/terrains_peering_bit/top_side = 0
+1:3/1/terrains_peering_bit/top_right_corner = 0
+2:3/next_alternative_id = 6
+2:3/0 = 0
+2:3/0/terrain_set = 0
+2:3/0/terrain = 0
+2:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_by4n8")
+2:3/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_f0cx1")
+2:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+2:3/0/terrains_peering_bit/right_side = 0
+2:3/0/terrains_peering_bit/bottom_right_corner = 0
+2:3/0/terrains_peering_bit/bottom_side = 0
+2:3/0/terrains_peering_bit/bottom_left_corner = 0
+2:3/0/terrains_peering_bit/left_side = 0
+2:3/0/terrains_peering_bit/top_left_corner = 0
+2:3/0/terrains_peering_bit/top_side = 0
+2:3/0/terrains_peering_bit/top_right_corner = 0
+2:3/1 = 1
+2:3/1/flip_h = true
+2:3/1/terrain_set = 0
+2:3/1/terrain = 0
+2:3/1/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_1bmlt")
+2:3/1/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_dghjy")
+2:3/1/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+2:3/1/terrains_peering_bit/right_side = 0
+2:3/1/terrains_peering_bit/bottom_right_corner = 0
+2:3/1/terrains_peering_bit/bottom_side = 0
+2:3/1/terrains_peering_bit/bottom_left_corner = 0
+2:3/1/terrains_peering_bit/left_side = 0
+2:3/1/terrains_peering_bit/top_left_corner = 0
+2:3/1/terrains_peering_bit/top_side = 0
+2:3/1/terrains_peering_bit/top_right_corner = 0
+2:3/2 = 2
+2:3/2/flip_v = true
+2:3/2/terrain_set = 0
+2:3/2/terrain = 0
+2:3/2/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_1bmlt")
+2:3/2/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_dc0ws")
+2:3/2/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+2:3/2/terrains_peering_bit/right_side = 0
+2:3/2/terrains_peering_bit/bottom_right_corner = 0
+2:3/2/terrains_peering_bit/bottom_side = 0
+2:3/2/terrains_peering_bit/bottom_left_corner = 0
+2:3/2/terrains_peering_bit/left_side = 0
+2:3/2/terrains_peering_bit/top_left_corner = 0
+2:3/2/terrains_peering_bit/top_side = 0
+2:3/2/terrains_peering_bit/top_right_corner = 0
+2:3/4 = 4
+2:3/4/transpose = true
+2:3/4/terrain_set = 0
+2:3/4/terrain = 0
+2:3/4/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_1bmlt")
+2:3/4/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_6l2xn")
+2:3/4/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+2:3/4/terrains_peering_bit/right_side = 0
+2:3/4/terrains_peering_bit/bottom_right_corner = 0
+2:3/4/terrains_peering_bit/bottom_side = 0
+2:3/4/terrains_peering_bit/bottom_left_corner = 0
+2:3/4/terrains_peering_bit/left_side = 0
+2:3/4/terrains_peering_bit/top_left_corner = 0
+2:3/4/terrains_peering_bit/top_side = 0
+2:3/4/terrains_peering_bit/top_right_corner = 0
+2:3/5 = 5
+2:3/5/flip_h = true
+2:3/5/transpose = true
+2:3/5/terrain_set = 0
+2:3/5/terrain = 0
+2:3/5/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_1bmlt")
+2:3/5/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_blamv")
+2:3/5/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+2:3/5/terrains_peering_bit/right_side = 0
+2:3/5/terrains_peering_bit/bottom_right_corner = 0
+2:3/5/terrains_peering_bit/bottom_side = 0
+2:3/5/terrains_peering_bit/bottom_left_corner = 0
+2:3/5/terrains_peering_bit/left_side = 0
+2:3/5/terrains_peering_bit/top_left_corner = 0
+2:3/5/terrains_peering_bit/top_side = 0
+2:3/5/terrains_peering_bit/top_right_corner = 0
+3:3/next_alternative_id = 2
+3:3/0 = 0
+3:3/0/terrain_set = 0
+3:3/0/terrain = 0
+3:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_by4n8")
+3:3/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_ru1yo")
+3:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+3:3/0/terrains_peering_bit/bottom_side = 0
+3:3/0/terrains_peering_bit/bottom_left_corner = 0
+3:3/0/terrains_peering_bit/left_side = 0
+3:3/0/terrains_peering_bit/top_left_corner = 0
+3:3/0/terrains_peering_bit/top_side = 0
+3:3/1 = 1
+3:3/1/flip_v = true
+3:3/1/terrain_set = 0
+3:3/1/terrain = 0
+3:3/1/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_kj7tv")
+3:3/1/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_vok1k")
+3:3/1/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+3:3/1/terrains_peering_bit/bottom_side = 0
+3:3/1/terrains_peering_bit/bottom_left_corner = 0
+3:3/1/terrains_peering_bit/left_side = 0
+3:3/1/terrains_peering_bit/top_left_corner = 0
+3:3/1/terrains_peering_bit/top_side = 0
+4:3/0 = 0
+4:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+4:3/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+4:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+5:3/0 = 0
+5:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+5:3/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+5:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+6:3/0 = 0
+6:3/0/terrain_set = 0
+6:3/0/terrain = 0
+6:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+6:3/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+6:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+6:3/0/terrains_peering_bit/right_side = 0
+6:3/0/terrains_peering_bit/bottom_side = 0
+6:3/0/terrains_peering_bit/bottom_left_corner = 0
+6:3/0/terrains_peering_bit/left_side = 0
+6:3/0/terrains_peering_bit/top_left_corner = 0
+6:3/0/terrains_peering_bit/top_side = 0
+6:3/0/terrains_peering_bit/top_right_corner = 0
+7:3/0 = 0
+7:3/0/terrain_set = 0
+7:3/0/terrain = 0
+7:3/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+7:3/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+7:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+7:3/0/terrains_peering_bit/right_side = 0
+7:3/0/terrains_peering_bit/bottom_right_corner = 0
+7:3/0/terrains_peering_bit/bottom_side = 0
+7:3/0/terrains_peering_bit/left_side = 0
+7:3/0/terrains_peering_bit/top_left_corner = 0
+7:3/0/terrains_peering_bit/top_side = 0
+7:3/0/terrains_peering_bit/top_right_corner = 0
+8:3/0 = 0
+9:3/0 = 0
+10:3/0 = 0
+11:3/0 = 0
+0:4/0 = 0
+1:4/0 = 0
+1:4/0/terrain_set = 0
+1:4/0/terrain = 0
+1:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_by4n8")
+1:4/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_g011h")
+1:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+1:4/0/terrains_peering_bit/right_side = 0
+1:4/0/terrains_peering_bit/top_side = 0
+1:4/0/terrains_peering_bit/top_right_corner = 0
+0:5/0 = 0
+1:5/0 = 0
+2:4/next_alternative_id = 2
+2:4/0 = 0
+2:4/0/terrain_set = 0
+2:4/0/terrain = 0
+2:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_by4n8")
+2:4/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_f77ak")
+2:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+2:4/0/terrains_peering_bit/right_side = 0
+2:4/0/terrains_peering_bit/left_side = 0
+2:4/0/terrains_peering_bit/top_left_corner = 0
+2:4/0/terrains_peering_bit/top_side = 0
+2:4/0/terrains_peering_bit/top_right_corner = 0
+2:4/1 = 1
+2:4/1/flip_h = true
+2:4/1/terrain_set = 0
+2:4/1/terrain = 0
+2:4/1/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_kj7tv")
+2:4/1/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_ro6yg")
+2:4/1/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16)
+2:4/1/terrains_peering_bit/right_side = 0
+2:4/1/terrains_peering_bit/left_side = 0
+2:4/1/terrains_peering_bit/top_left_corner = 0
+2:4/1/terrains_peering_bit/top_side = 0
+2:4/1/terrains_peering_bit/top_right_corner = 0
+3:4/0 = 0
+3:4/0/terrain_set = 0
+3:4/0/terrain = 0
+3:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_by4n8")
+3:4/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_flqmo")
+3:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+3:4/0/terrains_peering_bit/left_side = 0
+3:4/0/terrains_peering_bit/top_left_corner = 0
+3:4/0/terrains_peering_bit/top_side = 0
+6:4/0 = 0
+6:4/0/terrain_set = 0
+6:4/0/terrain = 0
+6:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+6:4/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+6:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+6:4/0/terrains_peering_bit/right_side = 0
+6:4/0/terrains_peering_bit/bottom_right_corner = 0
+6:4/0/terrains_peering_bit/bottom_side = 0
+6:4/0/terrains_peering_bit/bottom_left_corner = 0
+6:4/0/terrains_peering_bit/left_side = 0
+6:4/0/terrains_peering_bit/top_left_corner = 0
+6:4/0/terrains_peering_bit/top_side = 0
+7:4/0 = 0
+7:4/0/terrain_set = 0
+7:4/0/terrain = 0
+7:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+7:4/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+7:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+7:4/0/terrains_peering_bit/right_side = 0
+7:4/0/terrains_peering_bit/bottom_right_corner = 0
+7:4/0/terrains_peering_bit/bottom_side = 0
+7:4/0/terrains_peering_bit/bottom_left_corner = 0
+7:4/0/terrains_peering_bit/left_side = 0
+7:4/0/terrains_peering_bit/top_side = 0
+7:4/0/terrains_peering_bit/top_right_corner = 0
+4:4/0 = 0
+4:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+4:4/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+4:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+5:4/0 = 0
+5:4/0/occlusion_layer_0/polygon_0/polygon = SubResource("OccluderPolygon2D_njrqr")
+5:4/0/occlusion_layer_1/polygon_0/polygon = SubResource("OccluderPolygon2D_o2foe")
+5:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, -16, 16, 16, 16, 16, -16)
+
+[resource]
+tile_size = Vector2i(32, 32)
+occlusion_layer_0/light_mask = 1
+occlusion_layer_1/light_mask = 2
+physics_layer_0/collision_layer = 1
+terrain_set_0/mode = 0
+terrain_set_0/terrain_0/name = "Brick"
+terrain_set_0/terrain_0/color = Color(0.5, 0.34375, 0.25, 1)
+sources/0 = SubResource("TileSetAtlasSource_blkrv")
diff --git a/src/library/LevelPattern.cs b/src/library/LevelPattern.cs
new file mode 100644
index 0000000..25a5985
--- /dev/null
+++ b/src/library/LevelPattern.cs
@@ -0,0 +1,105 @@
+using Godot;
+using System;
+using System.Collections.Generic;
+
+#nullable enable
+public class LevelPattern {
+ public TileMapPattern Level { get; }
+
+ public TileSet Solid1 { get; }
+ public TileSet? Solid2 { get; init; }
+
+ public TileSet Background1 { get; }
+ public TileSet? Background2 { get; init; }
+
+ public record Connection(int Length, bool IsHorizontal) { public bool IsVertical => !IsHorizontal; }
+
+ public Connection[] Connections { get; }
+
+ public Dictionary TranslationMap { get; }
+
+ public class Template {
+ public readonly record struct Solid(int Id);
+ public readonly record struct Background(int Id);
+ public readonly record struct Enemy(int Id);
+ public readonly record struct Item(int Id);
+ public readonly record struct Decoration(int Id);
+ public readonly record struct MultiTile(Tile NonOverlappable, OverlappableTile[] Overlappable);
+ public readonly record struct Any;
+ public readonly union OverlappableTile(Enemy, Item, Decoration);
+ public readonly union Tile(Solid, Any, Background, Enemy, Item, Decoration, MultiTile) {
+ public bool IsAir() {
+ if (this is Any or Background or Enemy or Item or Decoration) return true;
+ if (this is MultiTile mt) {
+ do {
+ if (mt.NonOverlappable is MultiTile _mt)
+ mt = _mt;
+ else
+ return mt.NonOverlappable is Any or Background or Enemy or Item or Decoration;
+ } while (true);
+ }
+ return false;
+ }
+ }
+ }
+
+ public LevelPattern(TileMapPattern pattern, TileSet solid1, TileSet background1) {
+ Level = pattern;
+ Solid1 = solid1;
+ Background1 = background1;
+
+ // Connections = CalculateConnections(pattern);
+ }
+
+
+ record struct ScanInfo(int XFrom, int XTo, int YFrom, int YTo);
+ public static Connection[] CalculateConnections(TileMapPattern pattern, Dictionary translations) {
+ var current = Vector2I.Zero;
+ var size = pattern.GetSize();
+
+ // scan borders
+ Span borders = stackalloc ScanInfo[] {
+ new ScanInfo(current.X, size.X, current.Y, current.Y), // top-horiz
+ new ScanInfo(current.X, current.X, current.Y, size.Y), // left-vert
+ new ScanInfo(current.X, size.X, size.Y, size.Y), // bottom-horiz
+ new ScanInfo(size.X, size.X, current.Y, size.Y) // right-vert
+ };
+
+ List connections = [];
+ foreach(var border in borders) {
+ int xrun = 0;
+ for(int x = border.XFrom; x < border.XTo; x++) {
+ int yrun = 0;
+ for(int y = border.YFrom; y < border.YTo; y++) {
+ var cell = translations[pattern.GetCellAtlasCoords(new Vector2I(x, y))];
+ if (cell.IsAir())
+ yrun++;
+ else if (yrun > 0) {
+ connections.Add(new Connection(
+ yrun, IsHorizontal: false
+ ));
+ yrun = 0;
+ }
+ }
+
+ if (border.YFrom == border.YTo) {
+ // horizontal run
+ var cell = translations[pattern.GetCellAtlasCoords(new Vector2I(x, border.YFrom))];
+ if (cell.IsAir())
+ xrun++;
+ else if (xrun > 0) {
+ connections.Add(new Connection(
+ xrun, IsHorizontal: true
+ ));
+ xrun = 0;
+ }
+ }
+ }
+ }
+
+ return connections.ToArray();
+ }
+
+}
+
+#nullable restore
\ No newline at end of file
diff --git a/src/library/LevelPattern.cs.uid b/src/library/LevelPattern.cs.uid
new file mode 100644
index 0000000..1d7c3e9
--- /dev/null
+++ b/src/library/LevelPattern.cs.uid
@@ -0,0 +1 @@
+uid://b4fmcn1xf2rue
diff --git a/src/library/SymbolicTileMap.cs b/src/library/SymbolicTileMap.cs
new file mode 100644
index 0000000..6c750da
--- /dev/null
+++ b/src/library/SymbolicTileMap.cs
@@ -0,0 +1,4 @@
+
+public class SymbolicTileMap {
+
+}
\ No newline at end of file
diff --git a/src/library/SymbolicTileMap.cs.uid b/src/library/SymbolicTileMap.cs.uid
new file mode 100644
index 0000000..f89d036
--- /dev/null
+++ b/src/library/SymbolicTileMap.cs.uid
@@ -0,0 +1 @@
+uid://ca1802nst4udo
diff --git a/src/library/UnionSupport.cs b/src/library/UnionSupport.cs
new file mode 100644
index 0000000..16deda7
--- /dev/null
+++ b/src/library/UnionSupport.cs
@@ -0,0 +1,6 @@
+namespace System.Runtime.CompilerServices {
+ public interface IUnion { }
+
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class UnionAttribute : Attribute { }
+}
diff --git a/src/library/UnionSupport.cs.uid b/src/library/UnionSupport.cs.uid
new file mode 100644
index 0000000..876e303
--- /dev/null
+++ b/src/library/UnionSupport.cs.uid
@@ -0,0 +1 @@
+uid://cgpdhgigu3oo4