you can accept a passenger job offer

This commit is contained in:
Tenari
2026-03-17 07:44:48 -05:00
parent 09a7eb507a
commit 6ec461ef3e
3 changed files with 247 additions and 33 deletions
+182 -22
View File
@@ -30,7 +30,7 @@
///// TYPES ///// TYPES
typedef enum Tab { typedef enum Tab {
TabDebug, TabDebug,
TabChat, // TabChat,
TabMap, TabMap,
TabShip, TabShip,
TabMarket, TabMarket,
@@ -160,6 +160,8 @@ typedef struct GameState {
u8 destination_sys_idx; u8 destination_sys_idx;
MarketTabStates market_tab_state; MarketTabStates market_tab_state;
ShipTabStates ship_tab_states; ShipTabStates ship_tab_states;
PassengersTabStates passenger_tab_state;
bool passenger_job_accepted;
TransactionResult tx_result; TransactionResult tx_result;
u64 turn_tick_started_on; u64 turn_tick_started_on;
} GameState; } GameState;
@@ -173,7 +175,7 @@ global u8 system_message_index = 0;
global GameState state = {0}; global GameState state = {0};
global OutgoingMessageQueue* network_send_queue = {0}; global OutgoingMessageQueue* network_send_queue = {0};
global ParsedServerMessageThreadQueue* network_recv_queue = {0}; global ParsedServerMessageThreadQueue* network_recv_queue = {0};
global str TAB_STRS[Tab_Count] = {"Debug", "Chat", "Map", "Ship", "Market", "Passengers"}; global str TAB_STRS[Tab_Count] = {"Debug", /*"Chat",*/ "Map", "Ship", "Market", "Passengers"};
global FieldDescriptor COMPARE_COMMODITY_FIELDS[STAR_SYSTEM_COUNT] = { global FieldDescriptor COMPARE_COMMODITY_FIELDS[STAR_SYSTEM_COUNT] = {
{ "System", FieldTypeString, offsetof(CompareCommodity, system_name), 16 }, { "System", FieldTypeString, offsetof(CompareCommodity, system_name), 16 },
{ "Bid", FieldTypeU32, offsetof(CompareCommodity, bid), 6 }, { "Bid", FieldTypeU32, offsetof(CompareCommodity, bid), 6 },
@@ -322,13 +324,24 @@ fn void resetTabRow(Tab tab) {
if (state.menu.selected_index == TabMarket) { if (state.menu.selected_index == TabMarket) {
state.row.len = Commodity_Count; state.row.len = Commodity_Count;
state.row.selected_index = 0; state.row.selected_index = 0;
state.modal_choice.selected_index = 0;
state.modal_choice.len = 2;
} else if (state.menu.selected_index == TabShip) { } else if (state.menu.selected_index == TabShip) {
state.ship_tab_states = ShipTabStateMain; state.ship_tab_states = ShipTabStateMain;
state.row.len = 2; state.row.len = 2;
state.row.selected_index = 0; state.row.selected_index = 0;
} else if (state.menu.selected_index == TabPassengers) { } else if (state.menu.selected_index == TabPassengers) {
state.row.len = 0;// TODO the number of available passenger missions StarSystem s = state.map[state.me.system_idx];
u32 offer_count = 0;
for (u32 i = 0; i < MAX_PASSENGER_JOB_OFFERS; i++) {
if (s.offers[i].people > 0) {
offer_count += 1;
}
}
state.row.len = offer_count;
state.row.selected_index = 0; state.row.selected_index = 0;
state.modal_choice.selected_index = 0;
state.modal_choice.len = 2;
} }
} }
@@ -365,14 +378,20 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
} break; } break;
case MessageSystemPassengers: { case MessageSystemPassengers: {
parsed.byte = message[msg_pos++]; parsed.byte = message[msg_pos++];
u32 i = 0; u32 i;
while (msg_pos < len) { for (i = 0; msg_pos < len; i++) {
parsed.offers[i].goal_system_idx = message[msg_pos++]; parsed.offers[i].goal_system_idx = message[msg_pos++];
parsed.offers[i].people = message[msg_pos++]; parsed.offers[i].people = message[msg_pos++];
parsed.offers[i].time_limit = message[msg_pos++]; parsed.offers[i].time_limit = message[msg_pos++];
parsed.offers[i].offer = readU32FromBufferLE(message + msg_pos); parsed.offers[i].offer = readU32FromBufferLE(message + msg_pos);
msg_pos += 4; msg_pos += 4;
} }
u8 buf[128] = {0};
sprintf((ptr)buf, "Got %d passenger jobs for %s", i, STAR_NAMES[parsed.byte]);
addSystemMessage(buf);
} break;
case MessageJobAcceptResult: {
parsed.byte = message[msg_pos++]; // boolean success/fail
} break; } break;
case MessageTransactionResult: { case MessageTransactionResult: {
parsed.tx_result.buying = message[msg_pos++]; parsed.tx_result.buying = message[msg_pos++];
@@ -392,7 +411,6 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
} }
} break; } break;
case MessageSystemCommodities: { case MessageSystemCommodities: {
addSystemMessage((u8*)"Got prices ");
parsed.id = (u64)message[msg_pos++]; parsed.id = (u64)message[msg_pos++];
u32 planet_count = message[msg_pos++]; u32 planet_count = message[msg_pos++];
for (u32 i = 0; i < planet_count; i++) { for (u32 i = 0; i < planet_count; i++) {
@@ -432,6 +450,13 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
for (u32 i = 0; i < Commodity_Count; i++, msg_pos += 4) { for (u32 i = 0; i < Commodity_Count; i++, msg_pos += 4) {
parsed.ship.commodities[i] = readU32FromBufferLE(message + msg_pos); parsed.ship.commodities[i] = readU32FromBufferLE(message + msg_pos);
} }
for (u32 i = 0; i < MAX_PASSENGER_BERTHS; i++) {
parsed.ship.passengers[i].goal_system_idx = message[msg_pos++];
parsed.ship.passengers[i].people = message[msg_pos++];
parsed.ship.passengers[i].turns_remaining = message[msg_pos++];
parsed.ship.passengers[i].reward = readU32FromBufferLE(message + msg_pos);
msg_pos += 4;
}
} break; } break;
case MessageCharacterId: { case MessageCharacterId: {
parsed.id = readU64FromBufferLE(message + 1); parsed.id = readU64FromBufferLE(message + 1);
@@ -486,12 +511,30 @@ fn void drawStatusLine(TuiState* tui, ptr sbuf, PlayerShip* me, u32 x, u32 y) {
}; };
colorizeRange(tui, range, ANSI_HIGHLIGHT_YELLOW, ANSI_BLACK); colorizeRange(tui, range, ANSI_HIGHLIGHT_YELLOW, ANSI_BLACK);
renderStrToBuffer(tui->frame_buffer, x, y, sbuf, tui->screen_dimensions); renderStrToBuffer(tui->frame_buffer, x, y, sbuf, tui->screen_dimensions);
MemoryZero(sbuf, SBUFLEN); MemoryZero(sbuf, SBUFLEN);
sprintf(sbuf, " %d / %d cargo ", usedVacuumCargoSlots(*me), me->vacuum_cargo_slots); sprintf(sbuf, " %d / %d cargo ", usedVacuumCargoSlots(*me), me->vacuum_cargo_slots);
range.min = range.max; range.min = range.max;
range.max = range.min+strlen(sbuf); range.max = range.min+strlen(sbuf);
colorizeRange(tui, range, ANSI_DULL_BLUE, ANSI_WHITE); colorizeRange(tui, range, ANSI_DULL_BLUE, ANSI_WHITE);
renderStrToBuffer(tui->frame_buffer, range.min % tui->screen_dimensions.width, y, sbuf, tui->screen_dimensions); renderStrToBuffer(tui->frame_buffer, range.min % tui->screen_dimensions.width, y, sbuf, tui->screen_dimensions);
MemoryZero(sbuf, SBUFLEN);
sprintf(sbuf, " %d / %d berths ", shipUsedPassengerBerths(*me), me->passenger_berths);
range.min = range.max;
range.max = range.min+strlen(sbuf);
colorizeRange(tui, range, ANSI_DARK_GREEN, ANSI_WHITE);
renderStrToBuffer(tui->frame_buffer, range.min % tui->screen_dimensions.width, y, sbuf, tui->screen_dimensions);
}
fn Box defaultModal(TuiState* tui) {
Box modal_outline = {
.x = (tui->screen_dimensions.width - 50) / 2,
.y = (tui->screen_dimensions.height - 15) / 2,
.height = 15,
.width = 50,
};
return modal_outline;
} }
fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count) { fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count) {
@@ -525,6 +568,10 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
sprintf(sbuf,"got winner id: %d", msg.byte); sprintf(sbuf,"got winner id: %d", msg.byte);
addSystemMessage((u8*)sbuf); addSystemMessage((u8*)sbuf);
} break; } break;
case MessageJobAcceptResult: {
state->passenger_tab_state = PassengersTabStateResult;
state->passenger_job_accepted = msg.byte;
} break;
case MessagePayoffResult: { case MessagePayoffResult: {
state->ship_tab_states = ShipTabStateMain; state->ship_tab_states = ShipTabStateMain;
} break; } break;
@@ -562,6 +609,9 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
for (u32 i = 0; i < Commodity_Count; i++) { for (u32 i = 0; i < Commodity_Count; i++) {
state->me.commodities[i] = msg.ship.commodities[i]; state->me.commodities[i] = msg.ship.commodities[i];
} }
for (u32 i = 0; i < MAX_PASSENGER_BERTHS; i++) {
state->me.passengers[i] = msg.ship.passengers[i];
}
} }
} break; } break;
case MessageStarPositions: { case MessageStarPositions: {
@@ -773,9 +823,9 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
} }
renderSystemMessages(tui->frame_buffer, tui->screen_dimensions, box); renderSystemMessages(tui->frame_buffer, tui->screen_dimensions, box);
} break; } break;
case TabChat: { /*case TabChat: {
renderStrToBuffer(tui->frame_buffer, box.x+2, box.y+1, "You haven't heard anything interesting lately...", screen_dimensions); renderStrToBuffer(tui->frame_buffer, box.x+2, box.y+1, "You haven't heard anything interesting lately...", screen_dimensions);
} break; } break;*/
case TabMap: { case TabMap: {
if (input_buffer[0] == 'q' || user_pressed_esc) { if (input_buffer[0] == 'q' || user_pressed_esc) {
should_quit = true; should_quit = true;
@@ -879,7 +929,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
Pos2 dest_pos = {dest.x, dest.y}; Pos2 dest_pos = {dest.x, dest.y};
Pos2 curr_pos = {curr.x, curr.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);
if (have_enough_fuel) { if (have_enough_fuel) {
sprintf( sprintf(
@@ -996,18 +1046,19 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
} }
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions); renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions);
u32 used_berths = shipUsedPassengerBerths(state->me);
u32 passenger_count = shipTotalPassengers(state->me);
MemoryZero(sbuf, SBUFLEN);
sprintf(sbuf, "Passengers: %d filling %d / %d berths", passenger_count, used_berths, state->me.passenger_berths);
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions);
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", COMMODITIES[i].name, 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+3+i, sbuf, screen_dimensions);
} }
Box modal_outline = { Box modal_outline = defaultModal(tui);
.x = (tui->screen_dimensions.width - 50) / 2,
.y = (tui->screen_dimensions.height - 15) / 2,
.height = 15,
.width = 50,
};
u32 y_off = modal_outline.y+2; u32 y_off = modal_outline.y+2;
if (state->ship_tab_states == ShipTabStatePayoffModal) { if (state->ship_tab_states == ShipTabStatePayoffModal) {
if (input_buffer[0] == 'q' || user_pressed_esc) { if (input_buffer[0] == 'q' || user_pressed_esc) {
@@ -1143,12 +1194,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
} }
// calculate and maybe draw the modal outline // calculate and maybe draw the modal outline
Box modal_outline = { Box modal_outline = defaultModal(tui);
.x = (tui->screen_dimensions.width - 50) / 2,
.y = (tui->screen_dimensions.height - 15) / 2,
.height = 15,
.width = 50,
};
if (state->market_tab_state != MarketTabStateTable && state->market_tab_state != MarketTabStateComparisonTable) { if (state->market_tab_state != MarketTabStateTable && state->market_tab_state != MarketTabStateComparisonTable) {
// draw the modal outline // draw the modal outline
clearBox(tui, modal_outline); clearBox(tui, modal_outline);
@@ -1288,6 +1334,14 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
} break; } break;
case TabPassengers: { case TabPassengers: {
if (input_buffer[0] == 'q' || user_pressed_esc) {
if (state->passenger_tab_state == PassengersTabStateTable) {
should_quit = true;
} else {
state->passenger_tab_state = PassengersTabStateTable;
}
}
u32 line = box.y + 1; u32 line = box.y + 1;
// draw a nifty status-line // draw a nifty status-line
@@ -1301,6 +1355,7 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
if (curr.offers[i].people > 0) { if (curr.offers[i].people > 0) {
offer_count += 1; offer_count += 1;
rows[i].destination = state->map[curr.offers[i].goal_system_idx].name; rows[i].destination = state->map[curr.offers[i].goal_system_idx].name;
rows[i].goal_system_idx = curr.offers[i].goal_system_idx;
rows[i].people = curr.offers[i].people; rows[i].people = curr.offers[i].people;
rows[i].time_limit = curr.offers[i].time_limit; rows[i].time_limit = curr.offers[i].time_limit;
rows[i].offer = curr.offers[i].offer; rows[i].offer = curr.offers[i].offer;
@@ -1319,6 +1374,111 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
rows, rows,
sizeof(DisplayPassengerJobOffer) sizeof(DisplayPassengerJobOffer)
); );
// calculate and maybe draw the modal outline
Box modal_outline = defaultModal(tui);
if (state->passenger_tab_state != PassengersTabStateTable) {
// draw the modal outline
clearBox(tui, modal_outline);
drawAnsiBox(tui->frame_buffer, modal_outline, tui->screen_dimensions, false);
}
// common/shared variables
u32 y_off = modal_outline.y+2;
switch (state->passenger_tab_state) {
case PassengersTabStateBookModal: {
if (user_pressed_right) {
state->modal_choice.selected_index = 1;
} else if (user_pressed_left) {
state->modal_choice.selected_index = 0;
} else if (user_pressed_backspace || user_pressed_esc) {
state->passenger_tab_state = PassengersTabStateTable;
}
// draw the interior of the modal
DisplayPassengerJobOffer current_row = rows[state->row.selected_index];
MemoryZero(sbuf, SBUFLEN);
sprintf(sbuf, "%d passengers to %s", current_row.people, current_row.destination);
renderStrToBuffer(tui->frame_buffer, modal_outline.x+(modal_outline.width/2)-strlen(sbuf), y_off++, sbuf, screen_dimensions);
renderStrToBuffer(tui->frame_buffer, modal_outline.x+((modal_outline.width-8)/2), y_off++, "offering", screen_dimensions);
MemoryZero(sbuf, SBUFLEN);
sprintf(sbuf, "%d credits", current_row.offer);
renderStrToBuffer(tui->frame_buffer, modal_outline.x+((modal_outline.width-strlen(sbuf))/2), y_off++, sbuf, screen_dimensions);
renderStrToBuffer(tui->frame_buffer, modal_outline.x+((modal_outline.width-18)/2), y_off++, "if accomplished in", screen_dimensions);
MemoryZero(sbuf, SBUFLEN);
sprintf(sbuf, "%d turns", current_row.time_limit);
renderStrToBuffer(tui->frame_buffer, modal_outline.x+((modal_outline.width-strlen(sbuf))/2), y_off++, sbuf, screen_dimensions);
y_off++;
bool accepting = state->modal_choice.selected_index == 1;
u32 reject_x = modal_outline.x+5;
u32 accept_x = modal_outline.x+modal_outline.width-10;
renderStrToBuffer(tui->frame_buffer, reject_x, y_off, "Reject", screen_dimensions);
renderStrToBuffer(tui->frame_buffer, accept_x, y_off, "ACCEPT", screen_dimensions);
u32 pos = XYToPos(reject_x, y_off, tui->screen_dimensions.width);
if (accepting) {
pos = XYToPos(accept_x, y_off, tui->screen_dimensions.width);
}
for (u32 i = 0; i < 6; i++) {
tui->frame_buffer[pos+i].background = ANSI_WHITE;
tui->frame_buffer[pos+i].foreground = ANSI_BLACK;
}
tui->cursor.x = (accepting ? accept_x : reject_x);
tui->cursor.y = y_off++;
if (user_pressed_enter) {
if (accepting) {
// send the "job accept" message to server
// get back new "status" of things
u32 msg_idx = 0;
UDPMessage msg = {0};
msg.address = udp->server_address;
msg.bytes[msg_idx++] = CommandAcceptPassengerJob;
msg.bytes[msg_idx++] = current_row.goal_system_idx;
msg.bytes[msg_idx++] = current_row.people;
msg.bytes[msg_idx++] = current_row.time_limit;
msg_idx += writeU32ToBufferLE(msg.bytes + msg_idx, current_row.offer);
msg.bytes_len = msg_idx;
outgoingMessageQueuePush(network_send_queue, &msg);
state->passenger_tab_state = PassengersTabStateLoading;
} else {
state->passenger_tab_state = PassengersTabStateTable;
}
}
} break;
case PassengersTabStateLoading: {
if (user_pressed_backspace || user_pressed_esc) {
state->passenger_tab_state = PassengersTabStateTable;
}
renderStrToBuffer(tui->frame_buffer, modal_outline.x+4, modal_outline.y+3, "Loading...", screen_dimensions);
} break;
case PassengersTabStateResult: {
if (user_pressed_backspace || user_pressed_esc || user_pressed_enter) {
state->passenger_tab_state = PassengersTabStateTable;
}
if (state->passenger_job_accepted) {
renderStrToBuffer(tui->frame_buffer, modal_outline.x+4, modal_outline.y+3, "Job Accepted!", screen_dimensions);
} else {
renderStrToBuffer(tui->frame_buffer, modal_outline.x+4, modal_outline.y+3, "Job no longer available...", screen_dimensions);
renderStrToBuffer(tui->frame_buffer, modal_outline.x+4, modal_outline.y+4, "or you ran out of passenger berths", screen_dimensions);
}
} break;
case PassengersTabStateTable: {
moveRowUpDown(user_pressed_up, user_pressed_down);
if (user_pressed_enter) {
state->passenger_tab_state = PassengersTabStateBookModal;
state->modal_choice.len = 2;
state->modal_choice.selected_index = 0;
}
} break;
case PassengersTabStates_Count: assert(false && "passenger_tab_state is corrupted"); break;
}
} break; } break;
case Tab_Count: {} break; case Tab_Count: {} break;
} }
+41 -3
View File
@@ -305,10 +305,27 @@ fn UDPMessage makeMessagePlayerDetails(PlayerShip ship) {
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]);
} }
for (u32 i = 0; i < MAX_PASSENGER_BERTHS; i++) {
outgoing_message.bytes[msg_i++] = ship.passengers[i].goal_system_idx;
outgoing_message.bytes[msg_i++] = ship.passengers[i].people;
outgoing_message.bytes[msg_i++] = ship.passengers[i].turns_remaining;
msg_i += writeU32ToBufferLE(outgoing_message.bytes + msg_i, ship.passengers[i].reward);
}
outgoing_message.bytes_len = msg_i; outgoing_message.bytes_len = msg_i;
return outgoing_message; return outgoing_message;
} }
fn void sendMessageJobAcceptResult(SocketAddress addr, bool result) {
UDPMessage outgoing_message = {0};
outgoing_message.address = addr;
u32 msg_i = 0;
outgoing_message.bytes[msg_i++] = (u8)MessageJobAcceptResult;
outgoing_message.bytes[msg_i++] = result;
outgoing_message.bytes_len = msg_i;
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
printf("%s sent\n", MESSAGE_STRINGS[outgoing_message.bytes[0]]);
}
fn void sendMessagePayoffResult(SocketAddress addr) { fn void sendMessagePayoffResult(SocketAddress addr) {
UDPMessage outgoing_message = {0}; UDPMessage outgoing_message = {0};
outgoing_message.address = addr; outgoing_message.address = addr;
@@ -463,14 +480,14 @@ fn void* sendNetworkUpdates(void* sock) {
} }
UDPMessage sys_udp_msg = { 0 }; UDPMessage sys_udp_msg = { 0 };
sys_udp_msg = makeMessageSystemCommodities(&state.map[send_loop % STAR_SYSTEM_COUNT]); sys_udp_msg = makeMessageSystemCommodities(&state.map[send_loop/2 % STAR_SYSTEM_COUNT]);
u8List sys_msg = { u8List sys_msg = {
.capacity = UDP_MAX_MESSAGE_LEN, .capacity = UDP_MAX_MESSAGE_LEN,
.items = sys_udp_msg.bytes, .items = sys_udp_msg.bytes,
.length = sys_udp_msg.bytes_len, .length = sys_udp_msg.bytes_len,
}; };
UDPMessage sys_pass_udp_msg = { 0 }; UDPMessage sys_pass_udp_msg = { 0 };
sys_pass_udp_msg = makeMessageSystemPassengers(&state.map[send_loop % STAR_SYSTEM_COUNT]); sys_pass_udp_msg = makeMessageSystemPassengers(&state.map[send_loop/2 % STAR_SYSTEM_COUNT]);
u8List sys_pass_msg = { u8List sys_pass_msg = {
.capacity = UDP_MAX_MESSAGE_LEN, .capacity = UDP_MAX_MESSAGE_LEN,
.items = sys_pass_udp_msg.bytes, .items = sys_pass_udp_msg.bytes,
@@ -485,16 +502,19 @@ fn void* sendNetworkUpdates(void* sock) {
continue; continue;
} }
// every "send-frame" we send each connnected client the current prices for a different system if (send_loop % 2 == 0) {
// every other "send-frame" we send each connnected client the current prices for a different system
// so that the prices mostly stay up to date pretty quickly without having to track changes // so that the prices mostly stay up to date pretty quickly without having to track changes
sendUDPu8List(socket, &client.address, &sys_msg); sendUDPu8List(socket, &client.address, &sys_msg);
// and the passenger offers // and the passenger offers
sendUDPu8List(socket, &client.address, &sys_pass_msg); sendUDPu8List(socket, &client.address, &sys_pass_msg);
}
// update all the changed systems // update all the changed systems
UDPMessage msg_data; UDPMessage msg_data;
for (u32 ii = 0; ii < STAR_SYSTEM_COUNT; ii++) { for (u32 ii = 0; ii < STAR_SYSTEM_COUNT; ii++) {
if (state.map[ii].changed == true) { if (state.map[ii].changed == true) {
// send commodities
msg_data = makeMessageSystemCommodities(&state.map[ii]); msg_data = makeMessageSystemCommodities(&state.map[ii]);
u8List msg = { u8List msg = {
.capacity = UDP_MAX_MESSAGE_LEN, .capacity = UDP_MAX_MESSAGE_LEN,
@@ -502,6 +522,14 @@ fn void* sendNetworkUpdates(void* sock) {
.length = msg_data.bytes_len, .length = msg_data.bytes_len,
}; };
sendUDPu8List(socket, &client.address, &msg); sendUDPu8List(socket, &client.address, &msg);
// send passenger jobs
printf("sending passenger jobs for %s\n", STAR_NAMES[ii]);
msg_data = makeMessageSystemPassengers(&state.map[ii]);
msg.capacity = UDP_MAX_MESSAGE_LEN;
msg.items = msg_data.bytes;
msg.length = msg_data.bytes_len;
sendUDPu8List(socket, &client.address, &msg);
} }
} }
// update all the changed accounts // update all the changed accounts
@@ -596,6 +624,7 @@ fn void* gameLoop(void* params) {
}; };
// find the matching job, and IF the ship has room, // find the matching job, and IF the ship has room,
// "accept" it by clearing it from the system list and adding it to the ship // "accept" it by clearing it from the system list and adding it to the ship
bool succeeded = false;
for (u32 i = 0; i < MAX_PASSENGER_JOB_OFFERS; i++) { for (u32 i = 0; i < MAX_PASSENGER_JOB_OFFERS; i++) {
if (passengerJobEq(player_sys->offers[i], pjo)) { if (passengerJobEq(player_sys->offers[i], pjo)) {
if (shipAvailablePassengerBerths(account->ship) > 0) { if (shipAvailablePassengerBerths(account->ship) > 0) {
@@ -605,7 +634,12 @@ fn void* gameLoop(void* params) {
account->ship.passengers[ii].goal_system_idx = pjo.goal_system_idx; account->ship.passengers[ii].goal_system_idx = pjo.goal_system_idx;
account->ship.passengers[ii].turns_remaining = pjo.time_limit; account->ship.passengers[ii].turns_remaining = pjo.time_limit;
account->ship.passengers[ii].reward = pjo.offer; account->ship.passengers[ii].reward = pjo.offer;
account->changed = true;
MemoryZero(&player_sys->offers[i], sizeof(PassengerJobOffer)); MemoryZero(&player_sys->offers[i], sizeof(PassengerJobOffer));
player_sys->changed = true;
succeeded = true;
sendMessageJobAcceptResult(sender, succeeded);
// end both for loops "break break;"
ii = MAX_PASSENGER_BERTHS; ii = MAX_PASSENGER_BERTHS;
i = MAX_PASSENGER_JOB_OFFERS; i = MAX_PASSENGER_JOB_OFFERS;
break; break;
@@ -614,6 +648,9 @@ fn void* gameLoop(void* params) {
} }
} }
} }
if (!succeeded) {
sendMessageJobAcceptResult(sender, succeeded);
}
} break; } break;
case CommandPayMortgage: { case CommandPayMortgage: {
Account* account = &state.accounts[client->account_id]; Account* account = &state.accounts[client->account_id];
@@ -879,6 +916,7 @@ fn void* gameLoop(void* params) {
// 2. tick non-user entities // 2. tick non-user entities
if (state.all_accounts_ready) { if (state.all_accounts_ready) {
printf("NEW TURN: ticking all_accounts_ready\n");
// tick all the star systems // tick all the star systems
StarSystem* sys = NULL; StarSystem* sys = NULL;
Range1u64 sys_range = LaneRange(STAR_SYSTEM_COUNT); Range1u64 sys_range = LaneRange(STAR_SYSTEM_COUNT);
+20 -4
View File
@@ -277,8 +277,8 @@ global FieldDescriptor MARKET_COMMODITY_FIELDS[Commodity_Count] = {
}; };
typedef struct Passenger { typedef struct Passenger {
u8 people;
u8 goal_system_idx; u8 goal_system_idx;
u8 people;
u8 turns_remaining; u8 turns_remaining;
u32 reward; u32 reward;
} Passenger; } Passenger;
@@ -294,10 +294,10 @@ typedef struct DisplayPassengerJobOffer {
str destination; str destination;
u8 people; u8 people;
u8 time_limit; u8 time_limit;
u8 goal_system_idx;
u32 offer; u32 offer;
} DisplayPassengerJobOffer; } DisplayPassengerJobOffer;
global FieldDescriptor PASSENGER_JOB_OFFER_FIELDS[] = { global FieldDescriptor PASSENGER_JOB_OFFER_FIELDS[] = {
{ "Destination", FieldTypeString, offsetof(DisplayPassengerJobOffer, destination), 44 }, { "Destination", FieldTypeString, offsetof(DisplayPassengerJobOffer, destination), 44 },
{ "People", FieldTypeU8, offsetof(DisplayPassengerJobOffer, people), 6 }, { "People", FieldTypeU8, offsetof(DisplayPassengerJobOffer, people), 6 },
@@ -445,6 +445,7 @@ typedef enum Message {
MessageGameOver, MessageGameOver,
MessagePayoffResult, MessagePayoffResult,
MessageSystemPassengers, MessageSystemPassengers,
MessageJobAcceptResult,
Message_Count, Message_Count,
} Message; } Message;
@@ -461,6 +462,7 @@ static const char* MESSAGE_STRINGS[] = {
"GameOver", "GameOver",
"PayoffResult", "PayoffResult",
"SystemPassengers", "SystemPassengers",
"JobAcceptResult",
}; };
///// shared helper functions ///// shared helper functions
@@ -517,7 +519,17 @@ fn bool passengerJobEq(PassengerJobOffer a, PassengerJobOffer b) {
a.time_limit == b.time_limit; a.time_limit == b.time_limit;
} }
fn bool shipAvailablePassengerBerths(PlayerShip ship) { fn u32 shipTotalPassengers(PlayerShip ship) {
u32 count = 0;
for (u32 i = 0; i < MAX_PASSENGER_BERTHS; i++) {
if (ship.passengers[i].people > 0) {
count += ship.passengers[i].people;
}
}
return count;
}
fn u32 shipUsedPassengerBerths(PlayerShip ship) {
u32 used = 0; u32 used = 0;
for (u32 i = 0; i < MAX_PASSENGER_BERTHS; i++) { for (u32 i = 0; i < MAX_PASSENGER_BERTHS; i++) {
if (ship.passengers[i].people > 0) { if (ship.passengers[i].people > 0) {
@@ -525,7 +537,11 @@ fn bool shipAvailablePassengerBerths(PlayerShip ship) {
} }
} }
assert(used <= ship.passenger_berths); assert(used <= ship.passenger_berths);
return ship.passenger_berths - used; return used;
}
fn u32 shipAvailablePassengerBerths(PlayerShip ship) {
return (u32)ship.passenger_berths - shipUsedPassengerBerths(ship);
} }
#endif //GAMESHARED_H #endif //GAMESHARED_H