#include #include #include "curses.h" #include #include #include // read #include "../helper.h" #include "../player.h" #include "../game.h" #include "../wall.h" #include "../main.h" #include "../common.h" #include "../context.h" #include "../stubs.h" #include "../tile.h" // for DoorTile, etc. #include "../tiles/curses_tiles.h" #include "../net/sockets.h" #include "../console.h" void tickSignal() { gameLoop(); interfaceDraw(); } void interfaceSetInterval(const char *input_string) { if (input_string) { int tickrate = atoi(input_string); #if _WIN32 | _WIN64 KillTimer(NULL, win_timer); win_timer = SetTimer(NULL, 1, tickrate, (TIMERPROC) tickSignal); #else getitimer(ITIMER_REAL, &interval); interval.it_interval.tv_sec = tickrate / 1000; interval.it_interval.tv_usec = (tickrate*1000) % 1000000; setitimer(ITIMER_REAL, &interval, NULL); #endif } } int interfaceInit() { /* set up our visual display */ if ((screen = initscr()) == NULL) { perror("initscr() error'd"); return ERROR; } original_cursor = curs_set(0); // store original cursor position for restore and hide cursor keypad(screen, TRUE); // enable arrow keys/keypad noecho(); // turn off key echoing nonl(); // do not do NL->CR/NL on output cbreak(); // Handle char presses immediately, do not wait for \n if (has_colors()) { start_color(); // set up all possible color pairs using COLORS as our max (8 default) int x, y; for (x=0;x max_fd) { max_fd = new_fd; } char string[32]; char remote_ip[INET6_ADDRSTRLEN]; sprintf(string, "accept()'d, new client from %s on fd %d", inet_ntop(client_address.ss_family, get_in_addr((struct sockaddr *)&client_address), remote_ip, INET6_ADDRSTRLEN), new_fd); consoleLog(string); } } else if (i > net_socket) { // handle existing client data int bytes = 0; if((bytes = recv(i, data_buffer, sizeof data_buffer, 0)) <= 0) { if (bytes == 0) { consoleLog("lost client"); } else { consoleLog("recv() error'd"); } close(i); FD_CLR(i, &master_fds); } else { // good data //char string[sizeof data_buffer]; //sprintf(string, "client: %s", data_buffer); //consoleLog(string); consoleLog("client message"); } } } } interfaceDraw(); } return 1; } void interfaceDraw() { //clear(); int step_x = player->x - ((struct PlayerTile*)player->data)->vision; int step_y = player->y - ((struct PlayerTile*)player->data)->vision; int end_x = player->x + ((struct PlayerTile*)player->data)->vision; int end_y = player->y + ((struct PlayerTile*)player->data)->vision; float camera_offset_x = player->x - (80/2); // TODO: get term size float camera_offset_y = player->y - (24/2); while (step_x < end_x) { step_y = player->y - ((struct PlayerTile*)player->data)->vision; while (step_y < end_y) { //if (visible_matrix[step_x][step_y] & TILE_VISIBLE) { if (step_x >= 0 && step_y >= 0 && step_x < current_map->width && step_y < current_map->height) { struct Tile *current_tile; current_tile = &(current_map)->matrix[step_x][step_y]; while(current_tile) { short tile_id = current_tile->id; unsigned int type_id = current_tile->tid; int color; switch (type_id) { case WALL: color = curses_walls[tile_id].fg * COLORS + curses_walls[tile_id].bg; attron(COLOR_PAIR(color) | curses_walls[tile_id].attr); mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, curses_walls[tile_id].ch); attroff(COLOR_PAIR(color) | curses_walls[tile_id].attr); break; case FLOOR: color = curses_walls[tile_id].fg * COLORS + curses_walls[tile_id].bg; attron(COLOR_PAIR(color) | curses_walls[tile_id].attr); mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, '.'); attroff(COLOR_PAIR(color) | curses_walls[tile_id].attr); break; case DOOR: // doors work by taking the original id(0) and adding the current state(0=closed,1=open,2=broken,3=missing). For one door, you need 4 individual tiles. tile_id = tile_id*4; tile_id += ((struct DoorTile*)(current_tile->data))->state; color = curses_doors[tile_id].fg * COLORS + curses_doors[tile_id].bg; attron(COLOR_PAIR(color) | curses_doors[tile_id].attr); mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, curses_doors[tile_id].ch); attroff(COLOR_PAIR(color) | curses_doors[tile_id].attr); break; case PLAYER: color = curses_players[tile_id].fg * COLORS + curses_players[tile_id].bg; attron(COLOR_PAIR(color) | curses_players[tile_id].attr); mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, '@'); attroff(COLOR_PAIR(color) | curses_players[tile_id].attr); break; case NPC: color = curses_npcs[tile_id].fg * COLORS + curses_npcs[tile_id].bg; attron(COLOR_PAIR(color) | curses_npcs[tile_id].attr); mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, curses_npcs[tile_id].ch); attroff(COLOR_PAIR(color) | curses_npcs[tile_id].attr); break; case ITEM: color = curses_items[tile_id].fg * COLORS + curses_items[tile_id].bg; attron(COLOR_PAIR(color) | curses_items[tile_id].attr); mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, curses_items[tile_id].ch); attroff(COLOR_PAIR(color) | curses_items[tile_id].attr); break; break; } current_tile = current_tile->next; } } else { mvwaddch(screen, step_y-camera_offset_y, step_x-camera_offset_x, ' '); } step_y++; // move down } step_x++; // move right } move(player->y-camera_offset_y, player->x-camera_offset_x); if (current_context == &consoleContext) { interfaceDrawConsole(); } refresh(); } void interfaceClose() { wrefresh(screen); delwin(screen); endwin(); } /* non-main() funcs */ void interfacePrint(const char *input_string) { // TODO: "zero" out whole line before printing new one (so overlap is gone) mvwaddstr(screen, 22, 0, input_string); consoleLog(input_string); } void interfacePrintf(const char *input_string, ...) { int *byte_location; byte_location = &input_string+1; // our first arg, effectively int byte_offset; // our memory reference used for getting argument offsets from the original string char formatted_string[32];// start at 32? //int formatted_string_length = 8; int format_step = 0; int input_step = 0; char current_char = input_string[0]; formatted_string[0] = current_char; int handle_format = 0; while (current_char != '\0') { input_step++; current_char = input_string[input_step]; if (handle_format == 1) { switch(current_char) { case 'c': // for char byte_offset = *byte_location++; // our arg location handle_format = 0; format_step++; //formatted_string[format_step] = *byte_location; formatted_string[format_step] = byte_offset; // convert decimal to curses break; case 's': handle_format = 0; byte_offset = *byte_location++; // our arg location while(byte_offset != '\0') { format_step++; formatted_string[format_step] = byte_offset; byte_offset = *byte_location++; // our arg location } break; } } else if (current_char == '%') { handle_format = 1; } else { format_step++; formatted_string[format_step] = current_char; } } mvwaddstr(screen, 22, 0, formatted_string); } void interfaceDrawConsole() { int line; struct ConsoleEntry *entry; entry = console_last_entry; for (line = 7;line >= 0;line--) { move(line, 0); if (entry->size > 0) { addstr(consoleGetEntryString(entry)); } if (entry->prev) entry = entry->prev; hline(' ', 80); } move(9, 0); hline('-', 80); move(8, 0); hline(' ', 80); move(8, 0); addstr("> "); addstr(console_cmd); } void interfaceQuit() { is_running = 0; }