diff --git a/chunk420.data b/chunk420.data index 1a1b51b..4578c33 100644 Binary files a/chunk420.data and b/chunk420.data differ diff --git a/src/bot.c b/src/bot.c index e67446d..86740c5 100644 --- a/src/bot.c +++ b/src/bot.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "obcb.h" #include "packets.h" @@ -9,6 +10,10 @@ unsigned char chunk_current[OBCB_CHUNK_SIZE_BYTES], chunk_target[OBCB_CHUNK_SIZE int dst_chunk_id = 420; +void rot(int n, int *x, int *y, int rx, int ry); +int xy2d(int n, int x, int y); +void d2xy(int n, int d, int *x, int *y); + const uint8_t shuffle[256] = { 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, 8, @@ -44,6 +49,7 @@ const uint8_t shuffle[256] = { 159, 95, 223, 63, 191, 127, 255 }; +bool has_data = false; static void obcb_mg_handler(struct mg_connection *c, int ev, void *ev_data) { if (ev == MG_EV_OPEN) { printf("Connected to WebSocket\n"); @@ -58,6 +64,7 @@ static void obcb_mg_handler(struct mg_connection *c, int ev, void *ev_data) { struct obcb_msg_stats stats; memcpy(&stats, &wsm->data.buf[1], sizeof(stats)); } else if (wsm->data.buf[0] == OBCB_MSG_FULL_STATE_RESPONSE) { struct obcb_msg_full_state_response state; memcpy(&state, &wsm->data.buf[1], sizeof(state)); + has_data = true; if (state.chunk_index == dst_chunk_id) { memcpy(chunk_current, state.bitmap, OBCB_CHUNK_SIZE_BYTES); } @@ -110,12 +117,31 @@ int main(void) { int render_thread(void *_conn) { struct mg_connection *ws = _conn; - for (int i = 0; true; i = (i + 1) % (512 * 512)) { + srand(time(0)); + + while (!has_data) { + usleep(1000); // spin + } + + int failure = 0; + for (int i = (rand() % OBCB_CHUNK_SIZE); true; i = (i + 1) % OBCB_CHUNK_SIZE) { +#if 1 int blk_index = i / 256; int blk_pos = shuffle[i % 256]; int ox = blk_pos & 15, oy = blk_pos >> 4; +#if 1 + int x = (blk_index & 31) * 16 + ox; + int y = (blk_index >> 5) * 16 + oy; +#else int x = (blk_index & 31) + ox * 32; int y = (blk_index >> 5) + oy * 32; +#endif + +#else + int x, y; + d2xy(512, i, &x, &y); +#endif + int index = x + y * 512; int byte = index >> 3, bit = index & 7; @@ -123,7 +149,52 @@ int render_thread(void *_conn) { if ((chunk_current[byte] & mask) != (chunk_target[byte] & mask)) { obcb_send_toggle_bit(ws, index + dst_chunk_id * OBCB_CHUNK_SIZE); - usleep(5000); + usleep(2500); + } else if (failure++ > 1024) { + usleep(1000); + failure = 0; } } } + + +//convert (x,y) to d +int xy2d (int n, int x, int y) { + int rx, ry, s, d=0; + for (s=n/2; s>0; s/=2) { + rx = (x & s) > 0; + ry = (y & s) > 0; + d += s * s * ((3 * rx) ^ ry); + rot(n, &x, &y, rx, ry); + } + return d; +} + +//convert d to (x,y) +void d2xy(int n, int d, int *x, int *y) { + int rx, ry, s, t=d; + *x = *y = 0; + for (s=1; s #include #include +#include #include #include "obcb.h" #include "packets.h" @@ -12,6 +13,8 @@ struct mg_connection *ws = NULL; int chunk_id = 420; int connected_clients = 0; +double last_msg_time = 0; + static void obcb_mg_handler(struct mg_connection *c, int ev, void *ev_data) { if (ev == MG_EV_OPEN) { printf("Connected to WebSocket\n"); @@ -34,18 +37,20 @@ static void obcb_mg_handler(struct mg_connection *c, int ev, void *ev_data) { for (int i = 0; i < OBCB_CHUNK_SIZE; i++) { view[i] = state.bitmap[i >> 3] & (1 << (i & 7)) ? 0xff : 0x00; } + last_msg_time = GetTime(); } else if (wsm->data.buf[0] == OBCB_MSG_PARTIAL_STATE_UPDATE) { struct obcb_msg_partial_state_update update; memcpy(&update, &wsm->data.buf[1], sizeof(update)); + uint32_t chunk_index = update.offset / OBCB_CHUNK_SIZE_BYTES; uint32_t byte_offset = update.offset % OBCB_CHUNK_SIZE_BYTES; if (chunk_index != chunk_id) return; - printf("Got partial update: %d %d\n", chunk_index, byte_offset); unsigned char *view = c->fn_data; - for (int i = 0; i < OBCB_UPDATE_CHUNK_SIZE; i++) { + for (int i = 0; i < OBCB_UPDATE_CHUNK_SIZE * 8; i++) { view[i + byte_offset * 8] = update.chunk[i >> 3] & (1 << (i & 7)) ? 0xFF : 0x00; } + last_msg_time = GetTime(); } else { printf("UNHANDLED MESSAGE 0x%02x\n", wsm->data.buf[0]); } @@ -60,6 +65,8 @@ static int mongoose_thread(void *_mgr) { return 0; } +void DrawTextShadow(Font font, const char *txt, int x, int y, int size, Color color); + int main(void) { InitWindow(512, 512, "obcb-1chunk"); SetTargetFPS(60); @@ -67,6 +74,8 @@ int main(void) { thrd_t mongoose_manager_thrd; thrd_create(&mongoose_manager_thrd, mongoose_thread, 0); + Font font = LoadFontEx("/home/kc/.local/share/fonts/DepartureMono-Regular.otf", 14, 0, 512); + Image img = { .data = MemAlloc(512 * 512), .width = 512, @@ -80,17 +89,32 @@ int main(void) { struct mg_connection *ws = mg_ws_connect(&manager, "ws://bitmap-ws.alula.me/", obcb_mg_handler, img.data, "%s", "maidcore/4.2.0 (kc.is.being.pet)\r\n"); if (!ws) return 1; - obcb_send_full_state_request(ws, chunk_id); obcb_send_partial_subscription(ws, chunk_id); + obcb_send_full_state_request(ws, chunk_id); for (int frame = 0; !WindowShouldClose(); frame++) { - if ((frame % 512) == 511) { + if (IsKeyPressed(KEY_R)) { printf("Requesting state again\n"); obcb_send_full_state_request(ws, chunk_id); } + BeginDrawing(); UpdateTexture(tex, img.data); DrawTexture(tex, 0, 0, WHITE); + double time_since_msg = GetTime() - last_msg_time; + if (time_since_msg > 10) { + DrawTextShadow(font, TextFormat("%.1f seconds since last message", time_since_msg), 8, 8, 14, RED); + } EndDrawing(); } } + +void DrawTextShadow(Font font, const char *txt, int x, int y, int size, Color color) { + Vector2 pos = { x, y }; + for (int oy = -3; oy <= 3; oy++) { + for (int ox = -3; ox <= 3; ox++) { + DrawTextEx(font, txt, Vector2Add(pos, (Vector2) { ox, oy }), size, 0, BLACK); + } + } + DrawTextEx(font, txt, pos, size, 0, color); +} diff --git a/src/live.c b/src/live.c index 690af86..3cb6cda 100644 --- a/src/live.c +++ b/src/live.c @@ -109,7 +109,7 @@ static void obcb_mg_handler(struct mg_connection *c, int ev, void *ev_data) { } else if (wsm->data.buf[0] == OBCB_MSG_PARTIAL_STATE_UPDATE) { struct obcb_msg_partial_state_update update; memcpy(&update, &wsm->data.buf[1], sizeof(update)); printf("PARTIAL UPDATE AT %d\n", update.offset); - for (int i = 0; i < OBCB_UPDATE_CHUNK_SIZE; i++) { + for (int i = 0; i < OBCB_UPDATE_CHUNK_SIZE * 8; i++) { int index = update.offset * 8 + i; int x = index % 32768, y = index / 32768; int chunk_x = x / 1024, chunk_y = y / 1024;