Changelog
Track all changes and improvements made to Gurotopia
These changes are on the my-version branch of XeyyzuV2/Gurotopia.
Security & Stability
fix: stability, security and build hardening
Nine foundational fixes to harden the server against crashes and improve project infrastructure:
- main.cpp: Added null-check on
enet_host_create()— if binding to the configured port fails the server now prints an error and exits gracefully instead of dereferencing a null pointer and crashing. - Dockerfile: Rewritten as a multi-stage build (
ubuntu:24.04), addedWORKDIR,EXPOSE 17091/udpand443/tcp. Runtime image only contains runtime libraries (libssl3t64,libmariadb3) — no compiler toolchain remains. - .gitignore: Excluded
resources/ctx/server.key— the TLS private key is now auto-generated viascripts/gen-cert.shfor local dev. - Makefile: Added dependency on
resources/ctx/server.keyso the cert script runs automatically at build time. - world.hpp: Replaced fixed
int access[20]C-array withstd::vector<int>— eliminates buffer overflow risk and removes the arbitrary 20-entry cap. - database: Added
std::mutex(db_mutex) guarding everyhStmtoperation. The mutex is acquired in thehStmtconstructor vialock_guard, serialising all MariaDB access across the main thread and the detached HTTPS listener thread. - Codacy lint badge cleanup.
fix: compile errors and bugs
tile_change.cpp: Fixedlock_visualsvariable scope (moved declaration before if/else blocks, removed duplicate in the placing block).init_behaviors.cpp: Removed null-pointer dereference inon_roulette_wheelhandler.world_db.cpp: Fixedtime_pointconstruction usingsteady_clock::time_point() + milliseconds().
fix: critical compile errors
registry.hpp: Changedstruct ENetEvent&toENetEvent&— ENetEvent is a typedef,structprefix is rejected by conforming compilers.collision.hpp: Renamednamespace collisiontocollision_checkto avoid conflict withenum collisionat global scope.world_db.cpp: Fixed dangling pointer — temporary string inmake_bind_in()parameters array. Moved blob data to a namedstd::stringon the stack.world_db.hpp: Added missing#include <string>.init_behaviors.cpp: Fixedget_weather_idsignature frominttou_int.movement.cpp: Fixed signed/unsigned comparison (fg_id < items.size()).registry.cpp: Removed unused includes.
fix: vscode task fix — ucrt64 shell
Fixed .vscode/tasks.json to use ucrt64.exe instead of bash.exe for Ctrl+Shift+B builds, ensuring the proper MSYS2 UCRT64 environment is loaded.
Modular Item System
feat: modular item system with registry, properties & collision
Introduced a C++ item behavior framework replacing the hardcoded switch(item->id) approach:
Property flags (include/items/properties.hpp):
enum item_property : u_char {
PROP_DROP_SEED = 1 << 0,
PROP_NO_SEED = 1 << 1,
PROP_DROPLESS = 1 << 2,
PROP_PERMANENT = 1 << 3,
PROP_MULTI_FACING = 1 << 4,
PROP_NO_SHADOW = 1 << 5,
PROP_WRENCHABLE = 1 << 6,
PROP_AUTO_PICKUP = 1 << 7,
};Category flags (enum item_category):
CAT_RETURN,CAT_PUBLIC,CAT_HOLIDAY,CAT_UNTRADEABLE,CAT_SURPRISING_FRUIT
Behavior Registry (include/items/registry.hpp):
// Register a handler for any item ID — one line, no core file edits
item_registry::register_item(758, on_roulette_wheel, "Roulette Wheel");
item_registry::register_item(3400, on_love_potion, "Love Potion #8");
// ... 23 items registeredCollision System (include/items/collision.hpp):
namespace collision_check {
bool can_place_at(::collision col, const ::pos& player, const ::pos& target);
movement_rule get_movement_rule(::collision col);
bool is_passable(::collision col, float px, float py, int tx, int ty, bool falling);
}Movement rules: BLOCK, PASS, PLATFORM, SLAB, ONE_WAY_X, ONE_WAY_Y, ACCESS, VIP, GUILD, ACTIVATE.
refactor: complete modular item system migration
items.hpp: Replaced oldcatenum with#include "items/properties.hpp".drop.cpp: Usesitem_category::CAT_UNTRADEABLE.tile_change.cpp: Registry-first dispatch — checksitem_registry::get_handler()before falling through to type-based logic.movement.cpp: Integrated collision checking — players can no longer walk throughFULLcollision tiles, andPLATFORMtiles block falling-through.
refactor: move love chests + provider items to registry, cleanup dead code
- Registered all provider items (Chicken 872, Cow 866, Coffee Maker 1632, Sheep 3888, Tea Set 5116, Well 2798, Science Station 928).
- Registered Dice (456), Roshambo (1300), and love chests (Heartstone 392, GBC 3402, Super GBC 9350) as registry handlers.
- Removed dead love chest loot code and provider item-ID switch from
tile_change.cpp.
Currently registered items (23):
| ID | Name | Handler |
|---|---|---|
| 758 | Roulette Wheel | on_roulette_wheel |
| 1404 | Door Mover | on_door_mover |
| 822 | Water Bucket | on_water_bucket |
| 1866 | Block Glue | on_block_glue |
| 3062 | Pocket Lighter | on_pocket_lighter |
| 2480 | Megaphone | on_megaphone |
| 408 | Duct Tape | on_duct_tape |
| 3400 | Love Potion #8 | on_love_potion |
| 1488 | Experience Potion | on_exp_potion |
| 3404/3406 | Lollipops | on_lollipop |
| 3478-3492 | Paint Buckets (8) | on_paint_* |
| 1008 | ATM | on_atm |
| 872 | Chicken | on_provider_drop_next |
| 866 | Cow | on_provider_drop_next |
| 1632 | Coffee Maker | on_provider_drop_next |
| 3888 | Sheep | on_provider_drop_next |
| 5116 | Tea Set | on_provider_tea_set |
| 2798 | Well | on_provider_well |
| 928 | Science Station | on_provider_science |
| 456 | Dice | on_dice |
| 1300 | Roshambo | on_roshambo |
| 392 | Heartstone | on_love_chest |
| 3402 | GBC | on_love_chest |
| 9350 | Super GBC | on_love_chest |
World Persistence
feat: world save/load to database (persistent worlds)
Added full world persistence via MariaDB MEDIUMBLOB serialization:
- Schema:
world_statetable withname VARCHAR(100) PRIMARY KEY,owner INT,data MEDIUMBLOB,updated_at TIMESTAMP. - Serialization: Versioned binary format containing all 6000 tiles (fg, bg, state[4], hits[2], tick, label) plus doors, displays, random_blocks, objects, last_object_uid, access list, weather, lock state, and owner.
- Save:
save_world()called when last player leaves (quit_to_exit.cpp) and on graceful shutdown (safe_disconnect_peersinpeer.cpp). - Load:
load_world()called on world join (join_request.cpp). Falls back togenerate_world()if no DB data exists.
CI & Infrastructure
ci: activate workflow build setiap push di my-version
make.yml: Filtered branches to[master, my-version], building on bothwindows-latest(MSYS2) andubuntu-latest.docker.yml: Filtered branches to[master, my-version], validatesdocker build.README.md: Updated badges to point toXeyyzuV2/Gurotopiafork.