basic auction process works, but I still need to restrict the purchase/sale of these commodities on the Market tab
This commit is contained in:
+75
-18
@@ -65,6 +65,9 @@ typedef enum PassengersTabStates {
|
|||||||
typedef enum AuctionTabStates {
|
typedef enum AuctionTabStates {
|
||||||
AuctionTabStateMain,
|
AuctionTabStateMain,
|
||||||
AuctionTabStateLoading,
|
AuctionTabStateLoading,
|
||||||
|
AuctionTabStateNotEnoughMoney,
|
||||||
|
AuctionTabStateNotEnoughCargoSpace,
|
||||||
|
AuctionTabStateAlreadyFinished,
|
||||||
AuctionTabStateResult,
|
AuctionTabStateResult,
|
||||||
AuctionTabStates_Count,
|
AuctionTabStates_Count,
|
||||||
} AuctionTabStates;
|
} AuctionTabStates;
|
||||||
@@ -348,6 +351,7 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
case MessageNewAccountCreated:
|
case MessageNewAccountCreated:
|
||||||
case MessageNotAlive:
|
case MessageNotAlive:
|
||||||
case MessageBadPw: {/*nothing to parse but the type*/} break;
|
case MessageBadPw: {/*nothing to parse but the type*/} break;
|
||||||
|
case MessageAuctionBidResult: // same as GameOver
|
||||||
case MessageGameOver: {
|
case MessageGameOver: {
|
||||||
parsed.byte = message[msg_pos++];
|
parsed.byte = message[msg_pos++];
|
||||||
} break;
|
} break;
|
||||||
@@ -565,6 +569,26 @@ 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 MessageAuctionBidResult: {
|
||||||
|
AuctionBidResult result = msg.byte;
|
||||||
|
switch (result) {
|
||||||
|
case AuctionBidResultNotEnoughMoney:
|
||||||
|
state->auction_tab_state = AuctionTabStateNotEnoughMoney;
|
||||||
|
break;
|
||||||
|
case AuctionBidResultNotEnoughCargoSpace:
|
||||||
|
state->auction_tab_state = AuctionTabStateNotEnoughCargoSpace;
|
||||||
|
break;
|
||||||
|
case AuctionBidResultPurchased:
|
||||||
|
state->auction_tab_state = AuctionTabStateResult;
|
||||||
|
break;
|
||||||
|
case AuctionBidResultAuctionAlreadyFinished:
|
||||||
|
state->auction_tab_state = AuctionTabStateAlreadyFinished;
|
||||||
|
break;
|
||||||
|
case AuctionBidResult_Count:
|
||||||
|
assert(false && "unhandled message result");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case MessageNotAlive: {
|
case MessageNotAlive: {
|
||||||
// auto-re-login
|
// auto-re-login
|
||||||
if (state->me.base_cost > 0) {
|
if (state->me.base_cost > 0) {
|
||||||
@@ -1272,10 +1296,20 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
} break;
|
} break;
|
||||||
case TabAuction: {
|
case TabAuction: {
|
||||||
u32 yoff = box.y+1;
|
u32 yoff = box.y+1;
|
||||||
|
drawStatusLine(tui, sbuf, &state->me, box.x+2, yoff);
|
||||||
|
yoff++;
|
||||||
|
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+((box.width - 13)/2), yoff++, "Auction House", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, box.x+((box.width - 13)/2), yoff++, "Auction House", screen_dimensions);
|
||||||
yoff++;
|
yoff++;
|
||||||
|
|
||||||
if (curr.auction.finished_at > curr.auction.started_at) {
|
if (curr.auction.finished_at > curr.auction.started_at) {
|
||||||
|
if (state->auction_tab_state == AuctionTabStateResult) {
|
||||||
|
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, "Your bid was accepted", screen_dimensions);
|
||||||
|
yoff++;
|
||||||
|
} else if (state->auction_tab_state == AuctionTabStateAlreadyFinished) {
|
||||||
|
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, "Your bid was too late..", screen_dimensions);
|
||||||
|
yoff++;
|
||||||
|
}
|
||||||
MemoryZero(sbuf, SBUFLEN);
|
MemoryZero(sbuf, SBUFLEN);
|
||||||
sprintf(sbuf, "Sold! %d containers of %s were sold for $%d", curr.auction.qty, COMMODITY_STRINGS[curr.auction.type], curr.auction.price);
|
sprintf(sbuf, "Sold! %d containers of %s were sold for $%d", curr.auction.qty, COMMODITY_STRINGS[curr.auction.type], curr.auction.price);
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, box.x+2, yoff++, sbuf, screen_dimensions);
|
||||||
@@ -1294,25 +1328,48 @@ 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);
|
||||||
yoff++;
|
yoff++;
|
||||||
|
|
||||||
const char* label = "ACCEPT OFFER [ENTER]";
|
bool player_has_money_for_purchase = state->me.credits > curr.auction.price;
|
||||||
Range1u32 range = {
|
bool player_has_cargo_space_for_purchase = (state->me.vacuum_cargo_slots - usedVacuumCargoSlots(state->me)) > curr.auction.qty;
|
||||||
.min = XYToPos(box.x+6, yoff, screen_dimensions.width),
|
if (player_has_money_for_purchase && player_has_cargo_space_for_purchase) {
|
||||||
.max = XYToPos(box.x+6+strlen(label), yoff, screen_dimensions.width),
|
const char* label = "ACCEPT OFFER [ENTER]";
|
||||||
};
|
Range1u32 range = {
|
||||||
tui->cursor.x = box.x+6;
|
.min = XYToPos(box.x+6, yoff, screen_dimensions.width),
|
||||||
tui->cursor.y = yoff;
|
.max = XYToPos(box.x+6+strlen(label), yoff, screen_dimensions.width),
|
||||||
colorizeRange(tui, range, ANSI_WHITE, ANSI_BLACK);
|
};
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+6, yoff++, label, screen_dimensions);
|
tui->cursor.x = box.x+6;
|
||||||
if (user_pressed_enter) {
|
tui->cursor.y = yoff;
|
||||||
// send the "buy this auction" message to the server
|
colorizeRange(tui, range, ANSI_WHITE, ANSI_BLACK);
|
||||||
u32 msg_idx = 0;
|
renderStrToBuffer(tui->frame_buffer, box.x+6, yoff++, label, screen_dimensions);
|
||||||
UDPMessage msg = {0};
|
if (user_pressed_enter) {
|
||||||
msg.address = udp->server_address;
|
// send the "buy this auction" message to the server
|
||||||
msg.bytes[msg_idx++] = CommandBuyAuction;
|
u32 msg_idx = 0;
|
||||||
msg.bytes_len = msg_idx;
|
UDPMessage msg = {0};
|
||||||
outgoingMessageQueuePush(network_send_queue, &msg);
|
msg.address = udp->server_address;
|
||||||
|
msg.bytes[msg_idx++] = CommandBuyAuction;
|
||||||
|
msg.bytes_len = msg_idx;
|
||||||
|
outgoingMessageQueuePush(network_send_queue, &msg);
|
||||||
|
|
||||||
state->auction_tab_state = AuctionTabStateLoading;
|
state->auction_tab_state = AuctionTabStateLoading;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!player_has_money_for_purchase) {
|
||||||
|
const char* no_money_label = "You do not have enough money";
|
||||||
|
Range1u32 range = {
|
||||||
|
.min = XYToPos(box.x+6, yoff, screen_dimensions.width),
|
||||||
|
.max = XYToPos(box.x+6+strlen(no_money_label), yoff, screen_dimensions.width),
|
||||||
|
};
|
||||||
|
colorizeRange(tui, range, ANSI_DULL_RED, ANSI_WHITE);
|
||||||
|
renderStrToBuffer(tui->frame_buffer, box.x+6, yoff++, no_money_label, screen_dimensions);
|
||||||
|
}
|
||||||
|
if (!player_has_cargo_space_for_purchase) {
|
||||||
|
const char* no_cargo_label = "You do not have enough cargo space";
|
||||||
|
Range1u32 range = {
|
||||||
|
.min = XYToPos(box.x+6, yoff, screen_dimensions.width),
|
||||||
|
.max = XYToPos(box.x+6+strlen(no_cargo_label), yoff, screen_dimensions.width),
|
||||||
|
};
|
||||||
|
colorizeRange(tui, range, ANSI_DULL_RED, ANSI_WHITE);
|
||||||
|
renderStrToBuffer(tui->frame_buffer, box.x+6, yoff++, no_cargo_label, screen_dimensions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (state->auction_tab_state == AuctionTabStateLoading) {
|
} else if (state->auction_tab_state == AuctionTabStateLoading) {
|
||||||
renderStrToBuffer(tui->frame_buffer, box.x+((box.width - 13)/2), yoff++, "Bid submitted...", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, box.x+((box.width - 13)/2), yoff++, "Bid submitted...", screen_dimensions);
|
||||||
|
|||||||
+36
-2
@@ -419,6 +419,16 @@ fn void sendMessagePlayerDetails(PlayerShip ship, SocketAddress addr) {
|
|||||||
addSystemMessage((u8*)"MessagePlayerDetails sent");
|
addSystemMessage((u8*)"MessagePlayerDetails sent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn void sendMessageAuctionBidResult(SocketAddress addr, AuctionBidResult result) {
|
||||||
|
UDPMessage outgoing_message = {.address = addr};
|
||||||
|
u32 msg_i = 0;
|
||||||
|
outgoing_message.bytes[msg_i++] = (u8)MessageAuctionBidResult;
|
||||||
|
outgoing_message.bytes[msg_i++] = result;
|
||||||
|
outgoing_message.bytes_len = msg_i;
|
||||||
|
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
||||||
|
addSystemMessage((u8*)"Message AuctionBidResult sent");
|
||||||
|
}
|
||||||
|
|
||||||
fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 socket) {
|
fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 socket) {
|
||||||
dbg("%d: %s from %s:%d\n", len, command_type_strings[message[0]], inet_ntoa(sender.sin_addr), sender.sin_port);
|
dbg("%d: %s from %s:%d\n", len, command_type_strings[message[0]], inet_ntoa(sender.sin_addr), sender.sin_port);
|
||||||
char sbuf[SBUFLEN] = {0};
|
char sbuf[SBUFLEN] = {0};
|
||||||
@@ -435,6 +445,7 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
.capacity = 0,
|
.capacity = 0,
|
||||||
};
|
};
|
||||||
switch (parsed.type) {
|
switch (parsed.type) {
|
||||||
|
case CommandBuyAuction: break; // nothing to parse but the type
|
||||||
case CommandLogin: {
|
case CommandLogin: {
|
||||||
// parse the login command
|
// parse the login command
|
||||||
parsed.alt_port = ~readU16FromBufferLE(message + msg_idx);
|
parsed.alt_port = ~readU16FromBufferLE(message + msg_idx);
|
||||||
@@ -690,6 +701,29 @@ 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 CommandBuyAuction: {
|
||||||
|
if (client_handle == 0) break;
|
||||||
|
Account* account = &state.accounts[client->account_id];
|
||||||
|
StarSystem* player_sys = &state.map[account->ship.system_idx];
|
||||||
|
bool is_auction_still_running = player_sys->auction.finished_at == 0;
|
||||||
|
if (is_auction_still_running) {
|
||||||
|
bool player_has_money_for_purchase = account->ship.credits >= player_sys->auction.price;
|
||||||
|
bool player_has_cargo_space_for_purchase = (account->ship.vacuum_cargo_slots - usedVacuumCargoSlots(account->ship)) >= player_sys->auction.qty;
|
||||||
|
if (player_has_cargo_space_for_purchase && player_has_money_for_purchase) {
|
||||||
|
player_sys->auction.finished_at = state.frame;
|
||||||
|
account->ship.credits -= player_sys->auction.price;
|
||||||
|
account->ship.commodities[player_sys->auction.type] += player_sys->auction.qty;
|
||||||
|
sendMessageAuctionBidResult(sender, AuctionBidResultPurchased);
|
||||||
|
sendMessagePlayerDetails(account->ship, sender);
|
||||||
|
} else if (!player_has_money_for_purchase) {
|
||||||
|
sendMessageAuctionBidResult(sender, AuctionBidResultNotEnoughMoney);
|
||||||
|
} else {
|
||||||
|
sendMessageAuctionBidResult(sender, AuctionBidResultNotEnoughCargoSpace);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendMessageAuctionBidResult(sender, AuctionBidResultAuctionAlreadyFinished);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case CommandAcceptPassengerJob: {
|
case CommandAcceptPassengerJob: {
|
||||||
if (client_handle == 0) break;
|
if (client_handle == 0) break;
|
||||||
// move the offer out of the system and INTO the PlayerShip
|
// move the offer out of the system and INTO the PlayerShip
|
||||||
@@ -937,7 +971,7 @@ fn void* gameLoop(void* params) {
|
|||||||
.base_cost = template.base_cost,
|
.base_cost = template.base_cost,
|
||||||
.remaining_mortgage = template.base_cost - STARTING_DOWN_PAYMENT,
|
.remaining_mortgage = template.base_cost - STARTING_DOWN_PAYMENT,
|
||||||
.interest_rate = calcInterestRate(template.base_cost, STARTING_DOWN_PAYMENT),
|
.interest_rate = calcInterestRate(template.base_cost, STARTING_DOWN_PAYMENT),
|
||||||
.credits = 2000.0,
|
.credits = 20000.0,
|
||||||
.cu_m_fuel = template.cu_m_fuel,
|
.cu_m_fuel = template.cu_m_fuel,
|
||||||
.cu_m_o2 = template.cu_m_o2,
|
.cu_m_o2 = template.cu_m_o2,
|
||||||
.id = account->id,
|
.id = account->id,
|
||||||
@@ -1039,7 +1073,7 @@ fn void* gameLoop(void* params) {
|
|||||||
f32 t_sec = ((f32)state.frame - (f32)grace_period_ends_at) / (f32)GOAL_GAME_LOOPS_PER_S;
|
f32 t_sec = ((f32)state.frame - (f32)grace_period_ends_at) / (f32)GOAL_GAME_LOOPS_PER_S;
|
||||||
// t is in minutes
|
// t is in minutes
|
||||||
f32 t = t_sec / 60;
|
f32 t = t_sec / 60;
|
||||||
f32 decay = -0.30 * t;
|
f32 decay = -0.50 * t;
|
||||||
f32 floor_price = COMMODITIES[sys->auction.type].price * 0.9;
|
f32 floor_price = COMMODITIES[sys->auction.type].price * 0.9;
|
||||||
sys->auction.price = Max((initial_price * pow(EULERS_E, decay)), floor_price);
|
sys->auction.price = Max((initial_price * pow(EULERS_E, decay)), floor_price);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,6 +342,14 @@ global str STAR_NAMES[STAR_SYSTEM_COUNT] = {
|
|||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum AuctionBidResult {
|
||||||
|
AuctionBidResultPurchased,
|
||||||
|
AuctionBidResultNotEnoughMoney,
|
||||||
|
AuctionBidResultNotEnoughCargoSpace,
|
||||||
|
AuctionBidResultAuctionAlreadyFinished,
|
||||||
|
AuctionBidResult_Count
|
||||||
|
} AuctionBidResult;
|
||||||
|
|
||||||
typedef enum Direction {
|
typedef enum Direction {
|
||||||
DirectionInvalid,
|
DirectionInvalid,
|
||||||
North,
|
North,
|
||||||
@@ -396,6 +404,7 @@ typedef enum Message {
|
|||||||
MessageJobComplete,
|
MessageJobComplete,
|
||||||
MessageNotAlive,
|
MessageNotAlive,
|
||||||
MessageAuctionDetails,
|
MessageAuctionDetails,
|
||||||
|
MessageAuctionBidResult,
|
||||||
Message_Count,
|
Message_Count,
|
||||||
} Message;
|
} Message;
|
||||||
|
|
||||||
@@ -415,6 +424,7 @@ static const char* MESSAGE_STRINGS[] = {
|
|||||||
"JobAcceptResult",
|
"JobAcceptResult",
|
||||||
"NotAlive",
|
"NotAlive",
|
||||||
"AuctionDetails",
|
"AuctionDetails",
|
||||||
|
"AuctionBidResult",
|
||||||
};
|
};
|
||||||
|
|
||||||
///// shared helper functions
|
///// shared helper functions
|
||||||
|
|||||||
Reference in New Issue
Block a user