we have a core game-loop
This commit is contained in:
+93
-33
@@ -21,6 +21,8 @@
|
|||||||
#define MAX_SYSTEM_MESSAGE_LEN 512
|
#define MAX_SYSTEM_MESSAGE_LEN 512
|
||||||
#define GOAL_LOOPS_PER_S 50
|
#define GOAL_LOOPS_PER_S 50
|
||||||
#define GOAL_LOOP_US 1000000/GOAL_LOOPS_PER_S
|
#define GOAL_LOOP_US 1000000/GOAL_LOOPS_PER_S
|
||||||
|
#define TURN_TICK_S (3)
|
||||||
|
#define TURN_TICK_LEN (GOAL_LOOPS_PER_S * TURN_TICK_S)
|
||||||
#define LOGIN_NAME_BUFFER_LEN 16
|
#define LOGIN_NAME_BUFFER_LEN 16
|
||||||
#define PARSED_SERVER_MESSAGE_THREAD_QUEUE_LEN 16
|
#define PARSED_SERVER_MESSAGE_THREAD_QUEUE_LEN 16
|
||||||
#define SBUFLEN (512)
|
#define SBUFLEN (512)
|
||||||
@@ -49,6 +51,7 @@ typedef enum Screen {
|
|||||||
ScreenMainGame,
|
ScreenMainGame,
|
||||||
ScreenDefeat,
|
ScreenDefeat,
|
||||||
ScreenVictory,
|
ScreenVictory,
|
||||||
|
ScreenTurnTick,
|
||||||
Screen_Count
|
Screen_Count
|
||||||
} Screen;
|
} Screen;
|
||||||
|
|
||||||
@@ -149,10 +152,10 @@ typedef struct GameState {
|
|||||||
StringChunkList message_input;
|
StringChunkList message_input;
|
||||||
StarSystem map[STAR_SYSTEM_COUNT];
|
StarSystem map[STAR_SYSTEM_COUNT];
|
||||||
Pos2 pos;
|
Pos2 pos;
|
||||||
u32 destination_sys_idx;
|
u8 destination_sys_idx;
|
||||||
StarSystem current;
|
|
||||||
StationTabStates station_tab_state;
|
StationTabStates station_tab_state;
|
||||||
TransactionResult tx_result;
|
TransactionResult tx_result;
|
||||||
|
u64 turn_tick_started_on;
|
||||||
} GameState;
|
} GameState;
|
||||||
|
|
||||||
///// GLOBALS
|
///// GLOBALS
|
||||||
@@ -375,8 +378,6 @@ fn void renderStaticAssetToPixelBuffer(TuiState* tui, u8* asset, u32 len, u16 x,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn void clearServerSentState() {
|
fn void clearServerSentState() {
|
||||||
//memset(&state.current_room, 0, sizeof(RenderableRoom));
|
|
||||||
|
|
||||||
arenaClear(&state.entity_arena);
|
arenaClear(&state.entity_arena);
|
||||||
state.entities.capacity = 64;
|
state.entities.capacity = 64;
|
||||||
state.entities.length = 0;
|
state.entities.length = 0;
|
||||||
@@ -391,6 +392,7 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
ParsedServerMessage parsed = {0};
|
ParsedServerMessage parsed = {0};
|
||||||
parsed.type = msg_type;
|
parsed.type = msg_type;
|
||||||
switch (msg_type) {
|
switch (msg_type) {
|
||||||
|
case MessageTurnTick:
|
||||||
case MessageNewAccountCreated:
|
case MessageNewAccountCreated:
|
||||||
case MessageBadPw: {/*nothing to parse but the type*/} break;
|
case MessageBadPw: {/*nothing to parse but the type*/} break;
|
||||||
case MessageTransactionResult: {
|
case MessageTransactionResult: {
|
||||||
@@ -421,6 +423,8 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
} break;
|
} break;
|
||||||
case MessagePlayerDetails: {
|
case MessagePlayerDetails: {
|
||||||
parsed.ship.type = message[msg_pos++];
|
parsed.ship.type = message[msg_pos++];
|
||||||
|
parsed.ship.system_idx = message[msg_pos++];
|
||||||
|
parsed.ship.ready_to_depart = message[msg_pos++];
|
||||||
parsed.ship.drive_efficiency = message[msg_pos++];
|
parsed.ship.drive_efficiency = message[msg_pos++];
|
||||||
parsed.ship.life_support_efficiency = message[msg_pos++];
|
parsed.ship.life_support_efficiency = message[msg_pos++];
|
||||||
parsed.ship.vacuum_cargo_slots = readU16FromBufferLE(message + msg_pos);
|
parsed.ship.vacuum_cargo_slots = readU16FromBufferLE(message + msg_pos);
|
||||||
@@ -511,6 +515,10 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
while (next_net_msg != NULL) {
|
while (next_net_msg != NULL) {
|
||||||
msg_iters += 0;
|
msg_iters += 0;
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
|
case MessageTurnTick: {
|
||||||
|
state->screen = ScreenTurnTick;
|
||||||
|
state->turn_tick_started_on = loop_count;
|
||||||
|
} break;
|
||||||
case MessageTransactionResult: {
|
case MessageTransactionResult: {
|
||||||
state->station_tab_state = StationTabStateResult;
|
state->station_tab_state = StationTabStateResult;
|
||||||
MemoryCopyStruct(&state->tx_result, &msg.tx_result);
|
MemoryCopyStruct(&state->tx_result, &msg.tx_result);
|
||||||
@@ -518,6 +526,8 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
case MessagePlayerDetails: {
|
case MessagePlayerDetails: {
|
||||||
if (msg.ship.id == state->me.id) {
|
if (msg.ship.id == state->me.id) {
|
||||||
state->me.type = msg.ship.type;
|
state->me.type = msg.ship.type;
|
||||||
|
state->me.system_idx = msg.ship.system_idx;
|
||||||
|
state->me.ready_to_depart = msg.ship.ready_to_depart;
|
||||||
state->me.drive_efficiency = msg.ship.drive_efficiency;
|
state->me.drive_efficiency = msg.ship.drive_efficiency;
|
||||||
state->me.life_support_efficiency = msg.ship.life_support_efficiency;
|
state->me.life_support_efficiency = msg.ship.life_support_efficiency;
|
||||||
state->me.vacuum_cargo_slots = msg.ship.vacuum_cargo_slots;
|
state->me.vacuum_cargo_slots = msg.ship.vacuum_cargo_slots;
|
||||||
@@ -547,10 +557,10 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
} break;
|
} break;
|
||||||
case MessageSystemCommodities: {
|
case MessageSystemCommodities: {
|
||||||
u32 sys_idx = msg.id;
|
u32 sys_idx = msg.id;
|
||||||
MemoryCopyStruct(&state->current, &state->map[sys_idx]);
|
StarSystem* sys = &state->map[sys_idx];
|
||||||
for (u32 i = 0; i < MAX_PLANETS; i++) {
|
for (u32 i = 0; i < MAX_PLANETS; i++) {
|
||||||
for (u32 ii = 0; ii < Commodity_Count; ii++) {
|
for (u32 ii = 0; ii < Commodity_Count; ii++) {
|
||||||
state->current.planets[i].commodities[ii] = msg.sys.planets[i].commodities[ii];
|
sys->planets[i].commodities[ii] = msg.sys.planets[i].commodities[ii];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -582,7 +592,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
bool user_pressed_tab = input_buffer[0] == ASCII_TAB && input_buffer[1] == 0;
|
bool user_pressed_tab = input_buffer[0] == ASCII_TAB && input_buffer[1] == 0;
|
||||||
bool user_pressed_shift_tab = input_buffer[0] == '\x1b' && input_buffer[1] == '[' && input_buffer[2] == 'Z';
|
bool user_pressed_shift_tab = input_buffer[0] == '\x1b' && input_buffer[1] == '[' && input_buffer[2] == 'Z';
|
||||||
bool user_pressed_esc = input_buffer[0] == ASCII_ESCAPE && input_buffer[1] == 0;
|
bool user_pressed_esc = input_buffer[0] == ASCII_ESCAPE && input_buffer[1] == 0;
|
||||||
bool user_pressed_a_number = input_buffer[0] >= '1' && input_buffer[0] <= '9' && input_buffer[1] == 0;
|
bool user_pressed_a_number = input_buffer[0] >= '0' && input_buffer[0] <= '9' && input_buffer[1] == 0;
|
||||||
bool user_pressed_up = input_buffer[0] == 27 && input_buffer[1] == 91 && input_buffer[2] == 65;
|
bool user_pressed_up = input_buffer[0] == 27 && input_buffer[1] == 91 && input_buffer[2] == 65;
|
||||||
bool user_pressed_down = input_buffer[0] == 27 && input_buffer[1] == 91 && input_buffer[2] == 66;
|
bool user_pressed_down = input_buffer[0] == 27 && input_buffer[1] == 91 && input_buffer[2] == 66;
|
||||||
bool user_pressed_left = input_buffer[0] == 27 && input_buffer[1] == 91 && input_buffer[2] == 68;
|
bool user_pressed_left = input_buffer[0] == 27 && input_buffer[1] == 91 && input_buffer[2] == 68;
|
||||||
@@ -590,6 +600,25 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
bool user_pressed_backspace = input_buffer[0] == ASCII_BACKSPACE || input_buffer[0] == ASCII_DEL;
|
bool user_pressed_backspace = input_buffer[0] == ASCII_BACKSPACE || input_buffer[0] == ASCII_DEL;
|
||||||
bool user_pressed_enter = input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED;
|
bool user_pressed_enter = input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED;
|
||||||
switch (state->screen) {
|
switch (state->screen) {
|
||||||
|
case ScreenTurnTick: {
|
||||||
|
u32 line = 2;
|
||||||
|
StarSystem dest = state->map[state->destination_sys_idx];
|
||||||
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
|
sprintf(sbuf, "Warping to %s...", dest.name);
|
||||||
|
renderStrToBuffer(tui->frame_buffer, (screen_dimensions.width - (strlen(sbuf)+4))/2, line++, sbuf, screen_dimensions);
|
||||||
|
|
||||||
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
|
u32 frames_left = (TURN_TICK_LEN - (loop_count - state->turn_tick_started_on));
|
||||||
|
u32 seconds_left = (frames_left / GOAL_LOOPS_PER_S + 1);
|
||||||
|
sprintf(sbuf, "in %d", seconds_left);
|
||||||
|
renderStrToBuffer(tui->frame_buffer, (screen_dimensions.width - (strlen(sbuf)+4))/2, ++line, sbuf, screen_dimensions);
|
||||||
|
|
||||||
|
if (state->turn_tick_started_on + TURN_TICK_LEN < loop_count) {
|
||||||
|
state->screen = ScreenMainGame;
|
||||||
|
state->menu.len = Tab_Count;
|
||||||
|
state->menu.selected_index = TabMap;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case ScreenCreateCharacter: {
|
case ScreenCreateCharacter: {
|
||||||
//// SIMULATION
|
//// SIMULATION
|
||||||
if (state->me.id != 0) {
|
if (state->me.id != 0) {
|
||||||
@@ -607,7 +636,9 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
} else if (user_pressed_up || user_pressed_left) {
|
} else if (user_pressed_up || user_pressed_left) {
|
||||||
state->menu.selected_index--;
|
state->menu.selected_index--;
|
||||||
} else if (user_pressed_a_number) {
|
} else if (user_pressed_a_number) {
|
||||||
state->menu.selected_index = input_buffer[0] - '1';
|
if (input_buffer[0] != '0') {
|
||||||
|
state->menu.selected_index = input_buffer[0] - '1';
|
||||||
|
}
|
||||||
} else if (user_pressed_enter) {
|
} else if (user_pressed_enter) {
|
||||||
// save ship choice to our gamestate
|
// save ship choice to our gamestate
|
||||||
ShipTemplate template = SHIPS[state->menu.selected_index];
|
ShipTemplate template = SHIPS[state->menu.selected_index];
|
||||||
@@ -717,6 +748,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
.height = screen_dimensions.height - box_y - 2,
|
.height = screen_dimensions.height - box_y - 2,
|
||||||
};
|
};
|
||||||
drawAnsiBox(tui->frame_buffer, box, screen_dimensions, true);
|
drawAnsiBox(tui->frame_buffer, box, screen_dimensions, true);
|
||||||
|
StarSystem curr = state->map[state->me.system_idx];
|
||||||
switch (tab) {
|
switch (tab) {
|
||||||
case TabDebug: {
|
case TabDebug: {
|
||||||
if (input_buffer[0] == 'q' || user_pressed_esc) {
|
if (input_buffer[0] == 'q' || user_pressed_esc) {
|
||||||
@@ -762,7 +794,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
if (state->pos.x == sysx && state->pos.y == sysy) {
|
if (state->pos.x == sysx && state->pos.y == sysy) {
|
||||||
tui->frame_buffer[bufpos].background = ANSI_WHITE;
|
tui->frame_buffer[bufpos].background = ANSI_WHITE;
|
||||||
tui->frame_buffer[bufpos].foreground = ANSI_BLACK;
|
tui->frame_buffer[bufpos].foreground = ANSI_BLACK;
|
||||||
} else if (state->current.x == sysx && state->current.y == sysy) {
|
} else if (curr.x == sysx && curr.y == sysy) {
|
||||||
// highlight the system we are currently at
|
// highlight the system we are currently at
|
||||||
tui->frame_buffer[bufpos].background = ANSI_HIGHLIGHT_BLUE;
|
tui->frame_buffer[bufpos].background = ANSI_HIGHLIGHT_BLUE;
|
||||||
tui->frame_buffer[bufpos].foreground = ANSI_BLACK;
|
tui->frame_buffer[bufpos].foreground = ANSI_BLACK;
|
||||||
@@ -809,25 +841,16 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
|
|
||||||
// map key
|
// map key
|
||||||
y_off += 1+(MAP_HEIGHT*yh);
|
y_off += 1+(MAP_HEIGHT*yh);
|
||||||
for (u32 i = 0; i < xw; i++) {
|
Box current_key = { .height = yh, .width = xw, .x = x_off, .y = y_off };
|
||||||
for (u32 ii = 0; ii < yh; ii++) {
|
colorizeBox(tui, current_key, ANSI_HIGHLIGHT_BLUE, 0, ' ');
|
||||||
u32 bufpos = XYToPos(x_off+i, y_off+ii, screen_dimensions.width);
|
|
||||||
tui->frame_buffer[bufpos].background = ANSI_HIGHLIGHT_BLUE;
|
|
||||||
tui->frame_buffer[bufpos].bytes[0] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, "Your current star system:", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, "Your current star system:", screen_dimensions);
|
||||||
if (state->current.name) {
|
if (curr.name) {
|
||||||
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, state->current.name, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, curr.name, screen_dimensions);
|
||||||
}
|
}
|
||||||
y_off++;
|
y_off++;
|
||||||
for (u32 i = 0; i < xw; i++) {
|
|
||||||
for (u32 ii = 0; ii < yh; ii++) {
|
Box flight_dest_key = { .height = yh, .width = xw, .x = x_off, .y = y_off };
|
||||||
u32 bufpos = XYToPos(x_off+i, y_off+ii, screen_dimensions.width);
|
colorizeBox(tui, flight_dest_key, ANSI_HIGHLIGHT_RED, 0, ' ');
|
||||||
tui->frame_buffer[bufpos].background = ANSI_HIGHLIGHT_RED;
|
|
||||||
tui->frame_buffer[bufpos].bytes[0] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, "Flight Destination:", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, "Flight Destination:", screen_dimensions);
|
||||||
if (dest.name) {
|
if (dest.name) {
|
||||||
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, dest.name, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, x_off+5, y_off++, dest.name, screen_dimensions);
|
||||||
@@ -835,7 +858,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
y_off++;
|
y_off++;
|
||||||
|
|
||||||
Pos2 dest_pos = {dest.x, dest.y};
|
Pos2 dest_pos = {dest.x, dest.y};
|
||||||
Pos2 curr_pos = {state->current.x, state->current.y};
|
Pos2 curr_pos = {curr.x, curr.y};
|
||||||
u32 projected_fuel_cost = fuelCostForTravel(state->me.drive_efficiency, curr_pos, dest_pos);
|
u32 projected_fuel_cost = fuelCostForTravel(state->me.drive_efficiency, curr_pos, dest_pos);
|
||||||
bool have_enough_fuel = projected_fuel_cost < state->me.commodities[CommodityHydrogenFuel];
|
bool have_enough_fuel = projected_fuel_cost < state->me.commodities[CommodityHydrogenFuel];
|
||||||
MemoryZero(sbuf, SBUFLEN);
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
@@ -852,10 +875,11 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
"Not enough Fuel! Need %dkg more",
|
"Not enough Fuel! Need %dkg more",
|
||||||
projected_fuel_cost - state->me.commodities[CommodityHydrogenFuel]
|
projected_fuel_cost - state->me.commodities[CommodityHydrogenFuel]
|
||||||
);
|
);
|
||||||
for (u32 i = 0; i < strlen(sbuf); i++) {
|
Range1u32 range = {
|
||||||
u32 bufpos = XYToPos(x_off+i, y_off, screen_dimensions.width);
|
.min = XYToPos(x_off, y_off, screen_dimensions.width),
|
||||||
tui->frame_buffer[bufpos].background = ANSI_HIGHLIGHT_RED;
|
.max = XYToPos(x_off+strlen(sbuf), y_off, screen_dimensions.width),
|
||||||
}
|
};
|
||||||
|
colorizeRange(tui, range, ANSI_HIGHLIGHT_RED, 0);
|
||||||
}
|
}
|
||||||
renderStrToBuffer(tui->frame_buffer, x_off, y_off++, sbuf, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, x_off, y_off++, sbuf, screen_dimensions);
|
||||||
|
|
||||||
@@ -863,6 +887,17 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
for (u32 i = 0; i < STAR_SYSTEM_COUNT; i++) {
|
for (u32 i = 0; i < STAR_SYSTEM_COUNT; i++) {
|
||||||
if (state->pos.x == state->map[i].x && state->pos.y == state->map[i].y) {
|
if (state->pos.x == state->map[i].x && state->pos.y == state->map[i].y) {
|
||||||
state->destination_sys_idx = i;
|
state->destination_sys_idx = i;
|
||||||
|
// send the destination to the server
|
||||||
|
u32 msg_idx = 0;
|
||||||
|
UDPMessage msg = {0};
|
||||||
|
msg.address = udp->server_address;
|
||||||
|
// 1. msg type/CommandType
|
||||||
|
msg.bytes[msg_idx++] = CommandSetDestination;
|
||||||
|
// 2. buy?
|
||||||
|
msg.bytes[msg_idx++] = state->destination_sys_idx;
|
||||||
|
msg.bytes_len = msg_idx;
|
||||||
|
|
||||||
|
outgoingMessageQueuePush(network_send_queue, &msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -889,9 +924,34 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
sprintf(sbuf, "Cargo: %d / %d", used_cargo, state->me.vacuum_cargo_slots);
|
sprintf(sbuf, "Cargo: %d / %d", used_cargo, state->me.vacuum_cargo_slots);
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions);
|
||||||
|
|
||||||
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
|
sprintf(sbuf, "Ready To Depart: %s", state->me.ready_to_depart ? "yes" : "no");
|
||||||
|
Range1u32 range = {
|
||||||
|
.min = XYToPos(box.x+2, yoff, screen_dimensions.width),
|
||||||
|
.max = XYToPos(box.x+2+strlen(sbuf), yoff, screen_dimensions.width),
|
||||||
|
};
|
||||||
|
tui->cursor.x = box.x+2;
|
||||||
|
tui->cursor.y = yoff;
|
||||||
|
colorizeRange(tui, range, ANSI_WHITE, ANSI_BLACK);
|
||||||
|
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions);
|
||||||
|
|
||||||
|
if (user_pressed_enter) {
|
||||||
|
// send the "ready" or "not ready" message to the server
|
||||||
|
u32 msg_idx = 0;
|
||||||
|
UDPMessage msg = {0};
|
||||||
|
msg.address = udp->server_address;
|
||||||
|
// 1. msg type/CommandType
|
||||||
|
msg.bytes[msg_idx++] = CommandReadyStatus;
|
||||||
|
// 2. buy?
|
||||||
|
msg.bytes[msg_idx++] = !state->me.ready_to_depart;
|
||||||
|
msg.bytes_len = msg_idx;
|
||||||
|
|
||||||
|
outgoingMessageQueuePush(network_send_queue, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < Commodity_Count; i++) {
|
for (u32 i = 0; i < Commodity_Count; i++) {
|
||||||
MemoryZero(sbuf, SBUFLEN);
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
sprintf(sbuf, "%-42s %d", COMMODITY_STRINGS[i], state->me.commodities[i]);
|
sprintf(sbuf, "%-42s %d", COMMODITIES[i].name, state->me.commodities[i]);
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+4, yoff+4+i, sbuf, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, box.x+4, yoff+4+i, sbuf, screen_dimensions);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -927,7 +987,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+2, box.y+1, "Welcome to ", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, box.x+2, box.y+1, "Welcome to ", screen_dimensions);
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+2+11, box.y+1, state->current.name, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, box.x+2+11, box.y+1, curr.name, screen_dimensions);
|
||||||
|
|
||||||
// the table
|
// the table
|
||||||
TableDrawInfo info = {
|
TableDrawInfo info = {
|
||||||
@@ -937,7 +997,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
MarketCommodity rows[Commodity_Count] = { 0 };
|
MarketCommodity rows[Commodity_Count] = { 0 };
|
||||||
for (u32 i = 0; i < Commodity_Count; i++) {
|
for (u32 i = 0; i < Commodity_Count; i++) {
|
||||||
Commodity c = COMMODITIES[i];
|
Commodity c = COMMODITIES[i];
|
||||||
u32 qty = state->current.planets[0].commodities[i] + state->current.planets[1].commodities[i] + state->current.planets[2].commodities[i];
|
u32 qty = curr.planets[0].commodities[i] + curr.planets[1].commodities[i] + curr.planets[2].commodities[i];
|
||||||
rows[i].type = c.type;
|
rows[i].type = c.type;
|
||||||
rows[i].unit = c.unit;
|
rows[i].unit = c.unit;
|
||||||
rows[i].bid = priceForCommodity(i, qty, true);
|
rows[i].bid = priceForCommodity(i, qty, true);
|
||||||
|
|||||||
@@ -254,6 +254,27 @@ fn void renderStringChunkList(TuiState* tui, StringChunkList* list, u16 x, u16 y
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn void colorizeBox(TuiState* tui, Box box, u8 background, u8 foreground, u8 byte) {
|
||||||
|
for (u32 i = 0; i < box.width; i++) {
|
||||||
|
for (u32 ii = 0; ii < box.height; ii++) {
|
||||||
|
u32 bufpos = XYToPos(box.x+i, box.y+ii, tui->screen_dimensions.width);
|
||||||
|
tui->frame_buffer[bufpos].background = background;
|
||||||
|
tui->frame_buffer[bufpos].foreground = foreground;
|
||||||
|
if (byte) {
|
||||||
|
tui->frame_buffer[bufpos].bytes[0] = byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void colorizeRange(TuiState* tui, Range1u32 range, u8 background, u8 foreground) {
|
||||||
|
assert(range.max > range.min);
|
||||||
|
for (u32 i = 0; i < (range.max - range.min); i++) {
|
||||||
|
tui->frame_buffer[range.min+i].background = background;
|
||||||
|
tui->frame_buffer[range.min+i].foreground = foreground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn u32 sprintfAnsiMoveCursorTo(ptr output, u16 x, u16 y) {
|
fn u32 sprintfAnsiMoveCursorTo(ptr output, u16 x, u16 y) {
|
||||||
return sprintf(output, "\x1b[%d;%df",y,x);
|
return sprintf(output, "\x1b[%d;%df",y,x);
|
||||||
}
|
}
|
||||||
|
|||||||
+135
-27
@@ -24,10 +24,10 @@
|
|||||||
#define SERVER_PORT 7777
|
#define SERVER_PORT 7777
|
||||||
#define SERVER_MAX_HEAP_MEMORY MB(256)
|
#define SERVER_MAX_HEAP_MEMORY MB(256)
|
||||||
#define SERVER_MAX_CLIENTS 16
|
#define SERVER_MAX_CLIENTS 16
|
||||||
#define GAME_THREAD_CONCURRENCY 4
|
#define GAME_THREAD_CONCURRENCY 2
|
||||||
#define GOAL_NETWORK_SEND_LOOPS_PER_S 4
|
#define GOAL_NETWORK_SEND_LOOPS_PER_S 8
|
||||||
#define GOAL_NETWORK_SEND_LOOP_US 1000000/GOAL_NETWORK_SEND_LOOPS_PER_S
|
#define GOAL_NETWORK_SEND_LOOP_US 1000000/GOAL_NETWORK_SEND_LOOPS_PER_S
|
||||||
#define GOAL_GAME_LOOPS_PER_S 4
|
#define GOAL_GAME_LOOPS_PER_S 24
|
||||||
#define GOAL_GAME_LOOP_US 1000000/GOAL_GAME_LOOPS_PER_S
|
#define GOAL_GAME_LOOP_US 1000000/GOAL_GAME_LOOPS_PER_S
|
||||||
#define CLIENT_TIMEOUT_FRAMES GOAL_GAME_LOOPS_PER_S*3
|
#define CLIENT_TIMEOUT_FRAMES GOAL_GAME_LOOPS_PER_S*3
|
||||||
#define CHUNK_SIZE 64
|
#define CHUNK_SIZE 64
|
||||||
@@ -71,8 +71,9 @@ typedef struct Entity {
|
|||||||
} Entity;
|
} Entity;
|
||||||
|
|
||||||
typedef struct Account {
|
typedef struct Account {
|
||||||
|
u8 destination_sys_idx;
|
||||||
|
bool changed;
|
||||||
u32 id; // the index in the array
|
u32 id; // the index in the array
|
||||||
Pos2 pos;
|
|
||||||
String name;
|
String name;
|
||||||
String pw;
|
String pw;
|
||||||
PlayerShip ship;
|
PlayerShip ship;
|
||||||
@@ -114,6 +115,7 @@ typedef struct ClientList {
|
|||||||
} ClientList;
|
} ClientList;
|
||||||
|
|
||||||
typedef struct State {
|
typedef struct State {
|
||||||
|
bool all_accounts_ready;
|
||||||
Mutex client_mutex;
|
Mutex client_mutex;
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
ClientList clients;
|
ClientList clients;
|
||||||
@@ -373,7 +375,7 @@ fn u32 findClientHandleBySocketAddress(ClientList* clients, SocketAddress addres
|
|||||||
|
|
||||||
fn StarSystem* findAccountsSystem(Account* a) {
|
fn StarSystem* findAccountsSystem(Account* a) {
|
||||||
for (u32 i = 0; i < STAR_SYSTEM_COUNT; i++) {
|
for (u32 i = 0; i < STAR_SYSTEM_COUNT; i++) {
|
||||||
if (state.map[i].x == a->pos.x && state.map[i].y == a->pos.y) {
|
if (i == a->ship.system_idx) {
|
||||||
return &state.map[i];
|
return &state.map[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,11 +420,13 @@ fn void sendMessageTransactionResult(SocketAddress addr, u32 qty, bool buying, u
|
|||||||
printf("%s sent\n", MESSAGE_STRINGS[outgoing_message.bytes[0]]);
|
printf("%s sent\n", MESSAGE_STRINGS[outgoing_message.bytes[0]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void sendMessagePlayerDetails(PlayerShip ship, SocketAddress addr) {
|
fn UDPMessage makeMessagePlayerDetails(PlayerShip ship) {
|
||||||
UDPMessage outgoing_message = {.address = addr};
|
UDPMessage outgoing_message = {0};
|
||||||
u32 msg_i = 0;
|
u32 msg_i = 0;
|
||||||
outgoing_message.bytes[msg_i++] = (u8)MessagePlayerDetails;
|
outgoing_message.bytes[msg_i++] = (u8)MessagePlayerDetails;
|
||||||
outgoing_message.bytes[msg_i++] = ship.type;
|
outgoing_message.bytes[msg_i++] = ship.type;
|
||||||
|
outgoing_message.bytes[msg_i++] = ship.system_idx;
|
||||||
|
outgoing_message.bytes[msg_i++] = ship.ready_to_depart;
|
||||||
outgoing_message.bytes[msg_i++] = ship.drive_efficiency;
|
outgoing_message.bytes[msg_i++] = ship.drive_efficiency;
|
||||||
outgoing_message.bytes[msg_i++] = ship.life_support_efficiency;
|
outgoing_message.bytes[msg_i++] = ship.life_support_efficiency;
|
||||||
msg_i += writeU16ToBufferLE(outgoing_message.bytes + msg_i, ship.vacuum_cargo_slots);
|
msg_i += writeU16ToBufferLE(outgoing_message.bytes + msg_i, ship.vacuum_cargo_slots);
|
||||||
@@ -439,8 +443,13 @@ fn void sendMessagePlayerDetails(PlayerShip ship, SocketAddress addr) {
|
|||||||
for (u32 i = 0; i < Commodity_Count; i++) {
|
for (u32 i = 0; i < Commodity_Count; i++) {
|
||||||
msg_i += writeU32ToBufferLE(outgoing_message.bytes + msg_i, ship.commodities[i]);
|
msg_i += writeU32ToBufferLE(outgoing_message.bytes + msg_i, ship.commodities[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
outgoing_message.bytes_len = msg_i;
|
outgoing_message.bytes_len = msg_i;
|
||||||
|
return outgoing_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void sendMessagePlayerDetails(PlayerShip ship, SocketAddress addr) {
|
||||||
|
UDPMessage outgoing_message = makeMessagePlayerDetails(ship);
|
||||||
|
outgoing_message.address = addr;
|
||||||
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
||||||
printf("%s sent\n", MESSAGE_STRINGS[outgoing_message.bytes[0]]);
|
printf("%s sent\n", MESSAGE_STRINGS[outgoing_message.bytes[0]]);
|
||||||
}
|
}
|
||||||
@@ -496,6 +505,12 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
} break;
|
} break;
|
||||||
case CommandKeepAlive:
|
case CommandKeepAlive:
|
||||||
break;
|
break;
|
||||||
|
case CommandSetDestination: {
|
||||||
|
parsed.byte = message[1]; // index of system in array
|
||||||
|
} break;
|
||||||
|
case CommandReadyStatus: {
|
||||||
|
parsed.byte = message[1]; // boolean ready_to_depart
|
||||||
|
} break;
|
||||||
case CommandTransact: {
|
case CommandTransact: {
|
||||||
printf("command transact received\n");
|
printf("command transact received\n");
|
||||||
parsed.byte = message[1]; // buy?
|
parsed.byte = message[1]; // buy?
|
||||||
@@ -557,10 +572,23 @@ fn void* sendNetworkUpdates(void* sock) {
|
|||||||
// continue; // they are still creating their character
|
// continue; // they are still creating their character
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// update allthe changed systems
|
// update all the changed systems
|
||||||
for (u32 i = 0; i < STAR_SYSTEM_COUNT; i++) {
|
UDPMessage msg_data;
|
||||||
if (state.map[i].changed == true) {
|
for (u32 ii = 0; ii < STAR_SYSTEM_COUNT; ii++) {
|
||||||
UDPMessage msg_data = makeMessageSystemCommodities(&state.map[i]);
|
if (state.map[ii].changed == true) {
|
||||||
|
msg_data = makeMessageSystemCommodities(&state.map[ii]);
|
||||||
|
u8List msg = {
|
||||||
|
.capacity = UDP_MAX_MESSAGE_LEN,
|
||||||
|
.items = msg_data.bytes,
|
||||||
|
.length = msg_data.bytes_len,
|
||||||
|
};
|
||||||
|
sendUDPu8List(socket, &client.address, &msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// update all the changed accounts
|
||||||
|
for (u32 ii = 0; ii < ACCOUNT_LEN; ii++) {
|
||||||
|
if (state.accounts[ii].changed == true) {
|
||||||
|
msg_data = makeMessagePlayerDetails(state.accounts[ii].ship);
|
||||||
u8List msg = {
|
u8List msg = {
|
||||||
.capacity = UDP_MAX_MESSAGE_LEN,
|
.capacity = UDP_MAX_MESSAGE_LEN,
|
||||||
.items = msg_data.bytes,
|
.items = msg_data.bytes,
|
||||||
@@ -572,9 +600,14 @@ fn void* sendNetworkUpdates(void* sock) {
|
|||||||
}
|
}
|
||||||
} unlockMutex(&state.client_mutex);
|
} unlockMutex(&state.client_mutex);
|
||||||
|
|
||||||
for (u32 i = 0; i < STAR_SYSTEM_COUNT; i++) {
|
lockMutex(&state.mutex); {
|
||||||
state.map[i].changed = false;
|
for (u32 i = 0; i < STAR_SYSTEM_COUNT; i++) {
|
||||||
}
|
state.map[i].changed = false;
|
||||||
|
}
|
||||||
|
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
||||||
|
state.accounts[i].changed = false;
|
||||||
|
}
|
||||||
|
} unlockMutex(&state.mutex);
|
||||||
|
|
||||||
u32 loop_duration = osTimeMicrosecondsNow() - loop_start;
|
u32 loop_duration = osTimeMicrosecondsNow() - loop_start;
|
||||||
i32 remaining_time = GOAL_NETWORK_SEND_LOOP_US - loop_duration;
|
i32 remaining_time = GOAL_NETWORK_SEND_LOOP_US - loop_duration;
|
||||||
@@ -585,6 +618,10 @@ fn void* sendNetworkUpdates(void* sock) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bool accountIsEmpty(Account* a) {
|
||||||
|
return a->id == 0 && a->name.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
fn void* gameLoop(void* params) {
|
fn void* gameLoop(void* params) {
|
||||||
LaneCtx* lane_ctx = (LaneCtx*)params;
|
LaneCtx* lane_ctx = (LaneCtx*)params;
|
||||||
ThreadContext tctx = {
|
ThreadContext tctx = {
|
||||||
@@ -620,6 +657,23 @@ fn void* gameLoop(void* params) {
|
|||||||
u32 client_handle = findClientHandleBySocketAddress(&state.clients, sender);
|
u32 client_handle = findClientHandleBySocketAddress(&state.clients, sender);
|
||||||
Client* client = &state.clients.items[client_handle];
|
Client* client = &state.clients.items[client_handle];
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
|
case CommandSetDestination: {
|
||||||
|
Account* account = &state.accounts[client->account_id];
|
||||||
|
account->destination_sys_idx = msg.byte;
|
||||||
|
} break;
|
||||||
|
case CommandReadyStatus: {
|
||||||
|
Account* account = &state.accounts[client->account_id];
|
||||||
|
account->ship.ready_to_depart = msg.byte;
|
||||||
|
sendMessagePlayerDetails(account->ship, sender);
|
||||||
|
state.all_accounts_ready = true;
|
||||||
|
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
||||||
|
if (!accountIsEmpty(&state.accounts[i])) {
|
||||||
|
if (state.accounts[i].ship.ready_to_depart == false) {
|
||||||
|
state.all_accounts_ready = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case CommandTransact: {
|
case CommandTransact: {
|
||||||
printf("Transact for client_handle=%d, on #%lld", client_handle, state.frame);
|
printf("Transact for client_handle=%d, on #%lld", client_handle, state.frame);
|
||||||
bool is_buying_from_system = msg.byte;
|
bool is_buying_from_system = msg.byte;
|
||||||
@@ -629,7 +683,10 @@ fn void* gameLoop(void* params) {
|
|||||||
u32 qty_traded = 0;
|
u32 qty_traded = 0;
|
||||||
u32 credit_value = 0;
|
u32 credit_value = 0;
|
||||||
if (is_buying_from_system) {
|
if (is_buying_from_system) {
|
||||||
u32 ship_space = account->ship.vacuum_cargo_slots - usedVacuumCargoSlots(account->ship);
|
u32 ship_space = MAX_u32;
|
||||||
|
if (COMMODITIES[msg.commodity].unit == StorageUnitContainer) {
|
||||||
|
ship_space = account->ship.vacuum_cargo_slots - usedVacuumCargoSlots(account->ship);
|
||||||
|
}
|
||||||
for (u32 amount_to_buy = Min(msg.qty, total_available); amount_to_buy > 0; amount_to_buy--, total_available--, ship_space--) {
|
for (u32 amount_to_buy = Min(msg.qty, total_available); amount_to_buy > 0; amount_to_buy--, total_available--, ship_space--) {
|
||||||
u32 price = priceForCommodity(msg.commodity, total_available, false);
|
u32 price = priceForCommodity(msg.commodity, total_available, false);
|
||||||
if (price > account->ship.credits || ship_space == 0) {
|
if (price > account->ship.credits || ship_space == 0) {
|
||||||
@@ -717,7 +774,7 @@ fn void* gameLoop(void* params) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
||||||
if (state.accounts[i].id == 0 && state.accounts[i].name.length == 0) {
|
if (accountIsEmpty(&state.accounts[i])) {
|
||||||
existing_account = &state.accounts[i];
|
existing_account = &state.accounts[i];
|
||||||
existing_account->id = i;
|
existing_account->id = i;
|
||||||
break;
|
break;
|
||||||
@@ -772,8 +829,7 @@ fn void* gameLoop(void* params) {
|
|||||||
printf("ship_type=%s, client_handle=%d, acct_id=%d\n", SHIP_TYPE_STRINGS[msg.byte], client_handle, account->id);
|
printf("ship_type=%s, client_handle=%d, acct_id=%d\n", SHIP_TYPE_STRINGS[msg.byte], client_handle, account->id);
|
||||||
u32 starting_system_idx = rand() % STAR_SYSTEM_COUNT;
|
u32 starting_system_idx = rand() % STAR_SYSTEM_COUNT;
|
||||||
StarSystem starting_system = state.map[starting_system_idx];
|
StarSystem starting_system = state.map[starting_system_idx];
|
||||||
account->pos.x = starting_system.x;
|
account->ship.system_idx = starting_system_idx;
|
||||||
account->pos.y = starting_system.y;
|
|
||||||
|
|
||||||
// tell the client their account id
|
// tell the client their account id
|
||||||
outgoing_message.address = sender;
|
outgoing_message.address = sender;
|
||||||
@@ -817,21 +873,73 @@ fn void* gameLoop(void* params) {
|
|||||||
msg_iters++;
|
msg_iters++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.all_accounts_ready) {
|
||||||
|
for (u32 i = 1; i < SERVER_MAX_CLIENTS; i++) {
|
||||||
|
if (state.clients.items[i].last_ping != 0) {
|
||||||
|
outgoing_message.address = state.clients.items[i].address;
|
||||||
|
outgoing_message.bytes_len = 1;
|
||||||
|
outgoing_message.bytes[0] = (u8)MessageTurnTick;
|
||||||
|
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} unlockMutex(&state.mutex); unlockMutex(&state.client_mutex);
|
} unlockMutex(&state.mutex); unlockMutex(&state.client_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
LaneSync();
|
LaneSync();
|
||||||
|
|
||||||
// 2. tick non-user entities
|
// 2. tick non-user entities
|
||||||
// iterate all the rooms
|
if (state.all_accounts_ready) {
|
||||||
/*
|
// tick all the star systems
|
||||||
Room* room = NULL;
|
StarSystem* sys = NULL;
|
||||||
Range1u64 room_range = LaneRange(MAX_ROOMS);
|
Range1u64 sys_range = LaneRange(STAR_SYSTEM_COUNT);
|
||||||
for (u32 i = room_range.min; i < room_range.max; i++) {
|
for (u32 i = sys_range.min; i < sys_range.max; i++) {
|
||||||
room = &state.rooms->items[i];
|
sys = &state.map[i];
|
||||||
simulateRoom(&scratch_arena, room, burn_tick, regen_hp_tick);
|
sys->changed = true;
|
||||||
|
for (u32 ii = 0; ii < Commodity_Count; ii++) {
|
||||||
|
for (u32 iii = 0; iii < MAX_PLANETS; iii++) {
|
||||||
|
if (sys->planets[iii].type != PlanetTypeNull) {
|
||||||
|
if (sys->planets[iii].commodities[ii] > COMMODITIES[ii].consumption) {
|
||||||
|
sys->planets[iii].commodities[ii] -= COMMODITIES[ii].consumption;
|
||||||
|
} else {
|
||||||
|
sys->planets[iii].commodities[ii] = 0;
|
||||||
|
}
|
||||||
|
sys->planets[iii].commodities[ii] += sys->planets[iii].production[ii];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move all the players
|
||||||
|
u32 player_count = 0;
|
||||||
|
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
||||||
|
if (!accountIsEmpty(&state.accounts[i])) {
|
||||||
|
player_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Range1u64 ship_range = LaneRange(player_count);
|
||||||
|
for (u32 i = ship_range.min; i < ship_range.max; i++) {
|
||||||
|
Account* acct = &state.accounts[i];
|
||||||
|
StarSystem dest = state.map[acct->destination_sys_idx];
|
||||||
|
StarSystem current = state.map[acct->ship.system_idx];
|
||||||
|
Pos2 dest_pos = {dest.x, dest.y};
|
||||||
|
Pos2 curr_pos = {current.x, current.y};
|
||||||
|
u32 projected_fuel_cost = fuelCostForTravel(acct->ship.drive_efficiency, curr_pos, dest_pos);
|
||||||
|
bool have_enough_fuel = projected_fuel_cost < acct->ship.commodities[CommodityHydrogenFuel];
|
||||||
|
if (have_enough_fuel) {
|
||||||
|
// remove the fuel they used on the journey
|
||||||
|
acct->ship.commodities[CommodityHydrogenFuel] -= projected_fuel_cost;
|
||||||
|
// set the pos to be the system they had as destination
|
||||||
|
acct->ship.system_idx = acct->destination_sys_idx;
|
||||||
|
}
|
||||||
|
acct->ship.ready_to_depart = false;
|
||||||
|
acct->changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO pay the mortgage payment
|
||||||
}
|
}
|
||||||
*/
|
state.all_accounts_ready = false;
|
||||||
|
|
||||||
// 3. scratch cleanup
|
// 3. scratch cleanup
|
||||||
arenaClear(&scratch_arena);
|
arenaClear(&scratch_arena);
|
||||||
|
|||||||
+12
-2
@@ -314,6 +314,8 @@ fn f32 priceForCommodity(CommodityType type, u32 quantity, bool bid) {
|
|||||||
|
|
||||||
typedef struct PlayerShip {
|
typedef struct PlayerShip {
|
||||||
ShipType type;
|
ShipType type;
|
||||||
|
bool ready_to_depart;
|
||||||
|
u8 system_idx;
|
||||||
u8 drive_efficiency;
|
u8 drive_efficiency;
|
||||||
u8 life_support_efficiency;
|
u8 life_support_efficiency;
|
||||||
u16 vacuum_cargo_slots;
|
u16 vacuum_cargo_slots;
|
||||||
@@ -334,7 +336,9 @@ typedef struct PlayerShip {
|
|||||||
fn u32 usedVacuumCargoSlots(PlayerShip ship) {
|
fn u32 usedVacuumCargoSlots(PlayerShip ship) {
|
||||||
u32 used_cargo = 0;
|
u32 used_cargo = 0;
|
||||||
for (u32 i = 0; i < Commodity_Count; i++) {
|
for (u32 i = 0; i < Commodity_Count; i++) {
|
||||||
used_cargo += ship.commodities[i];
|
if (COMMODITIES[i].unit == StorageUnitContainer) {
|
||||||
|
used_cargo += ship.commodities[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return used_cargo;
|
return used_cargo;
|
||||||
}
|
}
|
||||||
@@ -431,14 +435,18 @@ typedef enum CommandType {
|
|||||||
CommandLogin,
|
CommandLogin,
|
||||||
CommandCreateCharacter,
|
CommandCreateCharacter,
|
||||||
CommandTransact,
|
CommandTransact,
|
||||||
|
CommandReadyStatus,
|
||||||
|
CommandSetDestination,
|
||||||
CommandType_Count,
|
CommandType_Count,
|
||||||
} CommandType;
|
} CommandType;
|
||||||
|
|
||||||
static const char* command_type_strings[] = {
|
static const char* command_type_strings[CommandType_Count] = {
|
||||||
"Invalid",
|
"Invalid",
|
||||||
"KeepAlive",
|
"KeepAlive",
|
||||||
"Login",
|
"Login",
|
||||||
"CreateCharacter",
|
"CreateCharacter",
|
||||||
|
"ReadyStatus",
|
||||||
|
"SetDestination",
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ENTITY_HEADER_MESSAGE_SIZE (8+8+1+1+1)
|
#define ENTITY_HEADER_MESSAGE_SIZE (8+8+1+1+1)
|
||||||
@@ -452,6 +460,7 @@ typedef enum Message {
|
|||||||
MessageSystemCommodities,
|
MessageSystemCommodities,
|
||||||
MessagePlayerDetails,
|
MessagePlayerDetails,
|
||||||
MessageTransactionResult,
|
MessageTransactionResult,
|
||||||
|
MessageTurnTick,
|
||||||
Message_Count,
|
Message_Count,
|
||||||
} Message;
|
} Message;
|
||||||
|
|
||||||
@@ -464,6 +473,7 @@ static const char* MESSAGE_STRINGS[] = {
|
|||||||
"SystemCommodities",
|
"SystemCommodities",
|
||||||
"PlayerDetails",
|
"PlayerDetails",
|
||||||
"TransactionResult",
|
"TransactionResult",
|
||||||
|
"TurnTick",
|
||||||
};
|
};
|
||||||
|
|
||||||
fn u32 fuelCostForTravel(u32 drive_efficiency, Pos2 current, Pos2 dest) {
|
fn u32 fuelCostForTravel(u32 drive_efficiency, Pos2 current, Pos2 dest) {
|
||||||
|
|||||||
Reference in New Issue
Block a user