Skip to content

Instantly share code, notes, and snippets.

@increpare
Created March 12, 2026 16:20
Show Gist options
  • Select an option

  • Save increpare/becac8047bbf4354d2b0527fc7c7b9a0 to your computer and use it in GitHub Desktop.

Select an option

Save increpare/becac8047bbf4354d2b0527fc7c7b9a0 to your computer and use it in GitHub Desktop.
OeufSerializer
String OeufSerializer::serialize_to_string(const Array &p_savedat) const {
if (p_savedat.size() != 5) {
ERR_PRINT(vformat("serialize_to_string: Invalid savedat array size (expected 5, got %d)", p_savedat.size()));
return "";
}
Dictionary level_state_data = p_savedat[0];
Array voxel_data = level_state_data["voxel_data"];
Array layers = level_state_data["layers"];
// entities - support both legacy (array) and versioned (dict with "version" + "entities")
Variant entities_slot = p_savedat[4];
int entities_version = 0;
Array entities;
if (entities_slot.get_type() == Variant::DICTIONARY) {
Dictionary d = entities_slot;
entities_version = d["version"];
entities = d["entities"];
} else {
entities = entities_slot;
}
TextWriter writer;
int voxel_count = voxel_data.size();
int entities_count = entities.size();
int layers_count = layers.size();
// Rough estimate: ~40 bytes per voxel, ~100 per entity, plus overhead
size_t estimated_size = 1024 + (voxel_count * 40) + (entities_count * 100);
writer.reserve(estimated_size);
// version
writer.put_tag("version");
writer.put_int(level_state_data["version"]);
writer.end_line();
// voxel_data
writer.put_tag("voxels");
writer.put_int(voxel_count);
writer.end_line();
Vector3i last_position = Vector3i(0, 0, 0);
for (int i = 0; i < voxel_count; i++) {
Array voxel = voxel_data[i];
Vector3i v = voxel[0];
Vector3i delta = v - last_position;
writer.put_tag("vx");
if (delta.x >= -128 && delta.x <= 127 && delta.y >= -128 && delta.y <= 127 && delta.z >= -128 && delta.z <= 127) {
writer.put_int(0); // type delta
writer.put_int(delta.x);
writer.put_int(delta.y);
writer.put_int(delta.z);
} else {
writer.put_int(1); // type absolute
writer.put_int(v.x);
writer.put_int(v.y);
writer.put_int(v.z);
}
last_position = v;
writer.put_int(voxel[1]); // blocktype
writer.put_int(voxel[2]); // tx
writer.put_int(voxel[3]); // ty
int rot = voxel[4];
int vflip = (bool)voxel[5] ? 1 : 0;
writer.put_int(rot + vflip * 4);
writer.put_int(voxel[6]); // extra
writer.end_line();
}
// layers
writer.put_tag("layers");
writer.put_int(layers_count);
writer.end_line();
for (int i = 0; i < layers_count; i++) {
Dictionary layer = layers[i];
writer.put_tag("l");
writer.put_string(layer["name"]);
writer.put_int((bool)layer["visible"] ? 1 : 0);
writer.end_line();
}
// selected_layer_idx
writer.put_tag("selected");
writer.put_int(level_state_data["selected_layer_idx"]);
writer.end_line();
// camera
writer.put_tag("cp");
writer.put_vector3(p_savedat[1]);
writer.end_line();
writer.put_tag("cbr");
writer.put_vector3(p_savedat[2]);
writer.end_line();
writer.put_tag("crr");
writer.put_vector3(p_savedat[3]);
writer.end_line();
// entities (version, then count)
writer.put_tag("entities_version");
writer.put_int(entities_version);
writer.end_line();
writer.put_tag("entities");
writer.put_int(entities_count);
writer.end_line();
for (int i = 0; i < entities_count; i++) {
Dictionary entity = entities[i];
writer.put_tag("e");
writer.put_string(entity["name"]);
int32_t entity_type = entity["type"];
writer.put_int(entity_type);
writer.put_vector3i(entity["position"]);
writer.put_int(entity["layer"]);
uint8_t flags = 0;
String meta_str;
String asset_name_str;
int32_t dir_value = 0;
if (entity.has("dir")) {
dir_value = entity["dir"];
flags |= 0x01;
}
if (entity.has("meta")) {
meta_str = entity["meta"];
if (!meta_str.is_empty()) flags |= 0x02;
}
if (entity.has("asset_name")) {
asset_name_str = entity["asset_name"];
if (!asset_name_str.is_empty()) flags |= 0x04;
}
writer.put_int(flags);
if (flags & 0x01) writer.put_int(dir_value + 1);
if (flags & 0x02) writer.put_string(meta_str);
if (flags & 0x04) writer.put_string(asset_name_str);
if (entity_type == 3) {
Vector3i size_EDS = entity.has("size_EDS") ? (Vector3i)entity["size_EDS"] : Vector3i();
writer.put_vector3i(size_EDS);
Vector3i size_WUN = entity.has("size_WUN") ? (Vector3i)entity["size_WUN"] : Vector3i();
writer.put_vector3i(size_WUN);
}
writer.end_line();
}
return writer.get_string();
}
Array OeufSerializer::deserialize_from_string(const godot::String &p_string) const {
TextReaderTokenized reader(p_string);
Array savedat;
Dictionary level_state_data;
TypedArray<Array> voxel_data;
Array layers;
TypedArray<Dictionary> entities;
int entities_version = 0;
Vector3 camera_pos;
Vector3 camera_base_rotation;
Vector3 camera_rot_rotation;
Vector3i last_position = Vector3i(0, 0, 0);
while (reader.has_more_lines()) {
TextReaderTokenized::LineTokenizer t = reader.next_line();
String tag = t.next_token();
if (tag == "") continue;
if (tag == "version") {
level_state_data[StringName("version")] = t.next_int();
} else if (tag == "entities_version") {
entities_version = t.next_int();
} else if (tag == "entities") {
t.next_int(); // consume count (entities are parsed from "e" tags)
} else if (tag == "vx") {
Array voxel;
int type = t.next_int();
if (type == 0) {
last_position += t.next_vector3i();
} else {
last_position = t.next_vector3i();
}
voxel.append(last_position);
voxel.append(t.next_int()); // blocktype
voxel.append(t.next_int()); // tx
voxel.append(t.next_int()); // ty
int rot_vflip = t.next_int();
voxel.append(rot_vflip & 3);
voxel.append((rot_vflip & 4) != 0);
voxel.append(t.next_int()); // extra
voxel_data.append(voxel);
} else if (tag == "l") {
Dictionary layer;
layer[StringName("name")] = t.next_token();
layer[StringName("visible")] = t.next_int() != 0;
layers.append(layer);
} else if (tag == "selected") {
level_state_data[StringName("selected_layer_idx")] = t.next_int();
} else if (tag == "cp") {
camera_pos = t.next_vector3();
} else if (tag == "cbr") {
camera_base_rotation = t.next_vector3();
} else if (tag == "crr") {
camera_rot_rotation = t.next_vector3();
} else if (tag == "e") {
Dictionary entity;
entity[StringName("name")] = t.next_token();
int type = t.next_int();
entity[StringName("type")] = type;
entity[StringName("position")] = t.next_vector3i();
if (entities_version >= 3){
//entities have a layer
entity[StringName("layer")] = t.next_int();
} else {
entity[StringName("layer")] = 0;
}
int flags = t.next_int();
if (flags & 0x01) entity[StringName("dir")] = t.next_int() - 1;
if (flags & 0x02) entity[StringName("meta")] = t.next_token();
if (flags & 0x04) entity[StringName("asset_name")] = t.next_token();
if (type == 3) {
entity[StringName("size_EDS")] = t.next_vector3i();
entity[StringName("size_WUN")] = t.next_vector3i();
}
entities.append(entity);
}
}
level_state_data[StringName("voxel_data")] = voxel_data;
level_state_data[StringName("layers")] = layers;
Dictionary entities_dict;
entities_dict[StringName("version")] = entities_version;
entities_dict[StringName("entities")] = entities;
savedat.append(level_state_data);
savedat.append(camera_pos);
savedat.append(camera_base_rotation);
savedat.append(camera_rot_rotation);
savedat.append(entities_dict);
return savedat;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment