diff --git a/buildsettings.h b/buildsettings.h index 8aa040c..a87cdcb 100644 --- a/buildsettings.h +++ b/buildsettings.h @@ -19,7 +19,7 @@ // #define DEBUG_WORLD // #define UNLOCK_ALL #define INFINITE_RESOURCES -#define FAT_THRUSTERS +// #define FAT_THRUSTERS // #define NO_GRAVITY // #define NO_SUNS diff --git a/gamestate.c b/gamestate.c index fcf7799..225b309 100644 --- a/gamestate.c +++ b/gamestate.c @@ -769,9 +769,11 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid) cur = next; } - // @Robust do the momentum stuff properly here so no matter which grid stays as the current grid, + // @BeforePatreon do the momentum stuff properly here so no matter which grid stays as the current grid, // the *SAME RESULT* happens. VERY IMPORTANT for client side prediction to match what the server says. - // Tried to use something consistent on the server and client like current entity index but DID NOT WORK + // Tried to use something consistent on the server and client like current entity index but DID NOT WORK. + // IDEA: just make it so *all* of the boxes are in new grids instead of choosing one to stay the same + // This bug is triggered heavily with high ping by placing a box on a corner, so that it starts out in the grid but this logic is ran. if (sepgrid_i != biggest_separate_grid_index) { cpBodySetVelocity(new_grid->body, cpBodyGetVelocityAtWorldPoint(grid->body, (grid_com(new_grid)))); @@ -853,8 +855,8 @@ void initialize(GameState *gs, void *entity_arena, size_t entity_arena_size) gs->entities = (Entity *)entity_arena; gs->max_entities = (unsigned int)(entity_arena_size / sizeof(Entity)); gs->space = cpSpaceNew(); - cpSpaceSetUserData(gs->space, (cpDataPointer)gs); // needed in the handler - cpCollisionHandler *handler = cpSpaceAddCollisionHandler(gs->space, 0, 0); // @Robust limit collision type to just blocks that can be damaged + cpSpaceSetUserData(gs->space, (cpDataPointer)gs); // needed in the handler + cpCollisionHandler *handler = cpSpaceAddCollisionHandler(gs->space, 0, 0); handler->postSolveFunc = on_damage; gs->server_side_computing = is_server_side; } @@ -1111,7 +1113,6 @@ enum GameVersion VMax, // this minus one will be the version used }; -// @Robust probably get rid of this as separate function, just use SER_VAR SerMaybeFailure ser_V2(SerState *ser, cpVect *var) { SER_VAR(&var->x); @@ -1223,7 +1224,7 @@ SerMaybeFailure ser_player(SerState *ser, Player *p) SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e) { - SER_VAR(&e->no_save_to_disk); // @Robust this is always false when saving to disk? + SER_VAR(&e->no_save_to_disk); SER_VAR(&e->generation); SER_MAYBE_RETURN(ser_f(ser, &e->damage)); @@ -1448,9 +1449,9 @@ SerMaybeFailure ser_server_to_client(SerState *ser, ServerToClient *s) GameState *gs = s->cur_gs; // completely reset and destroy all gamestate data - PROFILE_SCOPE("Destroy old gamestate") + if (!ser->serializing) { - if (!ser->serializing) + PROFILE_SCOPE("Destroy old gamestate") { // avoid a memset here very expensive. que rico! destroy(gs); @@ -1474,7 +1475,6 @@ SerMaybeFailure ser_server_to_client(SerState *ser, ServerToClient *s) if (!ser->save_or_load_from_disk) // don't save player info to disk, this is filled on connection/disconnection { - // @Robust save player data with their ID or something somehow. Like local backup of their account for (size_t i = 0; i < MAX_PLAYERS; i++) { if (get_entity(gs, gs->players[i].entity) != NULL && is_cloaked(gs, get_entity(gs, gs->players[i].entity), ser->for_player)) @@ -1542,7 +1542,7 @@ SerMaybeFailure ser_server_to_client(SerState *ser, ServerToClient *s) EntityID cur_id = get_id(gs, cur_box); SER_ASSERT(cur_id.index < gs->max_entities); SER_VAR(&entities_done); - size_t the_index = (size_t)cur_id.index; // super critical. Type of &i is size_t. @Robust add debug info in serialization for what size the expected type is, maybe string nameof the type + size_t the_index = (size_t)cur_id.index; // super critical. Type of &i is size_t. @BeforePatreon add debug info in serialization for what size the expected type is, maybe string nameof the type SER_VAR_NAME(&the_index, "&i"); SER_MAYBE_RETURN(ser_entity(ser, gs, cur_box)); } @@ -1627,20 +1627,16 @@ bool server_to_client_serialize(struct ServerToClient *msg, unsigned char *bytes .for_player = for_this_player, .max_entity_index = msg->cur_gs->cur_next_entity, .version = VMax - 1, + .save_or_load_from_disk = to_disk, }; - if (for_this_player == NULL) // @Robust jank - { - ser.save_or_load_from_disk = true; - } - ser.write_varnames = to_disk; #ifdef WRITE_VARNAMES ser.write_varnames = true; #endif SerMaybeFailure result = ser_server_to_client(&ser, msg); - *out_len = ser.cursor + 1; // @Robust not sure why I need to add one to cursor, ser.cursor should be the length.. + *out_len = ser.cursor + 1; // not sure why I need to add one to cursor, ser.cursor should be the length. It seems to work without the +1 but I have no way to ensure that it works completely when removing the +1... if (result.failed) { Log("Failed to serialize on line %d because of %s\n", result.line, result.expression); @@ -1842,7 +1838,6 @@ Entity *closest_box_to_point_in_radius(struct GameState *gs, cpVect point, doubl if (closest_to_point_in_radius_result != NULL) { - // @Robust query here for only boxes that are part of ships, could get nasty... return cp_shape_entity(closest_to_point_in_radius_result); } @@ -1962,6 +1957,11 @@ cpVect potentially_snap_hand_pos(GameState *gs, cpVect world_hand_pos) cpVect get_world_hand_pos(GameState *gs, InputFrame *input, Entity *player) { + if(cpvlength(input->hand_pos) > MAX_HAND_REACH) + { + // no cheating with long hand! + input->hand_pos = cpvmult(cpvnormalize(input->hand_pos), MAX_HAND_REACH); + } return potentially_snap_hand_pos(gs, cpvadd(entity_pos(player), input->hand_pos)); } @@ -2389,7 +2389,7 @@ void process(struct GameState *gs, double dt) flight_assert(potential_seat->is_box); flight_assert(potential_seat->box_type == BoxMerge); } - if (potential_seat->box_type == BoxCockpit || potential_seat->box_type == BoxMedbay) // @Robust check by feature flag instead of box type + if (potential_seat->box_type == BoxCockpit || potential_seat->box_type == BoxMedbay) { // don't let players get inside of cockpits that somebody else is already inside of if (get_entity(gs, potential_seat->player_who_is_inside_of_me) == NULL) @@ -2500,7 +2500,6 @@ void process(struct GameState *gs, double dt) cpPointQueryInfo info = {0}; cpVect world_build = world_hand_pos; - // @Robust sanitize this input so player can't build on any grid in the world Entity *target_grid = grid_to_build_on(gs, world_hand_pos); cpShape *maybe_box_to_destroy = cpSpacePointQueryNearest(gs->space, (world_build), 0.01, cpShapeFilterNew(CP_NO_GROUP, CP_ALL_CATEGORIES, BOXES), &info); if (maybe_box_to_destroy != NULL) diff --git a/main.c b/main.c index 53ec814..c913198 100644 --- a/main.c +++ b/main.c @@ -76,10 +76,10 @@ static cpVect camera_pos = {0}; // it being a global variable keeps camera at sa // position after player death static double player_scaling = 1.0; -static bool mouse_frozen = false; // @BeforeShip make this debug only thing +static bool mouse_frozen = false; // @BeforePatreon make this debug only thing static double funval = 0.0; // easy to play with value controlled by left mouse button when held -// down @BeforeShip remove on release builds +// down @BeforePatreon remove on release builds static Queue input_queue = {0}; char input_queue_data[QUEUE_SIZE_FOR_ELEMENTS(sizeof(InputFrame), LOCAL_INPUT_QUEUE_MAX)] = {0}; static ENetHost *client; @@ -1741,7 +1741,7 @@ static void frame(void) ENetPacket *packet = enet_packet_create((void *)compressed, compressed_len, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT); - enet_peer_send(peer, 0, packet); // @Robust error check this + enet_peer_send(peer, 0, packet); // @BeforePatreon error check this last_sent_input_time = stm_now(); } else diff --git a/server.c b/server.c index ca17af2..582f023 100644 --- a/server.c +++ b/server.c @@ -298,7 +298,7 @@ void server(void *info_raw) } total_time += (float)stm_sec(stm_diff(stm_now(), last_processed_time)); last_processed_time = stm_now(); - // @Robost @BeforeShip if can't process quick enough will be stuck being lagged behind, think of a solution for this... + // @Robost @BeforePatreon if can't process quick enough will be stuck being lagged behind, think of a solution for this... const double max_time = 5.0 * TIMESTEP; if (total_time > max_time) { diff --git a/types.h b/types.h index 3bb602b..c5a3158 100644 --- a/types.h +++ b/types.h @@ -102,8 +102,7 @@ #include "cpVect.h" // offers vector functions and types for the structs #include "miniaudio.h" // @Robust BAD. using miniaudio mutex construct for server thread synchronization. AWFUL! -// @Robust remove this include somehow, needed for sqrt and cos -#include +#include // sqrt and cos vector functions #include // tick is unsigned integer #include // logging on errors for functions @@ -195,6 +194,11 @@ typedef struct EntityID unsigned int index; // index into the entity arena } EntityID; +static inline bool entityids_same(EntityID a, EntityID b) +{ + return (a.generation == b.generation) && (a.index == b.index); +} + // when updated, must update serialization, comparison in main.c, and the server // on input received processing function typedef struct InputFrame @@ -210,7 +214,6 @@ typedef struct InputFrame bool seat_action; cpVect hand_pos; // local to player transationally but not rotationally - // @BeforeShip bounds check on the hand_pos so that players can't reach across the entire map bool dobuild; enum BoxType build_type; @@ -307,7 +310,7 @@ typedef struct Entity // scanner only stuff! EntityID currently_scanning; double currently_scanning_progress; // when 1.0, scans it! - BOX_UNLOCKS_TYPE blueprints_learned; // @Robust make this same type as blueprints + BOX_UNLOCKS_TYPE blueprints_learned; double scanner_head_rotate_speed; // not serialized, cosmetic double scanner_head_rotate; cpVect platonic_nearest_direction; // normalized @@ -339,10 +342,8 @@ typedef struct GameState { cpSpace *space; - // @Robust for the integer tick, also store a double for how much time has been processed. - // Like a whole timestep then a double for subtimestep uint64_t tick; - double subframe_time; + double subframe_time; // @Robust remove this, I don't think it's used anymore cpVect goldpos;