#include "grid_to_dict.h" #include #include #include #include using namespace godot; static void build_rooms_and_machines(grid_t g, Array &rooms, Array &machines) { /* Bucket cells by room_id and machine_id. room_id and machine_id are 1..255. */ struct Bucket { TypedArray cells; Vector2i gate = Vector2i(-1, -1); }; Bucket rbuckets[256]; Bucket mbuckets[256]; /* Also collect marker-per-cell for each machine. */ Dictionary mmarkers[256]; for (int y = 0; y < DROWS; y++) { for (int x = 0; x < DCOLS; x++) { const cell_t *c = &g[y][x]; Vector2i p(x, y); if (c->room_id > 0) { rbuckets[c->room_id].cells.push_back(p); } if (c->machine_id > 0) { mbuckets[c->machine_id].cells.push_back(p); if (c->flags & F_MACHINE_GATE) { mbuckets[c->machine_id].gate = p; } if (c->surface != MK_NONE) { Dictionary &mk = mmarkers[c->machine_id]; int key = (int)c->surface; TypedArray list; if (mk.has(key)) { list = (TypedArray)(Variant)mk[key]; } list.push_back(p); mk[key] = list; } } } } for (int i = 1; i < 256; i++) { if (rbuckets[i].cells.size() == 0) continue; Dictionary d; d["id"] = i; d["cells"] = rbuckets[i].cells; rooms.push_back(d); } for (int i = 1; i < 256; i++) { if (mbuckets[i].cells.size() == 0) continue; Dictionary d; d["id"] = i; d["interior_cells"] = mbuckets[i].cells; d["gate"] = mbuckets[i].gate; d["markers"] = mmarkers[i]; machines.push_back(d); } } Dictionary godot::grid_to_dictionary(grid_t g, int seed, int depth, bool add_metadata) { const int N = DCOLS * DROWS; PackedByteArray terrain; terrain.resize(N); PackedByteArray liquid; liquid.resize(N); PackedByteArray room_id; room_id.resize(N); PackedByteArray machine_id; machine_id.resize(N); PackedByteArray surface; surface.resize(N); PackedInt32Array flags; flags.resize(N); uint8_t *t = terrain.ptrw(); uint8_t *lq = liquid.ptrw(); uint8_t *ri = room_id.ptrw(); uint8_t *mi = machine_id.ptrw(); uint8_t *sf = surface.ptrw(); int32_t *fl = flags.ptrw(); Vector2i stairs_up(-1, -1), stairs_down(-1, -1); int i = 0; for (int y = 0; y < DROWS; y++) { for (int x = 0; x < DCOLS; x++, i++) { const cell_t *c = &g[y][x]; t[i] = c->terrain; lq[i] = c->liquid; ri[i] = c->room_id; mi[i] = c->machine_id; sf[i] = c->surface; fl[i] = (int32_t)c->flags; if (c->terrain == T_STAIRS_UP) stairs_up = Vector2i(x, y); if (c->terrain == T_STAIRS_DOWN) stairs_down = Vector2i(x, y); } } Dictionary d; d["seed"] = seed; d["depth"] = depth; d["width"] = DCOLS; d["height"] = DROWS; d["terrain"] = terrain; d["liquid"] = liquid; d["flags"] = flags; d["room_id"] = room_id; d["machine_id"] = machine_id; d["surface"] = surface; d["stairs_up"] = stairs_up; d["stairs_down"] = stairs_down; if (add_metadata) { Array rooms; Array machines; build_rooms_and_machines(g, rooms, machines); d["rooms"] = rooms; d["machines"] = machines; } return d; } Dictionary godot::cell_to_dictionary(grid_t g, int x, int y) { Dictionary d; if (!grid_in_bounds(x, y)) return d; const cell_t *c = &g[y][x]; d["x"] = x; d["y"] = y; d["terrain"] = (int)c->terrain; d["liquid"] = (int)c->liquid; d["surface"] = (int)c->surface; d["flags"] = (int)c->flags; d["room_id"] = (int)c->room_id; d["machine_id"] = (int)c->machine_id; return d; }