Initial commit
This commit is contained in:
		
						commit
						235f84833f
					
				| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
/target
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
{
 | 
			
		||||
    // Use IntelliSense to learn about possible attributes.
 | 
			
		||||
    // Hover to view descriptions of existing attributes.
 | 
			
		||||
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 | 
			
		||||
    "version": "0.2.0",
 | 
			
		||||
    "configurations": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "lldb",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "name": "Debug executable 'metodol_projekt'",
 | 
			
		||||
            "cargo": {
 | 
			
		||||
                "args": [
 | 
			
		||||
                    "build",
 | 
			
		||||
                    "--bin=metodol_projekt",
 | 
			
		||||
                    "--package=metodol_projekt"
 | 
			
		||||
                ],
 | 
			
		||||
                "filter": {
 | 
			
		||||
                    "name": "metodol_projekt",
 | 
			
		||||
                    "kind": "bin"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "args": [],
 | 
			
		||||
            "cwd": "${workspaceFolder}"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "type": "lldb",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "name": "Debug unit tests in executable 'metodol_projekt'",
 | 
			
		||||
            "cargo": {
 | 
			
		||||
                "args": [
 | 
			
		||||
                    "test",
 | 
			
		||||
                    "--no-run",
 | 
			
		||||
                    "--bin=metodol_projekt",
 | 
			
		||||
                    "--package=metodol_projekt"
 | 
			
		||||
                ],
 | 
			
		||||
                "filter": {
 | 
			
		||||
                    "name": "metodol_projekt",
 | 
			
		||||
                    "kind": "bin"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "args": [],
 | 
			
		||||
            "cwd": "${workspaceFolder}"
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,578 @@
 | 
			
		|||
# This file is automatically @generated by Cargo.
 | 
			
		||||
# It is not intended for manual editing.
 | 
			
		||||
version = 4
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "android-tzdata"
 | 
			
		||||
version = "0.1.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "android_system_properties"
 | 
			
		||||
version = "0.1.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "libc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "autocfg"
 | 
			
		||||
version = "1.5.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bitflags"
 | 
			
		||||
version = "2.9.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bumpalo"
 | 
			
		||||
version = "3.19.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "cc"
 | 
			
		||||
version = "1.2.27"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "shlex",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "cfg-if"
 | 
			
		||||
version = "1.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "chrono"
 | 
			
		||||
version = "0.4.41"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "android-tzdata",
 | 
			
		||||
 "iana-time-zone",
 | 
			
		||||
 "js-sys",
 | 
			
		||||
 "num-traits",
 | 
			
		||||
 "wasm-bindgen",
 | 
			
		||||
 "windows-link",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "colored"
 | 
			
		||||
version = "3.0.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-sys 0.59.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "core-foundation-sys"
 | 
			
		||||
version = "0.8.7"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "errno"
 | 
			
		||||
version = "0.3.12"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "libc",
 | 
			
		||||
 "windows-sys 0.59.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "iana-time-zone"
 | 
			
		||||
version = "0.1.63"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "android_system_properties",
 | 
			
		||||
 "core-foundation-sys",
 | 
			
		||||
 "iana-time-zone-haiku",
 | 
			
		||||
 "js-sys",
 | 
			
		||||
 "log",
 | 
			
		||||
 "wasm-bindgen",
 | 
			
		||||
 "windows-core",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "iana-time-zone-haiku"
 | 
			
		||||
version = "0.1.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "itoa"
 | 
			
		||||
version = "1.0.15"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "js-sys"
 | 
			
		||||
version = "0.3.77"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "once_cell",
 | 
			
		||||
 "wasm-bindgen",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "lazy_static"
 | 
			
		||||
version = "1.5.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "libc"
 | 
			
		||||
version = "0.2.174"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "linux-raw-sys"
 | 
			
		||||
version = "0.4.15"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "log"
 | 
			
		||||
version = "0.4.27"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "memchr"
 | 
			
		||||
version = "2.7.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "metodol_projekt"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "chrono",
 | 
			
		||||
 "colored",
 | 
			
		||||
 "lazy_static",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "serde_json",
 | 
			
		||||
 "signal-hook",
 | 
			
		||||
 "terminal_size",
 | 
			
		||||
 "text_io",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "num-traits"
 | 
			
		||||
version = "0.2.19"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "once_cell"
 | 
			
		||||
version = "1.21.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "proc-macro2"
 | 
			
		||||
version = "1.0.95"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "quote"
 | 
			
		||||
version = "1.0.40"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rustix"
 | 
			
		||||
version = "0.38.44"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bitflags",
 | 
			
		||||
 "errno",
 | 
			
		||||
 "libc",
 | 
			
		||||
 "linux-raw-sys",
 | 
			
		||||
 "windows-sys 0.59.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rustversion"
 | 
			
		||||
version = "1.0.21"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ryu"
 | 
			
		||||
version = "1.0.20"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde"
 | 
			
		||||
version = "1.0.219"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "serde_derive",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde_derive"
 | 
			
		||||
version = "1.0.219"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde_json"
 | 
			
		||||
version = "1.0.140"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "itoa",
 | 
			
		||||
 "memchr",
 | 
			
		||||
 "ryu",
 | 
			
		||||
 "serde",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "shlex"
 | 
			
		||||
version = "1.3.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "signal-hook"
 | 
			
		||||
version = "0.3.18"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "libc",
 | 
			
		||||
 "signal-hook-registry",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "signal-hook-registry"
 | 
			
		||||
version = "1.4.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "libc",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
version = "2.0.103"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "terminal_size"
 | 
			
		||||
version = "0.3.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "rustix",
 | 
			
		||||
 "windows-sys 0.48.0",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "text_io"
 | 
			
		||||
version = "0.1.13"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4d8d3ca3b06292094e03841d8995e910712d2a10b5869c8f9725385b29761115"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-ident"
 | 
			
		||||
version = "1.0.18"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "wasm-bindgen"
 | 
			
		||||
version = "0.2.100"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "once_cell",
 | 
			
		||||
 "rustversion",
 | 
			
		||||
 "wasm-bindgen-macro",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "wasm-bindgen-backend"
 | 
			
		||||
version = "0.2.100"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bumpalo",
 | 
			
		||||
 "log",
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
 "wasm-bindgen-shared",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "wasm-bindgen-macro"
 | 
			
		||||
version = "0.2.100"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "quote",
 | 
			
		||||
 "wasm-bindgen-macro-support",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "wasm-bindgen-macro-support"
 | 
			
		||||
version = "0.2.100"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
 "wasm-bindgen-backend",
 | 
			
		||||
 "wasm-bindgen-shared",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "wasm-bindgen-shared"
 | 
			
		||||
version = "0.2.100"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-core"
 | 
			
		||||
version = "0.61.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-implement",
 | 
			
		||||
 "windows-interface",
 | 
			
		||||
 "windows-link",
 | 
			
		||||
 "windows-result",
 | 
			
		||||
 "windows-strings",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-implement"
 | 
			
		||||
version = "0.60.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-interface"
 | 
			
		||||
version = "0.59.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-link"
 | 
			
		||||
version = "0.1.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-result"
 | 
			
		||||
version = "0.3.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-link",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-strings"
 | 
			
		||||
version = "0.4.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-link",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-sys"
 | 
			
		||||
version = "0.48.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-targets 0.48.5",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-sys"
 | 
			
		||||
version = "0.59.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows-targets 0.52.6",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-targets"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows_aarch64_gnullvm 0.48.5",
 | 
			
		||||
 "windows_aarch64_msvc 0.48.5",
 | 
			
		||||
 "windows_i686_gnu 0.48.5",
 | 
			
		||||
 "windows_i686_msvc 0.48.5",
 | 
			
		||||
 "windows_x86_64_gnu 0.48.5",
 | 
			
		||||
 "windows_x86_64_gnullvm 0.48.5",
 | 
			
		||||
 "windows_x86_64_msvc 0.48.5",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-targets"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows_aarch64_gnullvm 0.52.6",
 | 
			
		||||
 "windows_aarch64_msvc 0.52.6",
 | 
			
		||||
 "windows_i686_gnu 0.52.6",
 | 
			
		||||
 "windows_i686_gnullvm",
 | 
			
		||||
 "windows_i686_msvc 0.52.6",
 | 
			
		||||
 "windows_x86_64_gnu 0.52.6",
 | 
			
		||||
 "windows_x86_64_gnullvm 0.52.6",
 | 
			
		||||
 "windows_x86_64_msvc 0.52.6",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_aarch64_gnullvm"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_aarch64_gnullvm"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_aarch64_msvc"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_aarch64_msvc"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_gnu"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_gnu"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_gnullvm"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_msvc"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_msvc"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_gnu"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_gnu"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_gnullvm"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_gnullvm"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_msvc"
 | 
			
		||||
version = "0.48.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_msvc"
 | 
			
		||||
version = "0.52.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
[package]
 | 
			
		||||
name = "metodol_projekt"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
 | 
			
		||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
serde = { version = "1.0.219", features = ["derive"] }
 | 
			
		||||
serde_json = "1.0.140"
 | 
			
		||||
terminal_size = "0.3.0"
 | 
			
		||||
signal-hook = "0.3"
 | 
			
		||||
text_io = "0.1.13"
 | 
			
		||||
lazy_static = "1.5.0"
 | 
			
		||||
colored = "3.0.0"
 | 
			
		||||
chrono = "0.4.41"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,224 @@
 | 
			
		|||
{
 | 
			
		||||
    "version": 1,
 | 
			
		||||
    "maps": [
 | 
			
		||||
        {
 | 
			
		||||
            "default": true,
 | 
			
		||||
            "map_required": true,
 | 
			
		||||
            "starting_location": [3, 6],
 | 
			
		||||
            "name": "Mystic Forest",
 | 
			
		||||
            "description": "A mystical forest filled with ancient trees and hidden secrets.",
 | 
			
		||||
            "id": "mystic_forest",
 | 
			
		||||
            "width": 10,
 | 
			
		||||
            "height": 10,
 | 
			
		||||
            "events": [
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "npc",
 | 
			
		||||
                    "command_id": "oak",
 | 
			
		||||
                    "name": "Elder Oak",
 | 
			
		||||
                    "location": [2, 3],
 | 
			
		||||
                    "dialogue": [
 | 
			
		||||
                        "You meet the Elder Oak, a towering tree with a face carved into its bark.",
 | 
			
		||||
                        "<i>Welcome to the Mystic Forest, young traveler.</i>",
 | 
			
		||||
                        "<i>Many secrets lie within these woods.</i>",
 | 
			
		||||
                        "<i>Seek the hidden glades and you may find treasures untold.</i>"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "item",
 | 
			
		||||
                    "command_id": "scroll",
 | 
			
		||||
                    "name": "Ancient Scroll",
 | 
			
		||||
                    "description": "A scroll containing secrets of the forest.",
 | 
			
		||||
                    "location": [7, 8]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "location",
 | 
			
		||||
                    "command_id": "mystic_cottage",
 | 
			
		||||
                    "name": "Mystic Cottage",
 | 
			
		||||
                    "description": "A small cottage made of enchanted wood, home to a wise hermit.",
 | 
			
		||||
                    "location": [2, 6]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "tilemap": [
 | 
			
		||||
                ["water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border"],
 | 
			
		||||
                ["water_border", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "water", "house", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "water_border"],
 | 
			
		||||
                ["water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border", "water_border"]
 | 
			
		||||
            ],
 | 
			
		||||
            "tiles": {
 | 
			
		||||
                "house": {
 | 
			
		||||
                    "name": "Mystic Cottage",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "H",
 | 
			
		||||
                        "color": [139, 69, 19]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A small cottage made of enchanted wood, home to a wise hermit.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H"],
 | 
			
		||||
                        ["H", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "H"],
 | 
			
		||||
                        ["H", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "H"],
 | 
			
		||||
                        ["H", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "H"],
 | 
			
		||||
                        ["H", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "H"],
 | 
			
		||||
                        ["H", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "H"],
 | 
			
		||||
                        ["H", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "H"],
 | 
			
		||||
                        ["H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "water_border": {
 | 
			
		||||
                    "name": "Water Border",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "~",
 | 
			
		||||
                        "color": [0, 0, 255]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": false,
 | 
			
		||||
                    "description": "A border of water surrounding the Mystic Forest.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["~", "~", "~", "~", "~", "~", "~", "~", "~", "~"],
 | 
			
		||||
                        ["~", " ", " ", " ", " ", " ", " ", " ", " ", "~"],
 | 
			
		||||
                        ["~", " ", " ", " ", " ", " ", " ", " ", " ", "~"],
 | 
			
		||||
                        ["~", " ", " ", " ", " ", " ", " ", " ", " ", "~"],
 | 
			
		||||
                        ["~", " ", " ", " ", " ", " ", " ", " ", " ", "~"],
 | 
			
		||||
                        ["~", " ", " ", " ", " ", " ", " ", " ", " ", "~"],
 | 
			
		||||
                        ["~", " ", " ", " ", " ", " ", " ", " ", " ", "~"],
 | 
			
		||||
                        ["~", "~", "~", "~", "~", "~", "~", "~", "~", "~"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "water": {
 | 
			
		||||
                    "name": "Water",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "~",
 | 
			
		||||
                        "color": [0, 128, 255]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A serene body of water, perfect for fishing or swimming.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~"],
 | 
			
		||||
                        [" ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " "],
 | 
			
		||||
                        [" ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " "],
 | 
			
		||||
                        ["~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~"],
 | 
			
		||||
                        [" ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " "],
 | 
			
		||||
                        [" ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " "],
 | 
			
		||||
                        ["~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~"],
 | 
			
		||||
                        [" ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " ", "~", " ", " "]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "grass": {
 | 
			
		||||
                    "name": "Grass",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "#",
 | 
			
		||||
                        "color": [0, 255, 0]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "Lush green grass, perfect for a picnic or a stroll.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"]
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, {
 | 
			
		||||
            "default": false,
 | 
			
		||||
            "map_required": false,
 | 
			
		||||
            "starting_location": [2, 4],
 | 
			
		||||
            "name": "Mystic Cottage",
 | 
			
		||||
            "description": "A small cottage made of enchanted wood, home to a wise hermit.",
 | 
			
		||||
            "id": "mystic_cottage",
 | 
			
		||||
            "width": 5,
 | 
			
		||||
            "height": 5,
 | 
			
		||||
            "events": [
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "item",
 | 
			
		||||
                    "command_id": "map",
 | 
			
		||||
                    "name": "Mystic Forest Map",
 | 
			
		||||
                    "description": "A map of the Mystic Forest.",
 | 
			
		||||
                    "location": [7, 8]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "location",
 | 
			
		||||
                    "command_id": "mystic_forest",
 | 
			
		||||
                    "name": "Door",
 | 
			
		||||
                    "description": "A small wooden door leading to the outside.",
 | 
			
		||||
                    "location": [2, 4]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "tilemap": [
 | 
			
		||||
                ["wall", "wall", "wall", "wall", "wall"],
 | 
			
		||||
                ["wall", "floor", "floor", "floor", "wall"],
 | 
			
		||||
                ["wall", "floor", "floor", "floor", "wall"],
 | 
			
		||||
                ["wall", "floor", "floor", "floor", "wall"],
 | 
			
		||||
                ["wall", "wall", "door", "wall", "wall"]
 | 
			
		||||
            ],
 | 
			
		||||
            "tiles": {
 | 
			
		||||
                "wall": {
 | 
			
		||||
                    "name": "Wall",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "#",
 | 
			
		||||
                        "color": [0, 0, 255]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": false,
 | 
			
		||||
                    "description": "A sturdy wall made of enchanted wood, protecting the cottage.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "floor": {
 | 
			
		||||
                    "name": "Floor",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "+",
 | 
			
		||||
                        "color": [237, 207, 147]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A cozy wooden floor, warm and inviting.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"],
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"],
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"],
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "door": {
 | 
			
		||||
                    "name": "Door",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "@",
 | 
			
		||||
                        "color": [128, 0, 0]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A small wooden door leading to the outside.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "+", "-", "-", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "|", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@"]
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,330 @@
 | 
			
		|||
{
 | 
			
		||||
    "version": 1,
 | 
			
		||||
    "maps": [
 | 
			
		||||
        {
 | 
			
		||||
            "default": true,
 | 
			
		||||
            "map_required": true,
 | 
			
		||||
            "starting_location": [1, 14],
 | 
			
		||||
            "name": "test2",
 | 
			
		||||
            "description": "testtttt2",
 | 
			
		||||
            "id": "test2",
 | 
			
		||||
            "width": 16,
 | 
			
		||||
            "height": 16,
 | 
			
		||||
            "events": [
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "location",
 | 
			
		||||
                    "command_id": "mystic_cottage",
 | 
			
		||||
                    "name": "Mystic Cottage",
 | 
			
		||||
                    "description": "A small cottage made of enchanted wood, home to a wise hermit.",
 | 
			
		||||
                    "location": [8, 4]
 | 
			
		||||
                }, {
 | 
			
		||||
                    "evt_type": "item",
 | 
			
		||||
                    "command_id": "gate_key",
 | 
			
		||||
                    "name": "Gate key",
 | 
			
		||||
                    "description": "A key that unlocks the gate.",
 | 
			
		||||
                    "location": [5, 15]
 | 
			
		||||
                }, {
 | 
			
		||||
                    "evt_type": "lock",
 | 
			
		||||
                    "command_id": "gate_key",
 | 
			
		||||
                    "name": "Gate",
 | 
			
		||||
                    "description": "This gate is locked. You need a key to open it.",
 | 
			
		||||
                    "location": [7, 13]
 | 
			
		||||
                }, {
 | 
			
		||||
                    "evt_type": "lock",
 | 
			
		||||
                    "command_id": "gate_key",
 | 
			
		||||
                    "name": "Gate",
 | 
			
		||||
                    "description": "This gate is locked. You need a key to open it.",
 | 
			
		||||
                    "location": [8, 13]
 | 
			
		||||
                }, {
 | 
			
		||||
                    "evt_type": "item",
 | 
			
		||||
                    "command_id": "map",
 | 
			
		||||
                    "name": "Map",
 | 
			
		||||
                    "description": "A map of the Mystic Forest.",
 | 
			
		||||
                    "location": [8, 14]
 | 
			
		||||
                }, {
 | 
			
		||||
                    "evt_type": "npc",
 | 
			
		||||
                    "command_id": "czesio",
 | 
			
		||||
                    "name": "Czesio",
 | 
			
		||||
                    "description": "A friendly NPC who can help you with your journey.",
 | 
			
		||||
                    "location": [0, 14]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "tilemap": [
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "fence", "fence", "fence", "fence", "fence", "fence", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "house", "house", "grass", "grass", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "house", "house_entry", "grass", "grass", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass", "wall", "wall", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "grass", "grass", "grass", "grass", "wall", "wall", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "fence", "fence", "gate", "fence", "gate", "gate", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "wall", "wall", "grass", "grass", "concrete", "concrete", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "wall", "wall", "grass", "grass", "concrete", "concrete", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["grass", "grass", "grass", "grass", "fence", "wall", "wall", "grass", "grass", "concrete", "concrete", "fence", "grass", "grass", "grass", "grass"],
 | 
			
		||||
                ["fence", "fence", "fence", "fence", "fence", "wall", "wall", "gate", "gate", "wall", "wall", "fence", "fence", "fence", "fence", "fence"],
 | 
			
		||||
                ["road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road"],
 | 
			
		||||
                ["road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road", "road"]
 | 
			
		||||
            ],
 | 
			
		||||
            "tiles": {
 | 
			
		||||
                "road": {
 | 
			
		||||
                    "name": "Road",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "=",
 | 
			
		||||
                        "color": [64, 64, 64]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "Part of road.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="],
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="],
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="],
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="],
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="],
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="],
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="],
 | 
			
		||||
                        ["=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "=", "="]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "fence": {
 | 
			
		||||
                    "name": "Fence",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "+",
 | 
			
		||||
                        "color": [75, 26, 16]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": false,
 | 
			
		||||
                    "description": "A wooden fence, keeping the area secure.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+"],
 | 
			
		||||
                        ["+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "gate": {
 | 
			
		||||
                    "name": "Fence gate",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "@",
 | 
			
		||||
                        "color": [75, 26, 16]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A wooden gate in the fence, allowing passage.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "@", " ", " ", "@", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "@", " ", " ", "@", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", "+", "+", "+", "+", "+", "@", " ", " ", "@", "+", "+", "+", "+", "+", "+"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "@", " ", " ", "@", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", " ", " ", "|", " ", " ", "@", " ", " ", "@", " ", " ", "|", " ", " ", "|"],
 | 
			
		||||
                        ["|", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+"],
 | 
			
		||||
                        ["+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+", "+"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "wall": {
 | 
			
		||||
                    "name": "Wall",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "#",
 | 
			
		||||
                        "color": [204, 204, 204]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": false,
 | 
			
		||||
                    "description": "A sturdy wall made of stone, providing protection.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "concrete": {
 | 
			
		||||
                    "name": "Concrete",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": ".",
 | 
			
		||||
                        "color": [224, 224, 224]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A smooth concrete surface, often used in urban areas.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."],
 | 
			
		||||
                        [".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "."]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "grass": {
 | 
			
		||||
                    "name": "Grass",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": ",",
 | 
			
		||||
                        "color": [0, 255, 0]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "Lush green grass, perfect for a picnic or a stroll.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "house": {
 | 
			
		||||
                    "name": "House",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "#",
 | 
			
		||||
                        "color": [153, 111, 41]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": false,
 | 
			
		||||
                    "description": "A cozy little house made of enchanted wood, home to a wise hermit.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "house_entry": {
 | 
			
		||||
                    "name": "House door",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "@",
 | 
			
		||||
                        "color": [189, 135, 48]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A small wooden door leading to the inside of the house.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"],
 | 
			
		||||
                        ["#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " "],
 | 
			
		||||
                        [" ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#", " ", "#"]
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "npcs": {
 | 
			
		||||
                "czesio": {
 | 
			
		||||
                    "name": "Czesio",
 | 
			
		||||
                    "description": "Dzieńdobry",
 | 
			
		||||
                    "dialogue": [
 | 
			
		||||
                        "Hello adventurer!",
 | 
			
		||||
                        "What do you need?",
 | 
			
		||||
                        "#(00FF00)1. Nothing",
 | 
			
		||||
                        "#(00FF00)2. Gate key"
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, {
 | 
			
		||||
            "default": false,
 | 
			
		||||
            "map_required": false,
 | 
			
		||||
            "starting_location": [2, 4],
 | 
			
		||||
            "name": "Mystic Cottage",
 | 
			
		||||
            "description": "A small cottage made of enchanted wood, home to a wise hermit.",
 | 
			
		||||
            "id": "mystic_cottage",
 | 
			
		||||
            "width": 5,
 | 
			
		||||
            "height": 5,
 | 
			
		||||
            "events": [
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "item",
 | 
			
		||||
                    "command_id": "map",
 | 
			
		||||
                    "name": "Mystic Forest Map",
 | 
			
		||||
                    "description": "A map of the Mystic Forest.",
 | 
			
		||||
                    "location": [7, 8]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "evt_type": "location",
 | 
			
		||||
                    "command_id": "test2",
 | 
			
		||||
                    "name": "Door",
 | 
			
		||||
                    "description": "A small wooden door leading to the outside.",
 | 
			
		||||
                    "location": [2, 4]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "tilemap": [
 | 
			
		||||
                ["wall", "wall", "wall", "wall", "wall"],
 | 
			
		||||
                ["wall", "floor", "floor", "floor", "wall"],
 | 
			
		||||
                ["wall", "floor", "floor", "floor", "wall"],
 | 
			
		||||
                ["wall", "floor", "floor", "floor", "wall"],
 | 
			
		||||
                ["wall", "wall", "door", "wall", "wall"]
 | 
			
		||||
            ],
 | 
			
		||||
            "tiles": {
 | 
			
		||||
                "wall": {
 | 
			
		||||
                    "name": "Wall",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "#",
 | 
			
		||||
                        "color": [0, 0, 255]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": false,
 | 
			
		||||
                    "description": "A sturdy wall made of enchanted wood, protecting the cottage.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
 | 
			
		||||
                        ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "floor": {
 | 
			
		||||
                    "name": "Floor",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "+",
 | 
			
		||||
                        "color": [237, 207, 147]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A cozy wooden floor, warm and inviting.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"],
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"],
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"],
 | 
			
		||||
                        ["+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " "],
 | 
			
		||||
                        [" ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+", " ", "+"]
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                "door": {
 | 
			
		||||
                    "name": "Door",
 | 
			
		||||
                    "icon": {
 | 
			
		||||
                        "char": "@",
 | 
			
		||||
                        "color": [128, 0, 0]
 | 
			
		||||
                    },
 | 
			
		||||
                    "walkable": true,
 | 
			
		||||
                    "description": "A small wooden door leading to the outside.",
 | 
			
		||||
                    "bitmap": [
 | 
			
		||||
                        ["@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "+", "-", "-", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "|", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "@"],
 | 
			
		||||
                        ["@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@", "@"]
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "npcs": {}
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
{"coords":{"mystic_cottage":[2,4],"test2":[9,4]},"current_map_id":"test2","flags":{"gate_opened":true},"health":100,"inventory":["map","gate_key"],"last_save":"2025-07-11 14:11:52","lines_of_text":["> save progress","#(00FF00)Progress restored","> go d","You moved into grass tile","> go r","You moved into grass tile","> go r","You moved into grass tile","> go u","You moved into house_entry tile","> enter house","You entered a location.","> go u","You moved into floor tile","> go d","You moved into door tile","> exit house","You exited a location.","> go r","You moved into grass tile","> save progress"],"map_pack":"map","player_name":"Kapitan Bomba","stamina":50,"version":1}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
{
 | 
			
		||||
    "version": 1,
 | 
			
		||||
    "map_pack": "map",
 | 
			
		||||
    "player_name": "Kapitan Bomba",
 | 
			
		||||
    "last_save": "2025-06-18T12:00:00Z",
 | 
			
		||||
    "current_map_id": "test2",
 | 
			
		||||
    "health": 100,
 | 
			
		||||
    "mana": 50,
 | 
			
		||||
    "coords": {
 | 
			
		||||
        "test2": [5, 1]
 | 
			
		||||
    },
 | 
			
		||||
    "inventory": [
 | 
			
		||||
        "map",
 | 
			
		||||
        "gate_key"
 | 
			
		||||
    ],
 | 
			
		||||
    "flags": {
 | 
			
		||||
        "gate_opened": true
 | 
			
		||||
    },
 | 
			
		||||
    "lines_of_text": [
 | 
			
		||||
        "1",
 | 
			
		||||
        "2",
 | 
			
		||||
        "3"
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
pub mod player;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
use crate::{structs::json::Tile, tui::text::add_text, utils::maps::{get_current_map, get_map_events}};
 | 
			
		||||
 | 
			
		||||
pub fn move_player(x: i8, y: i8, dry_run: bool) -> bool {
 | 
			
		||||
    let mut all_coords = crate::PLAYER_COORDS.lock().unwrap();
 | 
			
		||||
    let player_coords = *all_coords.get(get_current_map().unwrap().id.as_str()).unwrap();
 | 
			
		||||
    // let mut new_coords = (player_coords.0 + x, player_coords.1 + y);
 | 
			
		||||
    let new_coords = (
 | 
			
		||||
        player_coords.0.wrapping_add_signed(x as i8),
 | 
			
		||||
        player_coords.1.wrapping_add_signed(y as i8),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let map = get_current_map().unwrap();
 | 
			
		||||
 | 
			
		||||
    let width = map.width as u8;
 | 
			
		||||
    let height = map.height as u8;
 | 
			
		||||
    
 | 
			
		||||
    // check if new coordinates are within bounds
 | 
			
		||||
    if new_coords.0 >= width || new_coords.1 >= height {
 | 
			
		||||
        return false; // Out of bounds, do not move
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // check if new coordinates are onto walkable tile
 | 
			
		||||
    let tile_name = map.tilemap.get(new_coords.1 as usize)
 | 
			
		||||
        .and_then(|row| row.get(new_coords.0 as usize))
 | 
			
		||||
        .and_then(|tile| Some(tile.as_str()))
 | 
			
		||||
        .unwrap_or_default();
 | 
			
		||||
 | 
			
		||||
    let walkable = map.tiles.get(tile_name)
 | 
			
		||||
        .and_then(|tile| Some(tile.walkable))
 | 
			
		||||
        .unwrap_or(false);
 | 
			
		||||
 | 
			
		||||
    // check if player is allowed to enter onto this tile
 | 
			
		||||
    let events = get_map_events(get_current_map().unwrap().id.as_str()).unwrap();
 | 
			
		||||
 | 
			
		||||
    let evt = events.iter().find(|e| e.evt_type == "lock" && e.location[0] == new_coords.0 && e.location[1] == new_coords.1);
 | 
			
		||||
    if evt.is_some() {
 | 
			
		||||
        let evt = evt.unwrap();
 | 
			
		||||
        
 | 
			
		||||
        let required_item = evt.command_id.clone();
 | 
			
		||||
        let player_items = crate::PLAYER_INVENTORY.lock().unwrap().clone();
 | 
			
		||||
        if !player_items.contains(&required_item) {
 | 
			
		||||
            if !dry_run { add_text(evt.description.as_ref().unwrap()); }
 | 
			
		||||
            return false; // Player does not have required item to enter this tile
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if dry_run { return walkable; }
 | 
			
		||||
 | 
			
		||||
    if !walkable {
 | 
			
		||||
        add_text(&format!("! Cannot move into {} tile", tile_name));
 | 
			
		||||
        return false; // Not a walkable tile, do not move
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    all_coords.insert(map.id, new_coords);
 | 
			
		||||
    *crate::PLAYER_STAMINA.lock().unwrap() -= 1;
 | 
			
		||||
 | 
			
		||||
    // crate::PLAYER_COORDS.lock().unwrap().0 = new_coords.0;
 | 
			
		||||
    // crate::PLAYER_COORDS.lock().unwrap().1 = new_coords.1;
 | 
			
		||||
 | 
			
		||||
    add_text(&format!("You moved into {} tile", tile_name));
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn get_current_tile() -> Option<Tile> {
 | 
			
		||||
    let map = get_current_map().unwrap();
 | 
			
		||||
    let player_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
    let map_coords = *player_coords.get(map.id.as_str()).unwrap();
 | 
			
		||||
 | 
			
		||||
    let tile_id = map.tilemap
 | 
			
		||||
        .get(map_coords.1 as usize)
 | 
			
		||||
        .and_then(|row| row.get(map_coords.0 as usize))
 | 
			
		||||
        .and_then(|tile| Some(tile.as_str()))
 | 
			
		||||
        .unwrap_or_default();
 | 
			
		||||
 | 
			
		||||
    let tile = map.tiles.get(tile_id)
 | 
			
		||||
        .cloned()
 | 
			
		||||
        .unwrap();
 | 
			
		||||
 | 
			
		||||
    Some(tile)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,232 @@
 | 
			
		|||
use std::collections::HashMap;
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
use std::sync::Mutex;
 | 
			
		||||
use std::{env, io};
 | 
			
		||||
use lazy_static::lazy_static;
 | 
			
		||||
use serde_json::{Map, Value};
 | 
			
		||||
use terminal_size::{Width, Height, terminal_size};
 | 
			
		||||
use signal_hook::consts::signal::SIGWINCH;
 | 
			
		||||
use signal_hook::iterator::Signals;
 | 
			
		||||
use text_io::read;
 | 
			
		||||
 | 
			
		||||
mod utils;
 | 
			
		||||
use utils::os::*;
 | 
			
		||||
 | 
			
		||||
mod tui;
 | 
			
		||||
use tui::interface::draw_interface;
 | 
			
		||||
use tui::interface::clear_input;
 | 
			
		||||
 | 
			
		||||
mod parser;
 | 
			
		||||
use parser::nlp::parse_command;
 | 
			
		||||
 | 
			
		||||
mod structs;
 | 
			
		||||
 | 
			
		||||
use crate::parser::nlp::get_available_commands;
 | 
			
		||||
use crate::structs::json::MapData;
 | 
			
		||||
use crate::structs::save::SaveData;
 | 
			
		||||
use crate::tui::interface::draw_player_data;
 | 
			
		||||
use crate::tui::map::{draw_map, draw_tile};
 | 
			
		||||
use crate::tui::menu::display_splash_screen;
 | 
			
		||||
 | 
			
		||||
mod game;
 | 
			
		||||
 | 
			
		||||
lazy_static! {
 | 
			
		||||
    static ref MAP_PACK: Mutex<String> = Mutex::new("".to_string());
 | 
			
		||||
    static ref PLAYER_NAME: Mutex<String> = Mutex::new("Player".to_string());
 | 
			
		||||
    static ref PLAYER_HEALTH: Mutex<u32> = Mutex::new(100);
 | 
			
		||||
    static ref PLAYER_STAMINA: Mutex<u32> = Mutex::new(50);
 | 
			
		||||
    static ref PLAYER_COORDS: Mutex<HashMap<String, (u8, u8)>> = Mutex::new(HashMap::new());
 | 
			
		||||
    static ref PLAYER_INVENTORY: Mutex<Vec<String>> = Mutex::new(Vec::new());
 | 
			
		||||
    static ref FLAGS: Mutex<HashMap<String, bool>> = Mutex::new(HashMap::new());
 | 
			
		||||
    static ref MAPS: Mutex<Vec<MapData>> = Mutex::new(Vec::new());
 | 
			
		||||
    static ref CURRENT_MAP_ID: Mutex<String> = Mutex::new("default".to_string());
 | 
			
		||||
    static ref LINES_OF_TEXT: Mutex<Vec<String>> = Mutex::new(Vec::new());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    set_terminal_title("Twoja Stara: The Game");
 | 
			
		||||
 | 
			
		||||
    let args: Vec<String> = env::args().collect();
 | 
			
		||||
    if args.len() > 1 && args[1] == "-d" {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    let mut signals = Signals::new(&[SIGWINCH]).expect("Failed to set up signal handling");
 | 
			
		||||
    
 | 
			
		||||
    let min_width = 100;
 | 
			
		||||
    let min_height = 30;
 | 
			
		||||
    // let width: u16;
 | 
			
		||||
    let height: u16;
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        clear_console();
 | 
			
		||||
        let size = terminal_size();
 | 
			
		||||
        if let Some((Width(w), Height(h))) = size {
 | 
			
		||||
            if w >= min_width && h >= min_height {
 | 
			
		||||
                // width = w;
 | 
			
		||||
                height = h;
 | 
			
		||||
                
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        
 | 
			
		||||
            println!("Terminal size is too small. Minimum size is {}x{}, but current size is {}x{}.", min_width, min_height, w, h);
 | 
			
		||||
            
 | 
			
		||||
            signals.forever().find(|&signal| signal == SIGWINCH);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // display_splash_screen();
 | 
			
		||||
 | 
			
		||||
    enum GameState {
 | 
			
		||||
        New,
 | 
			
		||||
        Loaded
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut error = "";
 | 
			
		||||
    let game_state: GameState;
 | 
			
		||||
    let map_name: String;
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        clear_console();
 | 
			
		||||
        display_splash_screen();
 | 
			
		||||
        // move_cursor(0, 0);
 | 
			
		||||
        println!("1. Start new game\n2. Load from save.json{}", error);
 | 
			
		||||
        let choice: String = read!("{}\n");
 | 
			
		||||
        match choice.as_str() {
 | 
			
		||||
            "1" => {
 | 
			
		||||
                game_state = GameState::New;
 | 
			
		||||
 | 
			
		||||
                map_name = "map".to_string();
 | 
			
		||||
 | 
			
		||||
                *PLAYER_NAME.lock().unwrap() = "Player".to_string();
 | 
			
		||||
                *PLAYER_HEALTH.lock().unwrap() = 100;
 | 
			
		||||
                *PLAYER_STAMINA.lock().unwrap() = 50;
 | 
			
		||||
                *PLAYER_COORDS.lock().unwrap() = HashMap::new();
 | 
			
		||||
                *PLAYER_INVENTORY.lock().unwrap() = Vec::new();
 | 
			
		||||
                *FLAGS.lock().unwrap() = HashMap::new();
 | 
			
		||||
                *CURRENT_MAP_ID.lock().unwrap() = map_name.to_string();
 | 
			
		||||
 | 
			
		||||
                let mut lines = Vec::new();
 | 
			
		||||
                lines.push("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
 | 
			
		||||
                *LINES_OF_TEXT.lock().unwrap() = Vec::new();
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            "2" => {
 | 
			
		||||
                let save = utils::json::load_json("save.json");
 | 
			
		||||
                match save {
 | 
			
		||||
                    Ok(data) => {
 | 
			
		||||
                        game_state = GameState::Loaded;
 | 
			
		||||
 | 
			
		||||
                        let save_data: SaveData = serde_json::from_value(data).unwrap();
 | 
			
		||||
                        let mut lines = save_data.lines_of_text;
 | 
			
		||||
                        lines.push("#(00FF00)Progress restored".to_string());
 | 
			
		||||
 | 
			
		||||
                        *PLAYER_NAME.lock().unwrap() = save_data.player_name;
 | 
			
		||||
                        *PLAYER_HEALTH.lock().unwrap() = save_data.health;
 | 
			
		||||
                        *PLAYER_STAMINA.lock().unwrap() = save_data.stamina;
 | 
			
		||||
                        *PLAYER_COORDS.lock().unwrap() = save_data.coords.iter().map(|(k, v)| (k.to_string(), (v[0], v[1]))).collect();
 | 
			
		||||
                        *PLAYER_INVENTORY.lock().unwrap() = save_data.inventory;
 | 
			
		||||
                        *FLAGS.lock().unwrap() = save_data.flags;
 | 
			
		||||
                        *CURRENT_MAP_ID.lock().unwrap() = save_data.current_map_id.clone();
 | 
			
		||||
                        *LINES_OF_TEXT.lock().unwrap() = lines;
 | 
			
		||||
 | 
			
		||||
                        map_name = save_data.map_pack;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    Err(e) => {
 | 
			
		||||
                        eprintln!("Error loading save file: {}", e);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            _ => {
 | 
			
		||||
                error = "\nPlease select either 1 or 2";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    println!("Loading map: {}.json", map_name);
 | 
			
		||||
    let json_data = utils::json::load_json(format!("{}.json", map_name).as_str());
 | 
			
		||||
    *MAP_PACK.lock().unwrap() = map_name;
 | 
			
		||||
    
 | 
			
		||||
    match json_data {
 | 
			
		||||
        Ok(data) => {
 | 
			
		||||
            let maps: Vec<MapData> = data.get("maps")
 | 
			
		||||
            .and_then(|v| v.as_array())
 | 
			
		||||
            .unwrap_or(&Vec::new())
 | 
			
		||||
            .iter()
 | 
			
		||||
            .filter_map(|v| v.as_object().cloned())
 | 
			
		||||
            .collect::<Vec<Map<String, Value>>>()
 | 
			
		||||
            .iter()
 | 
			
		||||
            .filter_map(|map| {
 | 
			
		||||
                print!("{:?}, ", map.get("id"));
 | 
			
		||||
                serde_json::from_value(Value::Object(map.clone())).ok()
 | 
			
		||||
            })
 | 
			
		||||
            .collect();
 | 
			
		||||
            *MAPS.lock().unwrap() = maps.clone();
 | 
			
		||||
            println!("asdf{:?}", MAPS.lock().unwrap());
 | 
			
		||||
 | 
			
		||||
            if matches!(game_state, GameState::New) {
 | 
			
		||||
                let current_map_id = maps.iter()
 | 
			
		||||
                .find(|map| map.default)
 | 
			
		||||
                .and_then(|map| Some(map.id.clone()))
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .to_string();
 | 
			
		||||
    
 | 
			
		||||
                *CURRENT_MAP_ID.lock().unwrap() = current_map_id.clone();
 | 
			
		||||
 | 
			
		||||
                let mut coords = PLAYER_COORDS.lock().unwrap();
 | 
			
		||||
 | 
			
		||||
                for(_, map) in maps.iter().enumerate() {
 | 
			
		||||
                    coords.insert(map.id.clone(), (
 | 
			
		||||
                        *map.starting_location.get(0).unwrap(),
 | 
			
		||||
                        *map.starting_location.get(1).unwrap()
 | 
			
		||||
                    ));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
            // let starting_location = data.get("data")
 | 
			
		||||
            // .and_then(|v| v.as_object())
 | 
			
		||||
            // .and_then(|obj| obj.get("starting_location"))
 | 
			
		||||
            // .and_then(|v| v.as_array())
 | 
			
		||||
            // .unwrap();
 | 
			
		||||
 | 
			
		||||
            // let mut a = PLAYER_COORDS.lock().unwrap();
 | 
			
		||||
            // a.insert(current_map_id, (
 | 
			
		||||
            //     starting_location.get(0).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0),
 | 
			
		||||
            //     starting_location.get(1).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0)
 | 
			
		||||
            // ));
 | 
			
		||||
 | 
			
		||||
            // PLAYER_COORDS.lock().unwrap().0 = starting_location.get(0).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0);
 | 
			
		||||
            // PLAYER_COORDS.lock().unwrap().1 = starting_location.get(1).and_then(|v| v.as_u64()).unwrap_or(0).try_into().unwrap_or(0);
 | 
			
		||||
            // draw_map(map_data);
 | 
			
		||||
            
 | 
			
		||||
        },
 | 
			
		||||
        Err(e) => eprintln!("Error loading JSON data: {}", e),
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    draw_interface();
 | 
			
		||||
 | 
			
		||||
    loop {    
 | 
			
		||||
        if PLAYER_INVENTORY.lock().unwrap().clone().iter().find(|x| x == &"map").is_some() { draw_map() }
 | 
			
		||||
        move_cursor(2, height - 2);
 | 
			
		||||
        set_cursor_visibility(true);
 | 
			
		||||
        
 | 
			
		||||
        let line: String = read!("{}\n");
 | 
			
		||||
        parse_command(&line);
 | 
			
		||||
        draw_tile();
 | 
			
		||||
        get_available_commands();
 | 
			
		||||
        io::stdout().flush().expect("Failed to flush stdout");
 | 
			
		||||
        // thread::sleep(std::time::Duration::from_millis(1000));
 | 
			
		||||
        clear_input();
 | 
			
		||||
        draw_player_data();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // move_cursor(width - 1, height - 1);
 | 
			
		||||
    // loop {}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
pub mod nlp;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,300 @@
 | 
			
		|||
use std::collections::HashMap;
 | 
			
		||||
use colored::Colorize;
 | 
			
		||||
use serde_json::to_value;
 | 
			
		||||
 | 
			
		||||
use crate::{game::player::move_player, structs::save::SaveData, tui::{text::add_text}, utils::{json::save_json, maps::{get_current_map, get_map_events, get_npc, load_new_map}, os::move_cursor}};
 | 
			
		||||
 | 
			
		||||
lazy_static::lazy_static! {
 | 
			
		||||
    static ref COMMAND_SYNONYMS: HashMap<&'static str, &'static str> = {
 | 
			
		||||
        let mut map = HashMap::new();
 | 
			
		||||
        map.insert("go", "go");
 | 
			
		||||
        map.insert("towards", "go");
 | 
			
		||||
        map.insert("head", "go");
 | 
			
		||||
        map.insert("walk", "go");
 | 
			
		||||
        map.insert("move", "go");
 | 
			
		||||
        map.insert("mv", "go");
 | 
			
		||||
        map.insert("examine", "examine");
 | 
			
		||||
        map.insert("inspect", "examine");
 | 
			
		||||
        map.insert("look", "examine");
 | 
			
		||||
        map.insert("take", "take");
 | 
			
		||||
        map.insert("grab", "take");
 | 
			
		||||
        map.insert("pick", "take");
 | 
			
		||||
        map.insert("enter", "enter");
 | 
			
		||||
        map.insert("exit", "exit");
 | 
			
		||||
        map.insert("leave", "exit");
 | 
			
		||||
        map.insert("talk", "talk");
 | 
			
		||||
        map.insert("describe", "describe");
 | 
			
		||||
        map.insert("desc", "describe");
 | 
			
		||||
        map.insert("talk", "talk");
 | 
			
		||||
        map.insert("say", "say");
 | 
			
		||||
        map.insert("save", "save");
 | 
			
		||||
        map
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static ref DIRECTIONS: HashMap<&'static str, (i8, i8)> = {
 | 
			
		||||
        let mut map = HashMap::new();
 | 
			
		||||
        map.insert("north", (0, -1));
 | 
			
		||||
        map.insert("n", (0, -1));
 | 
			
		||||
        map.insert("up", (0, -1));
 | 
			
		||||
        map.insert("u", (0, -1));
 | 
			
		||||
        map.insert("south", (0, 1));
 | 
			
		||||
        map.insert("s", (0, 1));
 | 
			
		||||
        map.insert("down", (0, 1));
 | 
			
		||||
        map.insert("d", (0, 1));
 | 
			
		||||
        map.insert("east", (1, 0));
 | 
			
		||||
        map.insert("e", (1, 0));
 | 
			
		||||
        map.insert("right", (1, 0));
 | 
			
		||||
        map.insert("r", (1, 0));
 | 
			
		||||
        map.insert("west", (-1, 0));
 | 
			
		||||
        map.insert("w", (-1, 0));
 | 
			
		||||
        map.insert("left", (-1, 0));
 | 
			
		||||
        map.insert("l", (-1, 0));
 | 
			
		||||
        map
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static ref LOCATIONS: HashMap<&'static str, &'static str> = {
 | 
			
		||||
        let mut map = HashMap::new();
 | 
			
		||||
        map.insert("home", "home");
 | 
			
		||||
        map.insert("house", "home");
 | 
			
		||||
        map.insert("cave", "cave");
 | 
			
		||||
        map.insert("forest", "forest");
 | 
			
		||||
        map.insert("village", "village");
 | 
			
		||||
        map.insert("town", "town");
 | 
			
		||||
        map.insert("city", "city");
 | 
			
		||||
        map
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn parse_command(input: &str) -> Option<(&str, String)> {
 | 
			
		||||
    let parts: Vec<&str> = input.trim().split_whitespace().collect();
 | 
			
		||||
    if parts.len() < 2 {
 | 
			
		||||
        return None;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    let command = parts[0];
 | 
			
		||||
    let argument = parts[1..].join(" ");
 | 
			
		||||
    let height = if let Some((_, terminal_size::Height(h))) = terminal_size::terminal_size() {
 | 
			
		||||
        h
 | 
			
		||||
    } else {
 | 
			
		||||
        24 // Default height if terminal size cannot be determined
 | 
			
		||||
    };
 | 
			
		||||
    if let Some(synonym) = COMMAND_SYNONYMS.get(command) {
 | 
			
		||||
        // print!("{}", input.green());
 | 
			
		||||
        add_text(format!("> {} {}", synonym, argument).as_str());
 | 
			
		||||
        move_cursor(2, height - 2);
 | 
			
		||||
        match synonym {
 | 
			
		||||
            &"go" => {
 | 
			
		||||
                if let Some(direction) = DIRECTIONS.get(argument.as_str()) {
 | 
			
		||||
                    print!("{}", input.green());
 | 
			
		||||
                    move_player(direction.0, direction.1, false);
 | 
			
		||||
                } else {
 | 
			
		||||
                    println!("{}", format!("{} | unknown direction: {}", input, argument).red());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &"enter" => {
 | 
			
		||||
                let events = get_map_events(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
                let all_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
                let player_coords = all_coords.get(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
 | 
			
		||||
                let evt = events.iter().find(|e| e.evt_type == "location" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
                if evt.is_some() {
 | 
			
		||||
                    let evt = evt.unwrap();
 | 
			
		||||
                    add_text("You entered a location.");
 | 
			
		||||
 | 
			
		||||
                    load_new_map(evt.command_id.as_str());
 | 
			
		||||
 | 
			
		||||
                    move_cursor(1, 1);
 | 
			
		||||
                    print!("Player: {} | Map: {}", crate::PLAYER_NAME.lock().unwrap().bold().underline(), get_current_map().unwrap().name.bold().underline());
 | 
			
		||||
 | 
			
		||||
                    // *crate::CURRENT_MAP_ID.lock().unwrap() = evt.command_id.clone();
 | 
			
		||||
                } else {
 | 
			
		||||
                    add_text("! You cannot enter this location.");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &"exit" => {
 | 
			
		||||
                let events = get_map_events(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
                let all_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
                let player_coords = all_coords.get(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
 | 
			
		||||
                // print!("{:?}, {:?}", events, player_coords);
 | 
			
		||||
 | 
			
		||||
                let evt = events.iter().find(|e| e.evt_type == "location" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
                if evt.is_some() {
 | 
			
		||||
                    let evt = evt.unwrap();
 | 
			
		||||
                    add_text("You exited a location.");
 | 
			
		||||
 | 
			
		||||
                    load_new_map(evt.command_id.as_str());
 | 
			
		||||
                    move_cursor(1, 1);
 | 
			
		||||
                    print!("Player: {} | Map: {}", crate::PLAYER_NAME.lock().unwrap().bold().underline(), get_current_map().unwrap().name.bold().underline());
 | 
			
		||||
 | 
			
		||||
                    // *crate::CURRENT_MAP_ID.lock().unwrap() = evt.command_id.clone();
 | 
			
		||||
                } else {
 | 
			
		||||
                    add_text("! You cannot exit from this location.");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &"describe" => {
 | 
			
		||||
                match argument.as_str() {
 | 
			
		||||
                    "item" => {
 | 
			
		||||
                        let events = get_map_events(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
                        let all_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
                        let player_coords = all_coords.get(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
 | 
			
		||||
                        let evt = events.iter().find(|e| e.evt_type == "item" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
                        if evt.is_some() {
 | 
			
		||||
                            let evt = evt.unwrap();
 | 
			
		||||
                            add_text(evt.description.as_ref().unwrap_or(&"No description available.".to_string()).as_str());
 | 
			
		||||
                        } else {
 | 
			
		||||
                            add_text("! No item to describe here.");
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    "tile" => {
 | 
			
		||||
                        let current_tile = crate::game::player::get_current_tile().unwrap();
 | 
			
		||||
                        add_text(current_tile.description.as_deref().unwrap_or("No description available."));        
 | 
			
		||||
                    }
 | 
			
		||||
                    "location" => {
 | 
			
		||||
                        let map = get_current_map().unwrap();
 | 
			
		||||
                        add_text(map.description.as_str());
 | 
			
		||||
                    }
 | 
			
		||||
                    _ => {
 | 
			
		||||
                        print!("{}", format!("{} | unknown argument: {}", input, argument).red());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &"take" => {
 | 
			
		||||
                let events = get_map_events(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
                let all_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
                let player_coords = all_coords.get(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
                let mut flags = crate::FLAGS.lock().unwrap();
 | 
			
		||||
                let evt = events.iter().find(|e| e.evt_type == "item" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
 | 
			
		||||
                if !evt.is_some() {
 | 
			
		||||
                    add_text("! Nothing to pick up here.");
 | 
			
		||||
                    return None;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let evt = evt.unwrap();
 | 
			
		||||
 | 
			
		||||
                if !flags.contains_key(evt.command_id.as_str()) {
 | 
			
		||||
                    add_text(format!("You picked up {}.", evt.command_id).as_str());
 | 
			
		||||
 | 
			
		||||
                    crate::PLAYER_INVENTORY.lock().unwrap().push(evt.command_id.clone());
 | 
			
		||||
                    flags.insert(evt.command_id.clone(), true);
 | 
			
		||||
                } else {
 | 
			
		||||
                    add_text("! Nothing to pick up here.");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &"talk" => {
 | 
			
		||||
                let events = get_map_events(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
                let all_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
                let player_coords = all_coords.get(get_current_map().unwrap().id.as_str())?;
 | 
			
		||||
 | 
			
		||||
                let evt = events.iter().find(|e| e.evt_type == "npc" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
                
 | 
			
		||||
                match evt {
 | 
			
		||||
                    Some(e) => {
 | 
			
		||||
                        let npc = get_npc(&e.command_id);
 | 
			
		||||
                        match npc {
 | 
			
		||||
                            Some(n) => {
 | 
			
		||||
                                add_text(format!("You talked to {}.", n.name).as_str());
 | 
			
		||||
                                for line in n.dialogue.iter() {
 | 
			
		||||
                                    add_text(line);
 | 
			
		||||
                                }
 | 
			
		||||
                                add_text("#(FFFF00)Use `say <number>` to respond");
 | 
			
		||||
                            }
 | 
			
		||||
                            None => {
 | 
			
		||||
                                add_text("! Strange NPC here, no dialogue available.");
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    None => {
 | 
			
		||||
                        add_text("! No NPC to talk to here.");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &"say" => {
 | 
			
		||||
                match argument.as_str() {
 | 
			
		||||
                    "1" => {
 | 
			
		||||
                        add_text("You said: 'Nothing'");
 | 
			
		||||
                    }
 | 
			
		||||
                    "2" => {
 | 
			
		||||
                        add_text("You said: 'Gate key'");
 | 
			
		||||
                        add_text("You acquired a key");
 | 
			
		||||
                        
 | 
			
		||||
                    }
 | 
			
		||||
                    _ => {
 | 
			
		||||
                        add_text("#(FF0000)! Unknown argument for 'say' command.");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &"save" => {
 | 
			
		||||
                let save_data = SaveData {
 | 
			
		||||
                    version: 1,
 | 
			
		||||
                    map_pack: crate::MAP_PACK.lock().unwrap().clone(),
 | 
			
		||||
                    player_name: crate::PLAYER_NAME.lock().unwrap().clone(),
 | 
			
		||||
                    last_save: chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
 | 
			
		||||
                    current_map_id: crate::CURRENT_MAP_ID.lock().unwrap().clone(),
 | 
			
		||||
                    health: *crate::PLAYER_HEALTH.lock().unwrap(),
 | 
			
		||||
                    stamina: *crate::PLAYER_STAMINA.lock().unwrap(),
 | 
			
		||||
                    coords: crate::PLAYER_COORDS.lock().unwrap().iter().map(|(k, v)| (k.to_string(), vec![v.0, v.1])).collect(),
 | 
			
		||||
                    inventory: crate::PLAYER_INVENTORY.lock().unwrap().clone(),
 | 
			
		||||
                    flags: crate::FLAGS.lock().unwrap().clone(),
 | 
			
		||||
                    lines_of_text: crate::LINES_OF_TEXT.lock().unwrap().clone(),
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                let result = save_json("save.json", to_value(save_data).unwrap());
 | 
			
		||||
                match result {
 | 
			
		||||
                    Ok(_) => {
 | 
			
		||||
                        add_text("#(00FF00)Progress saved");
 | 
			
		||||
                    }
 | 
			
		||||
                    Err(e) => {
 | 
			
		||||
                        add_text(format!("#(FF0000)Failed to save: {:?}", e).as_str());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            _ => {
 | 
			
		||||
                print!("{}", input.red());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Some((synonym, argument))
 | 
			
		||||
    } else {
 | 
			
		||||
        print!("{}", input.red());
 | 
			
		||||
        None
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn get_available_commands() {
 | 
			
		||||
    let width = if let Some((terminal_size::Width(w), _)) = terminal_size::terminal_size() {
 | 
			
		||||
        w
 | 
			
		||||
    } else {
 | 
			
		||||
        80 // Default height if terminal size cannot be determined
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let events = get_map_events(get_current_map().unwrap().id.as_str()).unwrap();
 | 
			
		||||
    let all_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
    let player_coords = all_coords.get(get_current_map().unwrap().id.as_str()).unwrap();
 | 
			
		||||
    let evt_item = events.iter().find(|e| e.evt_type == "item" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
    let evt_location = events.iter().find(|e| e.evt_type == "location" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
    let evt_npc = events.iter().find(|e| e.evt_type == "npc" && e.location[0] == player_coords.0 && e.location[1] == player_coords.1);
 | 
			
		||||
    let flags = crate::FLAGS.lock().unwrap();
 | 
			
		||||
    
 | 
			
		||||
    // GO
 | 
			
		||||
    move_cursor(width - 24, 4);
 | 
			
		||||
    print!("GO    | {} {} {} {}",
 | 
			
		||||
        if move_player(0, -1, true) { "▲".green() } else { "▲".red() },
 | 
			
		||||
        if move_player(0, 1, true) { "▼".green() } else { "▼".red() },
 | 
			
		||||
        if move_player(-1, 0, true) { "◀".green() } else { "◀".red() },
 | 
			
		||||
        if move_player(1, 0, true) { "▶".green() } else { "▶".red() }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // TAKE
 | 
			
		||||
    move_cursor(width - 24, 5);
 | 
			
		||||
    print!("TAKE  | {}", if evt_item.is_some() && !flags.contains_key(evt_item.unwrap().command_id.as_str())  { "✔".green() } else { "✘".red() });
 | 
			
		||||
 | 
			
		||||
    // ENTER/EXIT
 | 
			
		||||
    move_cursor(width - 24, 6);
 | 
			
		||||
    print!("ENTER | {}", if evt_location.is_some() { "✔".green() } else { "✘".red() });
 | 
			
		||||
 | 
			
		||||
    // TALK
 | 
			
		||||
    move_cursor(width - 24, 7);
 | 
			
		||||
    print!("TALK  | {}", if evt_npc.is_some() { "✔".green() } else { "✘".red() });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
use std::collections::HashMap;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct MapData {
 | 
			
		||||
    pub default: bool,
 | 
			
		||||
    pub map_required: bool,
 | 
			
		||||
    pub starting_location: Vec<u8>,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub id: String,
 | 
			
		||||
    pub width: u16,
 | 
			
		||||
    pub height: u16,
 | 
			
		||||
    pub events: Vec<Events>,
 | 
			
		||||
    pub tilemap: Vec<Vec<String>>,
 | 
			
		||||
    pub tiles: HashMap<String, Tile>,
 | 
			
		||||
    pub npcs: HashMap<String, NPC>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct Events {
 | 
			
		||||
    pub evt_type: String,
 | 
			
		||||
    pub command_id: String,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub location: Vec<u8>,
 | 
			
		||||
    pub dialogue: Option<Vec<String>>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct Tile {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub icon: Option<TileIcon>,
 | 
			
		||||
    pub walkable: bool,
 | 
			
		||||
    pub description: Option<String>,
 | 
			
		||||
    pub bitmap: Vec<Vec<String>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct TileIcon {
 | 
			
		||||
    pub char: String,
 | 
			
		||||
    pub color: Vec<u8>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct NPC {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub description: String,
 | 
			
		||||
    pub dialogue: Vec<String>,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
pub mod json;
 | 
			
		||||
pub mod save;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
use std::collections::HashMap;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, Debug, Clone)]
 | 
			
		||||
pub struct SaveData {
 | 
			
		||||
    pub version: u16,
 | 
			
		||||
    pub map_pack: String,
 | 
			
		||||
    pub player_name: String,
 | 
			
		||||
    pub last_save: String,
 | 
			
		||||
    pub current_map_id: String,
 | 
			
		||||
    pub health: u32,
 | 
			
		||||
    pub stamina: u32,
 | 
			
		||||
    pub coords: HashMap<String, Vec<u8>>,
 | 
			
		||||
    pub inventory: Vec<String>,
 | 
			
		||||
    pub flags: HashMap<String, bool>,
 | 
			
		||||
    pub lines_of_text: Vec<String>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,113 @@
 | 
			
		|||
use colored::Colorize;
 | 
			
		||||
use terminal_size::{Width, Height, terminal_size};
 | 
			
		||||
 | 
			
		||||
use crate::{parser::nlp::get_available_commands, tui::{map::draw_tile, text::refresh_text}, utils::{maps::get_current_map, os::move_cursor}};
 | 
			
		||||
 | 
			
		||||
pub fn draw_interface() {
 | 
			
		||||
    move_cursor(0, 0);
 | 
			
		||||
 | 
			
		||||
    let Some((Width(w), Height(h))) = terminal_size()
 | 
			
		||||
    else {
 | 
			
		||||
        eprintln!("Could not determine terminal size.");
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let horizontal_char = "─";
 | 
			
		||||
    let vertical_char = "│";
 | 
			
		||||
    // let corner_char = "+";
 | 
			
		||||
    let perp_down_char = "┬";
 | 
			
		||||
    let perp_up_char = "┴";
 | 
			
		||||
    let perp_left_char = "├";
 | 
			
		||||
    let perp_right_char = "┤";
 | 
			
		||||
    let corner_down_left_char = "┌";
 | 
			
		||||
    let corner_down_right_char = "┐";
 | 
			
		||||
    let corner_up_left_char = "└";
 | 
			
		||||
    let corner_up_right_char = "┘";
 | 
			
		||||
 | 
			
		||||
    let horizontal_line = horizontal_char.repeat(usize::from(w - 2));
 | 
			
		||||
 | 
			
		||||
    print!("{}", String::from(corner_down_left_char) + &horizontal_line + corner_down_right_char);
 | 
			
		||||
    for i in 0..(h - 2) {
 | 
			
		||||
        if i == 0 {
 | 
			
		||||
            print!("{}", String::from(vertical_char) + &" ".repeat(usize::from(w - 2)) + vertical_char);
 | 
			
		||||
        } else if i == 1 {
 | 
			
		||||
            print!("{}", String::from(perp_left_char) + &horizontal_char.repeat(16) + perp_down_char + &horizontal_char.repeat(usize::from(w - 19 - 25)) + perp_down_char + &horizontal_char.repeat(24) + perp_right_char);
 | 
			
		||||
        } else if i == h - 9 || i == 10 {
 | 
			
		||||
            print!("{}", String::from(perp_left_char) + &horizontal_char.repeat(16) + perp_right_char + &" ".repeat(usize::from(w - 19 - 25)) + vertical_char + &" ".repeat(24) + vertical_char);
 | 
			
		||||
        } else if i < h - 4 {
 | 
			
		||||
            print!("{}", String::from(vertical_char) + &" ".repeat(16) + vertical_char + &" ".repeat(usize::from(w - 19 - 25)) + vertical_char + &" ".repeat(24) + vertical_char);
 | 
			
		||||
        } else if i == h - 4 {
 | 
			
		||||
            print!("{}", String::from(perp_left_char) + &horizontal_char.repeat(16) + perp_up_char + &horizontal_char.repeat(usize::from(w - 19 - 25)) + perp_up_char + &horizontal_char.repeat(24) + perp_right_char);
 | 
			
		||||
        } else {
 | 
			
		||||
            print!("{}", String::from(vertical_char) + &" ".repeat(usize::from(w - 2)) + vertical_char);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    print!("{}", String::from(corner_up_left_char) + &horizontal_line + corner_up_right_char);
 | 
			
		||||
 | 
			
		||||
    draw_player_data();
 | 
			
		||||
 | 
			
		||||
    move_cursor(w - 21, 3);
 | 
			
		||||
    print!("{}", "POSSIBLE ACTIONS".bold().underline());
 | 
			
		||||
 | 
			
		||||
    move_cursor(1, 1);
 | 
			
		||||
    print!("Player: {} | Map: {}", crate::PLAYER_NAME.lock().unwrap().bold().underline(), get_current_map().unwrap().name.bold().underline());
 | 
			
		||||
 | 
			
		||||
    draw_tile();
 | 
			
		||||
    get_available_commands();
 | 
			
		||||
    
 | 
			
		||||
    refresh_text();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn clear_input() {
 | 
			
		||||
    let Some((Width(width), Height(height))) = terminal_size()
 | 
			
		||||
    else {
 | 
			
		||||
        eprintln!("Could not determine terminal size.");
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    move_cursor(2, height - 2);
 | 
			
		||||
    
 | 
			
		||||
    print!("{:width$}", "", width = usize::from(width - 4));
 | 
			
		||||
    move_cursor(2, height - 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn draw_player_data() {
 | 
			
		||||
    let Some((Width(_), Height(height))) = terminal_size()
 | 
			
		||||
    else {
 | 
			
		||||
        eprintln!("Could not determine terminal size.");
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
    let y = height - 7;
 | 
			
		||||
 | 
			
		||||
    let hp = u16::try_from(*crate::PLAYER_HEALTH.lock().unwrap()).unwrap();
 | 
			
		||||
    let sp = u16::try_from(*crate::PLAYER_STAMINA.lock().unwrap()).unwrap();
 | 
			
		||||
 | 
			
		||||
    let max_hp = 100;
 | 
			
		||||
    let max_sp = 50;
 | 
			
		||||
 | 
			
		||||
    move_cursor(1, y);
 | 
			
		||||
    print!("HP: {}/{}", hp, max_hp);
 | 
			
		||||
    move_cursor(1, y + 1);
 | 
			
		||||
    let hp_blocks_count = ((hp as f64) / 100.0 * 16.0).ceil() as u8;
 | 
			
		||||
    let mut hp_blocks = String::from("");
 | 
			
		||||
    for _ in 0..hp_blocks_count {
 | 
			
		||||
        hp_blocks.push('█');
 | 
			
		||||
    }
 | 
			
		||||
    for _ in hp_blocks_count..16 {
 | 
			
		||||
        hp_blocks.push('_');
 | 
			
		||||
    }
 | 
			
		||||
    print!("{}", hp_blocks.red());
 | 
			
		||||
 | 
			
		||||
    move_cursor(1, y + 2);
 | 
			
		||||
    print!("SP: {}/{}", sp, max_sp);
 | 
			
		||||
    move_cursor(1, y + 3);
 | 
			
		||||
    let mp_blocks_count = ((sp as f64) / 50.0 * 16.0).ceil() as u8;
 | 
			
		||||
    let mut mp_blocks = String::from("");
 | 
			
		||||
    for _ in 0..mp_blocks_count {
 | 
			
		||||
        mp_blocks.push('█');
 | 
			
		||||
    }
 | 
			
		||||
    for _ in mp_blocks_count..16 {
 | 
			
		||||
        mp_blocks.push('_');
 | 
			
		||||
    }
 | 
			
		||||
    print!("{}", mp_blocks.yellow());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
use colored::Colorize;
 | 
			
		||||
 | 
			
		||||
use crate::{game::player::get_current_tile, utils::os::move_cursor};
 | 
			
		||||
 | 
			
		||||
pub fn draw_tile() {
 | 
			
		||||
    let tile = get_current_tile();
 | 
			
		||||
 | 
			
		||||
    let bitmap = tile.clone().unwrap().bitmap;
 | 
			
		||||
 | 
			
		||||
    for (y, row) in bitmap.iter().enumerate() {
 | 
			
		||||
        move_cursor(1, (y as u16) + 3);
 | 
			
		||||
        for (_, pixel) in row.iter().enumerate() {
 | 
			
		||||
            let colors = tile.clone().unwrap().icon.unwrap().color;
 | 
			
		||||
 | 
			
		||||
            print!("{}", pixel.on_truecolor(colors[0], colors[1], colors[2]));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn draw_map() {
 | 
			
		||||
    clear_map();
 | 
			
		||||
    let map = crate::utils::maps::get_current_map().unwrap().clone();
 | 
			
		||||
    let player_coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
    let map_coords = *player_coords.get(map.id.as_str()).unwrap();
 | 
			
		||||
 | 
			
		||||
    let starting_index = (
 | 
			
		||||
        if map.width > 16 {
 | 
			
		||||
            if map_coords.0 > 8 {
 | 
			
		||||
                map_coords.0 as u16 - 8
 | 
			
		||||
            } else {
 | 
			
		||||
                0
 | 
			
		||||
            }
 | 
			
		||||
        } else { 0 },
 | 
			
		||||
        if map.height > 8 {
 | 
			
		||||
            if map_coords.1 > 4 {
 | 
			
		||||
                map_coords.1 as u16 - 4
 | 
			
		||||
            } else {
 | 
			
		||||
                0
 | 
			
		||||
            }
 | 
			
		||||
        } else { 0 }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    for (y, row) in map.tilemap.iter().skip(starting_index.1 as usize).enumerate() {
 | 
			
		||||
        if y >= 8 { break }
 | 
			
		||||
        move_cursor(1, (y as u16) + 12);
 | 
			
		||||
        for (x, tile_id) in row.iter().skip(starting_index.0 as usize).enumerate() {
 | 
			
		||||
            if x + starting_index.0 as usize == map_coords.0 as usize && y + starting_index.1 as usize == map_coords.1 as usize {
 | 
			
		||||
                print!("{}", "X".bold().red().on_truecolor(228, 209, 178));
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            let tile = map.tiles.get(tile_id.as_str()).unwrap();
 | 
			
		||||
            let icon = tile.icon.clone().unwrap();
 | 
			
		||||
            print!("{}", icon.char.truecolor(icon.color[0], icon.color[1], icon.color[2]).on_truecolor(228, 209, 178));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn clear_map() {
 | 
			
		||||
    for y in 0..8 {
 | 
			
		||||
        move_cursor(1, 12 + y);
 | 
			
		||||
        print!("{}", " ".repeat(16));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
use std::io::{self, Write};
 | 
			
		||||
 | 
			
		||||
pub fn display_splash_screen() {
 | 
			
		||||
    let splash = r#"
 | 
			
		||||
▄▄▄█████▓ ██░ ██ ▓█████      ▄████  ▄▄▄       ███▄ ▄███▓▓█████ 
 | 
			
		||||
▓  ██▒ ▓▒▓██░ ██▒▓█   ▀     ██▒ ▀█▒▒████▄    ▓██▒▀█▀ ██▒▓█   ▀ 
 | 
			
		||||
▒ ▓██░ ▒░▒██▀▀██░▒███      ▒██░▄▄▄░▒██  ▀█▄  ▓██    ▓██░▒███   
 | 
			
		||||
░ ▓██▓ ░ ░▓█ ░██ ▒▓█  ▄    ░▓█  ██▓░██▄▄▄▄██ ▒██    ▒██ ▒▓█  ▄ 
 | 
			
		||||
  ▒██▒ ░ ░▓█▒░██▓░▒████▒   ░▒▓███▀▒ ▓█   ▓██▒▒██▒   ░██▒░▒████▒
 | 
			
		||||
  ▒ ░░    ▒ ░░▒░▒░░ ▒░ ░    ░▒   ▒  ▒▒   ▓▒█░░ ▒░   ░  ░░░ ▒░ ░
 | 
			
		||||
    ░     ▒ ░▒░ ░ ░ ░  ░     ░   ░   ▒   ▒▒ ░░  ░      ░ ░ ░  ░
 | 
			
		||||
  ░       ░  ░░ ░   ░      ░ ░   ░   ░   ▒   ░      ░      ░   
 | 
			
		||||
          ░  ░  ░   ░  ░         ░       ░  ░       ░      ░  ░
 | 
			
		||||
 | 
			
		||||
"#;
 | 
			
		||||
 | 
			
		||||
    let stdout = io::stdout();
 | 
			
		||||
    let mut handle = stdout.lock();
 | 
			
		||||
    write!(handle, "{}", splash).unwrap();
 | 
			
		||||
    handle.flush().unwrap();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
pub mod menu;
 | 
			
		||||
pub mod interface;
 | 
			
		||||
pub mod map;
 | 
			
		||||
pub mod text;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
use colored::{ColoredString, Colorize};
 | 
			
		||||
use terminal_size::{Width, Height, terminal_size};
 | 
			
		||||
 | 
			
		||||
use crate::utils::os::{move_cursor, set_cursor_visibility};
 | 
			
		||||
 | 
			
		||||
// pub fn clear_text() {
 | 
			
		||||
//     set_cursor_visibility(false);
 | 
			
		||||
//     // let Some((Width(width), Height(height))) = terminal_size()
 | 
			
		||||
//     // else {
 | 
			
		||||
//     //     eprintln!("Could not determine terminal size.");
 | 
			
		||||
//     //     return;
 | 
			
		||||
//     // };
 | 
			
		||||
 | 
			
		||||
//     // let text_area_width: u16 = width - 4 - 16 - 24;
 | 
			
		||||
 | 
			
		||||
//     move_cursor(18, 1);
 | 
			
		||||
//     // print!("{}", "x".repeat(usize::from(text_area_width)));
 | 
			
		||||
//     *crate::LINES_OF_TEXT.lock().unwrap() = [].to_vec();
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
fn color_text(text: &str) -> ColoredString {
 | 
			
		||||
    if text.starts_with("#") {
 | 
			
		||||
        let color_code_raw = &text[2..8];
 | 
			
		||||
        let color_code = (
 | 
			
		||||
            u8::from_str_radix(&color_code_raw[0..2], 16).unwrap_or(255),
 | 
			
		||||
            u8::from_str_radix(&color_code_raw[2..4], 16).unwrap_or(255),
 | 
			
		||||
            u8::from_str_radix(&color_code_raw[4..6], 16).unwrap_or(255)
 | 
			
		||||
        );
 | 
			
		||||
        let text = &text[9..].truecolor(color_code.0, color_code.1, color_code.2);
 | 
			
		||||
 | 
			
		||||
        text.clone()
 | 
			
		||||
    } else {
 | 
			
		||||
        text.normal()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn add_text(text: &str) {
 | 
			
		||||
    set_cursor_visibility(false);
 | 
			
		||||
    let Some((Width(width), Height(height))) = terminal_size()
 | 
			
		||||
    else {
 | 
			
		||||
        eprintln!("Could not determine terminal size.");
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
    let text_area_width: u16 = width - 4 - 16 - 24;
 | 
			
		||||
 | 
			
		||||
    let mut lines_of_text = crate::LINES_OF_TEXT.lock().unwrap();
 | 
			
		||||
 | 
			
		||||
    // move_cursor(18, (*lines_of_text + 1).try_into().unwrap_or(1));
 | 
			
		||||
 | 
			
		||||
    let wrapped_lines = wrap_text(text, text_area_width);
 | 
			
		||||
    for line in wrapped_lines {
 | 
			
		||||
        lines_of_text.push(line);
 | 
			
		||||
        print_text(lines_of_text.clone(), text_area_width, height - 6);
 | 
			
		||||
        // move_cursor(18, (*lines_of_text + 1).try_into().unwrap_or(1));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn wrap_text(text: &str, width: u16) -> Vec<String> {
 | 
			
		||||
    let mut wrapped_lines = Vec::new();
 | 
			
		||||
    let mut current_line = String::new();
 | 
			
		||||
    let words: Vec<&str> = text.split_whitespace().collect();
 | 
			
		||||
 | 
			
		||||
    for word in words {
 | 
			
		||||
        if current_line.len() + word.len() + 1 > usize::from(width) {
 | 
			
		||||
            wrapped_lines.push(current_line.trim().to_string());
 | 
			
		||||
            current_line.clear();
 | 
			
		||||
        }
 | 
			
		||||
        if !current_line.is_empty() {
 | 
			
		||||
            current_line.push(' ');
 | 
			
		||||
        }
 | 
			
		||||
        current_line.push_str(word);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if !current_line.is_empty() {
 | 
			
		||||
        wrapped_lines.push(current_line.trim().to_string());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wrapped_lines    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn print_text(lines: Vec<String>, width: u16, height: u16) {
 | 
			
		||||
    set_cursor_visibility(false);
 | 
			
		||||
 | 
			
		||||
    let mut line_number = 3;
 | 
			
		||||
 | 
			
		||||
    if lines.len() > usize::from(height) {
 | 
			
		||||
        let start_index = lines.len() - usize::from(height);
 | 
			
		||||
        let end_index = lines.len();
 | 
			
		||||
        let visible_lines = &lines[start_index..end_index];
 | 
			
		||||
        for line in visible_lines.iter() {
 | 
			
		||||
            let text = color_text(&line);
 | 
			
		||||
            move_cursor(18, line_number);
 | 
			
		||||
            print!("{}{}", text, " ".repeat(usize::from(width) - line.len()));
 | 
			
		||||
            line_number += 1;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        for line in lines.iter() {
 | 
			
		||||
            let text = color_text(&line);
 | 
			
		||||
            move_cursor(18, line_number);
 | 
			
		||||
            print!("{}", text);
 | 
			
		||||
            line_number += 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn refresh_text() {
 | 
			
		||||
    let Some((Width(width), Height(height))) = terminal_size()
 | 
			
		||||
    else {
 | 
			
		||||
        eprintln!("Could not determine terminal size.");
 | 
			
		||||
        return;
 | 
			
		||||
    };
 | 
			
		||||
    let text_area_width: u16 = width - 4 - 16 - 24;
 | 
			
		||||
 | 
			
		||||
    let lines_of_text = crate::LINES_OF_TEXT.lock().unwrap();
 | 
			
		||||
 | 
			
		||||
    print_text(lines_of_text.to_vec(), text_area_width, height);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
pub fn load_json(file_path: &str) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
 | 
			
		||||
    let file = std::fs::File::open(file_path)?;
 | 
			
		||||
    let reader = std::io::BufReader::new(file);
 | 
			
		||||
    let json_data: serde_json::Value = serde_json::from_reader(reader)?;
 | 
			
		||||
    Ok(json_data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn save_json(file_path: &str, data: serde_json::Value) -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
    let file = std::fs::File::create(file_path)?;
 | 
			
		||||
    let writer = std::io::BufWriter::new(file);
 | 
			
		||||
    serde_json::to_writer(writer, &data)?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
use crate::structs::json::{Events, MapData, NPC};
 | 
			
		||||
 | 
			
		||||
pub fn get_map_data_by_id(map_id: &str) -> Option<MapData> {
 | 
			
		||||
    let maps = crate::MAPS.lock().unwrap();
 | 
			
		||||
    maps.iter().find(|map| map.id == map_id).cloned()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn get_current_map() -> Option<MapData> {
 | 
			
		||||
    let current_map_id = crate::CURRENT_MAP_ID.lock().unwrap().clone();
 | 
			
		||||
    let maps = crate::MAPS.lock().unwrap();
 | 
			
		||||
        
 | 
			
		||||
    maps.iter().find(|map| map.id == current_map_id).cloned()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn get_map_events(map_id: &str) -> Option<Vec<Events>> {
 | 
			
		||||
    let map = get_map_data_by_id(map_id)?;
 | 
			
		||||
    Some(map.events)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn get_npc(npc_id: &str) -> Option<NPC> {
 | 
			
		||||
    let map = get_current_map()?;
 | 
			
		||||
    map.npcs.get(npc_id).cloned()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn load_new_map(map_id: &str) {
 | 
			
		||||
    let map = get_map_data_by_id(map_id).unwrap();
 | 
			
		||||
    *crate::CURRENT_MAP_ID.lock().unwrap() = map.id.clone();
 | 
			
		||||
    let coords = crate::PLAYER_COORDS.lock().unwrap().clone();
 | 
			
		||||
    if coords.get(&map.id).is_none() {
 | 
			
		||||
        // If the player has no coordinates for this map, set starting location
 | 
			
		||||
        let starting_location = map.starting_location.clone();
 | 
			
		||||
        crate::PLAYER_COORDS.lock().unwrap().insert(map.id.clone(), (starting_location[0] as u8, starting_location[1] as u8));
 | 
			
		||||
    }
 | 
			
		||||
    // let new_coords = map.starting_location.clone();
 | 
			
		||||
    // *crate::PLAYER_COORDS.lock().unwrap() = (new_coords[0] as u8, new_coords[1] as u8);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
pub mod json;
 | 
			
		||||
pub mod os;
 | 
			
		||||
pub mod maps;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
use std::io::{self, Write};
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "linux")]
 | 
			
		||||
pub fn move_cursor(x: u16, y: u16) {
 | 
			
		||||
    {
 | 
			
		||||
        let stdout = io::stdout();
 | 
			
		||||
        let mut handle = stdout.lock();
 | 
			
		||||
        write!(handle, "\x1b[{};{}H", y + 1, x + 1).unwrap();
 | 
			
		||||
        handle.flush().unwrap();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "linux")]
 | 
			
		||||
pub fn clear_console() {
 | 
			
		||||
    {
 | 
			
		||||
        let stdout = io::stdout();
 | 
			
		||||
        let mut handle = stdout.lock();
 | 
			
		||||
        write!(handle, "\x1b[2J\x1b[H").unwrap();
 | 
			
		||||
        handle.flush().unwrap();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "linux")]
 | 
			
		||||
pub fn set_terminal_title(title: &str) {
 | 
			
		||||
    let stdout = io::stdout();
 | 
			
		||||
    let mut handle = stdout.lock();
 | 
			
		||||
    write!(handle, "\x1b]0;{}\x07", title).unwrap();
 | 
			
		||||
    handle.flush().unwrap();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "linux")]
 | 
			
		||||
pub fn set_cursor_visibility(enable: bool) {
 | 
			
		||||
    let stdout = io::stdout();
 | 
			
		||||
    let mut handle = stdout.lock();
 | 
			
		||||
    if enable {
 | 
			
		||||
        write!(handle, "\x1b[?25h").unwrap(); // Show cursor
 | 
			
		||||
    } else {
 | 
			
		||||
        write!(handle, "\x1b[?25l").unwrap(); // Hide cursor
 | 
			
		||||
    }
 | 
			
		||||
    handle.flush().unwrap();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
pub mod linux;
 | 
			
		||||
pub mod windows;
 | 
			
		||||
 | 
			
		||||
pub fn move_cursor(x: u16, y: u16) {
 | 
			
		||||
    #[cfg(target_os = "linux")]
 | 
			
		||||
    linux::move_cursor(x, y);
 | 
			
		||||
    
 | 
			
		||||
    #[cfg(target_os = "windows")]
 | 
			
		||||
    windows::move_cursor(x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn clear_console() {
 | 
			
		||||
    #[cfg(target_os = "linux")]
 | 
			
		||||
    linux::clear_console();
 | 
			
		||||
    
 | 
			
		||||
    #[cfg(target_os = "windows")]
 | 
			
		||||
    windows::clear_console();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn set_terminal_title(title: &str) {
 | 
			
		||||
    #[cfg(target_os = "linux")]
 | 
			
		||||
    linux::set_terminal_title(title);
 | 
			
		||||
    
 | 
			
		||||
    #[cfg(target_os = "windows")]
 | 
			
		||||
    windows::set_terminal_title(title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn set_cursor_visibility(enable: bool) {
 | 
			
		||||
    #[cfg(target_os = "linux")]
 | 
			
		||||
    linux::set_cursor_visibility(enable);
 | 
			
		||||
    
 | 
			
		||||
    #[cfg(target_os = "windows")]
 | 
			
		||||
    windows::set_cursor_visibility(enable);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,67 @@
 | 
			
		|||
#[cfg(target_os = "windows")]
 | 
			
		||||
pub fn move_cursor(x: u16, y: u16) {
 | 
			
		||||
    {
 | 
			
		||||
        use std::io::{self, Write};
 | 
			
		||||
        use std::os::windows::io::AsRawHandle;
 | 
			
		||||
        use winapi::um::wincon::{SetConsoleCursorPosition, COORD};
 | 
			
		||||
 | 
			
		||||
        let stdout = io::stdout();
 | 
			
		||||
        let handle = stdout.as_raw_handle();
 | 
			
		||||
        let coord = COORD { X: x as i16, Y: y as i16 };
 | 
			
		||||
        unsafe {
 | 
			
		||||
            SetConsoleCursorPosition(handle, coord);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
pub fn clear_console() {
 | 
			
		||||
    {
 | 
			
		||||
        use std::io::{self, Write};
 | 
			
		||||
        use winapi::um::wincon::{GetConsoleScreenBufferInfo, COORD, CONSOLE_SCREEN_BUFFER_INFO, FillConsoleOutputCharacterA, FillConsoleOutputAttribute};
 | 
			
		||||
        use winapi::um::winbase::GetStdHandle;
 | 
			
		||||
        use winapi::um::winnt::STD_OUTPUT_HANDLE;
 | 
			
		||||
 | 
			
		||||
        let stdout = io::stdout();
 | 
			
		||||
        let handle = unsafe { GetStdHandle(STD_OUTPUT_HANDLE) };
 | 
			
		||||
        let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = unsafe { std::mem::zeroed() };
 | 
			
		||||
        
 | 
			
		||||
        unsafe {
 | 
			
		||||
            GetConsoleScreenBufferInfo(handle, &mut csbi);
 | 
			
		||||
            let size = csbi.dwSize;
 | 
			
		||||
            let coord = COORD { X: 0, Y: 0 };
 | 
			
		||||
            FillConsoleOutputCharacterA(handle, b' ' as u8, (size.X * size.Y) as u32, coord, std::ptr::null_mut());
 | 
			
		||||
            FillConsoleOutputAttribute(handle, csbi.wAttributes, (size.X * size.Y) as u32, coord, std::ptr::null_mut());
 | 
			
		||||
            SetConsoleCursorPosition(handle, coord);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
pub fn set_terminal_title(title: &str) {
 | 
			
		||||
    use std::io::{self, Write};
 | 
			
		||||
    use winapi::um::wincon::SetConsoleTitleA;
 | 
			
		||||
 | 
			
		||||
    let title_bytes = title.as_bytes();
 | 
			
		||||
    let c_title = std::ffi::CString::new(title_bytes).unwrap();
 | 
			
		||||
    
 | 
			
		||||
    unsafe {
 | 
			
		||||
        SetConsoleTitleA(c_title.as_ptr());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
pub fn set_cursor_visibility(enable: bool) {
 | 
			
		||||
    use std::io::{self, Write};
 | 
			
		||||
    use winapi::um::wincon::{SetConsoleCursorInfo, CONSOLE_CURSOR_INFO};
 | 
			
		||||
 | 
			
		||||
    let stdout = io::stdout();
 | 
			
		||||
    let handle = stdout.as_raw_handle();
 | 
			
		||||
    let mut cursor_info: CONSOLE_CURSOR_INFO = unsafe { std::mem::zeroed() };
 | 
			
		||||
    
 | 
			
		||||
    unsafe {
 | 
			
		||||
        SetConsoleCursorInfo(handle, &mut cursor_info);
 | 
			
		||||
        cursor_info.bVisible = if enable { 1 } else { 0 };
 | 
			
		||||
        SetConsoleCursorInfo(handle, &cursor_info);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue