Initial commit
							parent
							
								
									6bf7e9c1fe
								
							
						
					
					
						commit
						0220cedf10
					
				| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					build/
 | 
				
			||||||
 | 
					.vscode/
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,48 @@
 | 
				
			||||||
 | 
					cmake_minimum_required(VERSION 3.26)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					project(collision_cacher)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD 20)
 | 
				
			||||||
 | 
					set(CMAKE_CXX_STANDARD_REQUIRED ON)
 | 
				
			||||||
 | 
					set(CMAKE_SHARED_LINKER_FLAGS "-Os -s -m32 -static-libgcc -static-libstdc++ -static")
 | 
				
			||||||
 | 
					set(CMAKE_SHARED_LIBRARY_PREFIX "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (NOT DEFINED ALPACABOT_DIR)
 | 
				
			||||||
 | 
					  set(ALPACABOT_DIR $ENV{USERPROFILE}\\AlpacaBot)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (NOT DEFINED ALPACABOT_INCLUDE_DIR)
 | 
				
			||||||
 | 
					  set(ALPACABOT_INCLUDE_DIR ${ALPACABOT_DIR}\\Include)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (NOT DEFINED ALPACABOT_LIB_DIR)
 | 
				
			||||||
 | 
					  set(ALPACABOT_LIB_DIR ${ALPACABOT_DIR}\\Library)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (NOT DEFINED ALPACABOT_SCRIPT_DIR)
 | 
				
			||||||
 | 
					  set(ALPACABOT_SCRIPT_DIR ${ALPACABOT_DIR}\\Script\\Local)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(SOURCE_FILES
 | 
				
			||||||
 | 
					    src/main.cpp
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_target_properties(${PROJECT_NAME} PROPERTIES
 | 
				
			||||||
 | 
					  RUNTIME_OUTPUT_DIRECTORY ${ALPACABOT_SCRIPT_DIR}/${PROJECT_NAME}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_include_directories(${PROJECT_NAME} PRIVATE
 | 
				
			||||||
 | 
					  ${CMAKE_CURRENT_SOURCE_DIR}/include
 | 
				
			||||||
 | 
					  ${ALPACABOT_INCLUDE_DIR}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_directories(${PROJECT_NAME} PRIVATE
 | 
				
			||||||
 | 
					  ${ALPACABOT_LIB_DIR}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_link_libraries(${PROJECT_NAME} PRIVATE
 | 
				
			||||||
 | 
					  AlpacaLibrary
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.1 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 37 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.6 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
						 | 
					@ -0,0 +1,134 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/csv"
 | 
				
			||||||
 | 
						"image"
 | 
				
			||||||
 | 
						"image/color"
 | 
				
			||||||
 | 
						"image/png"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						// Path to the CSV file
 | 
				
			||||||
 | 
						userProfile := os.Getenv("USERPROFILE")
 | 
				
			||||||
 | 
						filePath := filepath.Join(userProfile, "AlpacaBot", "Collision Data", "collision_data.csv")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Open the CSV file
 | 
				
			||||||
 | 
						file, err := os.Open(filePath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Failed to open file: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer file.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read the CSV file
 | 
				
			||||||
 | 
						reader := csv.NewReader(file)
 | 
				
			||||||
 | 
						records, err := reader.ReadAll()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("Failed to read file: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Group records by plane
 | 
				
			||||||
 | 
						dataByPlane := make(map[string][][]string)
 | 
				
			||||||
 | 
						for _, record := range records[1:] { // Skip the header row
 | 
				
			||||||
 | 
							plane := record[1]
 | 
				
			||||||
 | 
							dataByPlane[plane] = append(dataByPlane[plane], record)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for plane, records := range dataByPlane {
 | 
				
			||||||
 | 
							// Find the min and max x, y coordinates
 | 
				
			||||||
 | 
							minX, minY, maxX, maxY := 1<<31-1, 1<<31-1, 0, 0
 | 
				
			||||||
 | 
							for _, record := range records {
 | 
				
			||||||
 | 
								x, err := strconv.Atoi(record[2])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								y, err := strconv.Atoi(record[3])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if x < minX {
 | 
				
			||||||
 | 
									minX = x
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if y < minY {
 | 
				
			||||||
 | 
									minY = y
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if x > maxX {
 | 
				
			||||||
 | 
									maxX = x
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if y > maxY {
 | 
				
			||||||
 | 
									maxY = y
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Create an empty image
 | 
				
			||||||
 | 
							width, height := maxX-minX+1, maxY-minY+1
 | 
				
			||||||
 | 
							img := image.NewRGBA(image.Rect(0, 0, width, height))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Fill in the image with data
 | 
				
			||||||
 | 
							for _, record := range records {
 | 
				
			||||||
 | 
								x, err := strconv.Atoi(record[2])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								y, err := strconv.Atoi(record[3])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								flag, err := strconv.Atoi(record[4])
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Determine the color based on the flag value
 | 
				
			||||||
 | 
								var col color.Color
 | 
				
			||||||
 | 
								switch flag {
 | 
				
			||||||
 | 
								case 0:
 | 
				
			||||||
 | 
									col = color.RGBA{0, 255, 0, 255}
 | 
				
			||||||
 | 
								case 0xFFFFFF:
 | 
				
			||||||
 | 
									col = color.RGBA{255, 0, 0, 255}
 | 
				
			||||||
 | 
								case 0x1000000:
 | 
				
			||||||
 | 
									col = color.RGBA{0, 0, 255, 255}
 | 
				
			||||||
 | 
								case 0x100:
 | 
				
			||||||
 | 
									col = color.RGBA{255, 255, 0, 255}
 | 
				
			||||||
 | 
								case 0x20000:
 | 
				
			||||||
 | 
									col = color.RGBA{128, 0, 128, 255}
 | 
				
			||||||
 | 
								case 0x200000:
 | 
				
			||||||
 | 
									col = color.RGBA{255, 128, 0, 255}
 | 
				
			||||||
 | 
								case 0x2:
 | 
				
			||||||
 | 
									col = color.RGBA{0, 255, 255, 255}
 | 
				
			||||||
 | 
								case 0x8:
 | 
				
			||||||
 | 
									col = color.RGBA{255, 0, 255, 255}
 | 
				
			||||||
 | 
								case 0x20:
 | 
				
			||||||
 | 
									col = color.RGBA{128, 128, 0, 255}
 | 
				
			||||||
 | 
								case 0x80:
 | 
				
			||||||
 | 
									col = color.RGBA{128, 128, 128, 255}
 | 
				
			||||||
 | 
								case 0x4:
 | 
				
			||||||
 | 
									col = color.RGBA{0, 128, 0, 255}
 | 
				
			||||||
 | 
								case 0x10:
 | 
				
			||||||
 | 
									col = color.RGBA{128, 0, 0, 255}
 | 
				
			||||||
 | 
								case 0x40:
 | 
				
			||||||
 | 
									col = color.RGBA{0, 0, 128, 255}
 | 
				
			||||||
 | 
								case 0x1:
 | 
				
			||||||
 | 
									col = color.RGBA{0, 128, 128, 255}
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									col = color.RGBA{0, 0, 0, 255}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Set the pixel in the image
 | 
				
			||||||
 | 
								img.Set(x-minX, height-(y-minY)-1, col)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Save the image to a file
 | 
				
			||||||
 | 
							outputFileName := "collision_map_plane_" + plane + ".png"
 | 
				
			||||||
 | 
							outputFile, err := os.Create(outputFileName)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Fatalf("Failed to create output file: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer outputFile.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							png.Encode(outputFile, img)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,247 @@
 | 
				
			||||||
 | 
					#include <filesystem>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <unordered_set>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Game/Core.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Setup() {
 | 
				
			||||||
 | 
					  ScriptInfo Info;
 | 
				
			||||||
 | 
					  Info.Name = "Collision Cacher";
 | 
				
			||||||
 | 
					  Info.Description = "Caches collision data around the player.";
 | 
				
			||||||
 | 
					  Info.Version = "1.00";
 | 
				
			||||||
 | 
					  Info.Category = "Magic";
 | 
				
			||||||
 | 
					  Info.Author = "Warren";
 | 
				
			||||||
 | 
					  Info.UID = "UID";
 | 
				
			||||||
 | 
					  Info.ForumPage = "forum.alpacabot.org";
 | 
				
			||||||
 | 
					  SetScriptInfo(Info);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class region_key {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    std::int32_t region;
 | 
				
			||||||
 | 
					    std::int32_t plane;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    region_key() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    region_key(std::int32_t region, std::int32_t plane)
 | 
				
			||||||
 | 
					        : region(region), plane(plane) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool operator==(const region_key& other) const {
 | 
				
			||||||
 | 
					        return region == other.region && plane == other.plane;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class collision {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    Tile tile;
 | 
				
			||||||
 | 
					    Pathfinding::COLLISION_FLAG flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    collision(const Tile& tile, Pathfinding::COLLISION_FLAG flag) : tile(tile), flag(flag) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool operator==(const collision& other) const {
 | 
				
			||||||
 | 
					        return tile == other.tile && flag == other.flag;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace std {
 | 
				
			||||||
 | 
					    template<>
 | 
				
			||||||
 | 
					    struct hash<region_key> {
 | 
				
			||||||
 | 
					        std::size_t operator()(const region_key& key) const {
 | 
				
			||||||
 | 
					            std::size_t h1 = std::hash<std::int32_t>()(key.region);
 | 
				
			||||||
 | 
					            std::size_t h2 = std::hash<std::int32_t>()(key.plane);
 | 
				
			||||||
 | 
					            return h1 ^ (h2 << 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<>
 | 
				
			||||||
 | 
					    struct hash<Tile> {
 | 
				
			||||||
 | 
					        std::size_t operator()(const Tile& tile) const {
 | 
				
			||||||
 | 
					            std::size_t h1 = std::hash<std::int32_t>()(tile.X);
 | 
				
			||||||
 | 
					            std::size_t h2 = std::hash<std::int32_t>()(tile.Y);
 | 
				
			||||||
 | 
					            std::size_t h3 = std::hash<std::int32_t>()(tile.Plane);
 | 
				
			||||||
 | 
					            return h1 ^ (h2 << 1) ^ (h3 << 2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template<>
 | 
				
			||||||
 | 
					    struct hash<collision> {
 | 
				
			||||||
 | 
					        std::size_t operator()(const collision& collision) const {
 | 
				
			||||||
 | 
					            std::size_t h1 = std::hash<Tile>()(collision.tile);
 | 
				
			||||||
 | 
					            std::size_t h2 = std::hash<std::int32_t>()(static_cast<std::int32_t>(collision.flag));
 | 
				
			||||||
 | 
					            return h1 ^ (h2 << 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::unordered_map<region_key, std::unordered_set<collision>> cached_regions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cache_current_region() {
 | 
				
			||||||
 | 
					    const auto get_tile_region = [](const Tile& tile) {
 | 
				
			||||||
 | 
					        return ((std::int32_t)(((tile.X >> 6) << 8) | (tile.Y >> 6)));
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto to_world_tile = [](const Pathfinding::TileNode& node, std::int32_t client_x, std::int32_t client_y, std::int32_t client_plane) {
 | 
				
			||||||
 | 
					        return Tile(
 | 
				
			||||||
 | 
					            node.X + client_x,
 | 
				
			||||||
 | 
					            node.Y + client_y,
 | 
				
			||||||
 | 
					            client_plane
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Pathfinding::GenerateNodes();
 | 
				
			||||||
 | 
					    const std::int32_t client_x = Internal::GetClientX();
 | 
				
			||||||
 | 
					    const std::int32_t client_y = Internal::GetClientY();
 | 
				
			||||||
 | 
					    const std::int32_t client_plane = Internal::GetClientPlane();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for (const auto& nodes : Pathfinding::GetNodes()) {
 | 
				
			||||||
 | 
					        for (const auto& node : nodes) {
 | 
				
			||||||
 | 
					            const auto flag = node.Flag;
 | 
				
			||||||
 | 
					            const auto world_tile = to_world_tile(node, client_x, client_y, client_plane);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((flag & Pathfinding::UNINITIALIZED) || flag == Pathfinding::UNINITIALIZED) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if ((flag == Pathfinding::CLOSED)) {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::int32_t current_region = get_tile_region(world_tile);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            cached_regions[region_key(current_region, client_plane)].emplace(world_tile, static_cast<Pathfinding::COLLISION_FLAG>(flag));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void paint() {
 | 
				
			||||||
 | 
					    Paint::Clear();
 | 
				
			||||||
 | 
					    std::vector<std::string> texts;
 | 
				
			||||||
 | 
					    auto local_tile = Players::GetLocal().GetTile();
 | 
				
			||||||
 | 
					    for (const auto& [key, collision_data] : cached_regions) {
 | 
				
			||||||
 | 
					        texts.emplace_back(
 | 
				
			||||||
 | 
					            "(" + std::to_string(key.region) + ", " + std::to_string(key.plane) + "): " + std::to_string(collision_data.size())
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const auto& collision : collision_data) {
 | 
				
			||||||
 | 
					            if (collision.tile.DistanceFrom(local_tile) > 12)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if ((collision.flag & Pathfinding::BLOCKED) || (collision.flag & Pathfinding::OCCUPIED)) {
 | 
				
			||||||
 | 
					                Paint::DrawTile(collision.tile, 255, 0, 0, 255);
 | 
				
			||||||
 | 
					            } else if (collision.flag & Pathfinding::NORTH) {
 | 
				
			||||||
 | 
					                Paint::DrawTile(collision.tile, 255, 0, 255, 255);
 | 
				
			||||||
 | 
					            } else if (collision.flag & Pathfinding::EAST) {
 | 
				
			||||||
 | 
					                Paint::DrawTile(collision.tile, 0, 255, 0, 255);
 | 
				
			||||||
 | 
					            } else if (collision.flag & Pathfinding::SOUTH) {
 | 
				
			||||||
 | 
					                Paint::DrawTile(collision.tile, 0, 0, 255, 255);
 | 
				
			||||||
 | 
					            } else if (collision.flag & Pathfinding::WEST) {
 | 
				
			||||||
 | 
					                Paint::DrawTile(collision.tile, 255, 165, 0, 255);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Point p = Point(0, 5);
 | 
				
			||||||
 | 
					    for (const auto& text : texts) {
 | 
				
			||||||
 | 
					        p += Point(0, 20);
 | 
				
			||||||
 | 
					        Paint::DrawString(text, p, 0, 255, 0, 255);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Paint::SwapBuffer();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void verify_and_clean() {
 | 
				
			||||||
 | 
					    // verify each tile in a region actually belongs to it, if not, remove it
 | 
				
			||||||
 | 
					    for (auto it = cached_regions.begin(); it != cached_regions.end();) {
 | 
				
			||||||
 | 
					        const auto& [key, collision_data] = *it;
 | 
				
			||||||
 | 
					        const auto get_tile_region = [](const Tile& tile) {
 | 
				
			||||||
 | 
					            return ((std::int32_t)(((tile.X >> 6) << 8) | (tile.Y >> 6)));
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const auto& collision : collision_data) {
 | 
				
			||||||
 | 
					            if (get_tile_region(collision.tile) != key.region) {
 | 
				
			||||||
 | 
					                it->second.erase(collision);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (it->second.empty()) {
 | 
				
			||||||
 | 
					            it = cached_regions.erase(it);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ++it;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void write_collision_data(std::ofstream& file) {
 | 
				
			||||||
 | 
					    file << "region,plane,x,y,flag\n";
 | 
				
			||||||
 | 
					    verify_and_clean();
 | 
				
			||||||
 | 
					    for (const auto& [key, collision_data] : cached_regions) {
 | 
				
			||||||
 | 
					        for (const auto& collision : collision_data) {
 | 
				
			||||||
 | 
					            if (collision.flag == Pathfinding::OPEN)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            file << key.region << "," << key.plane << "," << collision.tile.X << "," << collision.tile.Y << "," << static_cast<std::int32_t>(collision.flag) << "\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void read_collision_data(std::ifstream& file) {
 | 
				
			||||||
 | 
					    std::string line;
 | 
				
			||||||
 | 
					    std::getline(file, line); // skip csv header
 | 
				
			||||||
 | 
					    while (std::getline(file, line)) {
 | 
				
			||||||
 | 
					        std::stringstream ss(line);
 | 
				
			||||||
 | 
					        std::string token;
 | 
				
			||||||
 | 
					        std::vector<std::string> tokens;
 | 
				
			||||||
 | 
					        while (std::getline(ss, token, ',')) {
 | 
				
			||||||
 | 
					            tokens.emplace_back(token);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto region = std::stoi(tokens[0]);
 | 
				
			||||||
 | 
					        const auto plane = std::stoi(tokens[1]);
 | 
				
			||||||
 | 
					        const auto x = std::stoi(tokens[2]);
 | 
				
			||||||
 | 
					        const auto y = std::stoi(tokens[3]);
 | 
				
			||||||
 | 
					        const auto flag = static_cast<Pathfinding::COLLISION_FLAG>(std::stoi(tokens[4]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cached_regions[region_key(region, plane)].emplace(Tile(x, y, plane), flag);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string data_url() {
 | 
				
			||||||
 | 
					    char *userprofile = std::getenv("USERPROFILE");
 | 
				
			||||||
 | 
					    if (userprofile == nullptr)
 | 
				
			||||||
 | 
					        return "";
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return std::string(userprofile) + "\\AlpacaBot\\Collision Data\\collision_data.csv";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool OnStart() { 
 | 
				
			||||||
 | 
					    SetLoopDelay(5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string path = data_url();
 | 
				
			||||||
 | 
					    std::ifstream file(path);
 | 
				
			||||||
 | 
					    read_collision_data(file);
 | 
				
			||||||
 | 
					    return true; 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Loop() {
 | 
				
			||||||
 | 
					    cache_current_region();
 | 
				
			||||||
 | 
					    paint();
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool OnBreak() {
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void OnEnd() {
 | 
				
			||||||
 | 
					    char *userprofile = std::getenv("USERPROFILE");
 | 
				
			||||||
 | 
					    if (userprofile == nullptr)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    std::string path = data_url();
 | 
				
			||||||
 | 
					    if (!std::filesystem::exists(path)) {
 | 
				
			||||||
 | 
					        std::filesystem::create_directories(std::string(userprofile) + "\\AlpacaBot\\Collision Data\\");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::ofstream file(path);
 | 
				
			||||||
 | 
					    write_collision_data(file);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue