@ -2,36 +2,48 @@
# include "ipsettings.h"
# define MAX_BOX_TYPES 64
# define MAX_PLAYERS 16
# define MAX_ENTITIES 1024 * 25
# define BOX_SIZE 0.25f
# define PLAYER_SIZE ((V2){.x = BOX_SIZE, .y = BOX_SIZE})
# define PLAYER_MASS 0.5f
# define PLAYER_JETPACK_FORCE 1.5f
# define PLAYER_JETPACK_TORQUE 0.05f
// #define PLAYER_JETPACK_FORCE 20.0f
# define PLAYER_JETPACK_SPICE_PER_SECOND 0.1f
// distance at which things become geostationary and no more solar power!
# define PLAYER_JETPACK_ROTATION_ENERGY_PER_SECOND 0.2f
# define PLAYER_JETPACK_SPICE_PER_SECOND 0.2f
# define SCANNER_ENERGY_USE 0.05f
# define MAX_HAND_REACH 1.0f
# define SCANNER_SCAN_RATE 0.5f
# define SCANNER_RADIUS 1.0f
# define GOLD_COLLECT_RADIUS 0.3f
# define BUILD_BOX_SNAP_DIST_TO_SHIP 0.2f
# define BOX_MASS 1.0f
# define COLLISION_DAMAGE_SCALING 0.15f
# define THRUSTER_FORCE 12.0f
# define THRUSTER_ENERGY_USED_PER_SECOND 0.005f
# define GYROSCOPE_ENERGY_USED_PER_SECOND 0.005f
# define GYROSCOPE_TORQUE 0.5f
# define CLOAKING_ENERGY_USE 0.1f
# define CLOAKING_PANEL_SIZE BOX_SIZE*3.0f
# define VISION_RADIUS 12.0f
# define MAX_SERVER_TO_CLIENT 1024 * 512 // maximum size of serialized gamestate buffer
# define MAX_CLIENT_TO_SERVER 1024 * 10 // maximum size of serialized inputs and mic data
# define SUN_RADIUS 10.0f
# define SUN_NO_MORE_ELECTRICITY_OR_GRAVITY 200.0f
# define INSTANT_DEATH_DISTANCE_FROM_SUN 2000.0f
# define SUN_POS ((V2){50.0f, 0.0f})
# ifdef NO_GRAVITY
# define SUN_GRAVITY_STRENGTH 0. 1 f
# define SUN_GRAVITY_STRENGTH 0. 0 f
# else
# define SUN_GRAVITY_STRENGTH ( 9 .0e2f)
# define SUN_GRAVITY_STRENGTH ( 11 .0e2f)
# endif
# define SOLAR_ENERGY_PER_SECOND 0.0 2 f
# define SOLAR_ENERGY_PER_SECOND 0.0 9 f
# define DAMAGE_TO_PLAYER_PER_BLOCK 0.1f
# define BATTERY_CAPACITY DAMAGE_TO_PLAYER_PER_BLOCK * 0.7 f
# define PLAYER_ENERGY_RECHARGE_PER_SECOND 0. 1 f
# define BATTERY_CAPACITY 1.5 f
# define PLAYER_ENERGY_RECHARGE_PER_SECOND 0. 2 f
# define EXPLOSION_TIME 0.5f
# define EXPLOSION_PUSH_STRENGTH 5.0f
# define EXPLOSION_DAMAGE_PER_SEC 10.0f
@ -44,10 +56,12 @@
# define VOIP_PACKET_BUFFER_SIZE 15 // audio. Must be bigger than 2
# define VOIP_EXPECTED_FRAME_COUNT 480
# define VOIP_SAMPLE_RATE 48000
# define VOIP_TIME_PER_PACKET (1.0f / ((float)(VOIP_SAMPLE_RATE / VOIP_EXPECTED_FRAME_COUNT))) // in seconds
// in seconds
# define VOIP_TIME_PER_PACKET (1.0f / ((float)((float)VOIP_SAMPLE_RATE / VOIP_EXPECTED_FRAME_COUNT)))
# define VOIP_PACKET_MAX_SIZE 4000
# define VOIP_DISTANCE_WHEN_CANT_HEAR (VISION_RADIUS * 0.8f)
// multiplayer
# define MAX_REPREDICTION_TIME (TIMESTEP * 50.0f)
# define TIME_BETWEEN_SEND_GAMESTATE (1.0f / 20.0f)
# define TIME_BETWEEN_INPUT_PACKETS (1.0f / 20.0f)
@ -56,6 +70,9 @@
# define LOCAL_INPUT_QUEUE_MAX 90 // please god let you not have more than 90 frames of game latency
# define INPUT_QUEUE_MAX 15
// fucks up serialization if you change this, fix it if you do that!
# define BOX_UNLOCKS_TYPE uint64_t
// cross platform threadlocal variables
# if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
# define THREADLOCAL __declspec(thread)
@ -75,7 +92,7 @@
// defined in gamestate.c. Janky
# ifndef assert
# define assert(condition) __ assert(condition, __FILE__, __LINE__, #condition)
# define assert(condition) __ flight_ assert(condition, __FILE__, __LINE__, #condition)
# endif
// including headers from headers bad
@ -126,6 +143,7 @@ typedef sgp_point P2;
enum BoxType
{
BoxInvalid , // zero initialized box is invalid!
BoxHullpiece ,
BoxThruster ,
BoxBattery ,
@ -133,6 +151,9 @@ enum BoxType
BoxMedbay ,
BoxSolarPanel ,
BoxExplosive ,
BoxScanner ,
BoxGyroscope ,
BoxCloaking ,
BoxLast ,
} ;
@ -173,6 +194,7 @@ typedef struct InputFrame
{
uint64_t tick ;
V2 movement ;
float rotation ;
int take_over_squad ; // -1 means not taking over any squad
bool accept_cur_squad_invite ;
@ -199,7 +221,13 @@ typedef struct Entity
float damage ; // used by box and player
cpBody * body ; // used by grid, player, and box
cpShape * shape ; // must be a box so shape_size can be set appropriately, and serialized
// players and boxes can be cloaked
// If this is within 2 timesteps of the current game time, the entity is invisible.
double time_was_last_cloaked ;
enum Squad last_cloaked_by_squad ;
// for serializing the shape
// @Robust remove shape_parent_entity from this struct, use the shape's body to figure out
// what the shape's parent entity is
@ -208,7 +236,7 @@ typedef struct Entity
// player
bool is_player ;
enum Squad presenting_squad ;
enum Squad presenting_squad ; // also controls what the player can see, because of cloaking!
EntityID currently_inside_of_box ;
enum Squad squad_invited_to ; // if squad none, then no squad invite
float goldness ; // how much the player is a winner
@ -226,24 +254,47 @@ typedef struct Entity
// boxes
bool is_box ;
bool always_visible ; // always serialized to the player
enum Squad owning_squad ; // which squad owns this box
enum BoxType box_type ;
bool is_explosion_unlock ;
EntityID next_box ;
bool is_platonic ; // can't be destroyed, unaffected by physical forces
bool always_visible ; // always serialized to the player. @Robust check if not used
EntityID next_box ; // for the grid!
EntityID prev_box ; // doubly linked so can remove in middle of chain
enum CompassRotation compass_rotation ;
bool indestructible ;
// used by medbay and cockpit
EntityID player_who_is_inside_of_me ;
// only serialized when box_type is thruster or gyroscope, used for both. Thrust
// can mean rotation thrust!
float wanted_thrust ; // the thrust command applied to the thruster
float thrust ; // the actual thrust it can provide based on energy sources in the grid
float energy_used ; // battery
// only serialized when box_type is battery
float energy_used ; // battery, between 0 battery capacity. You have to look through code to figure out what that is! haha sucker!
// only serialized when box_type is solar panel
float sun_amount ; // solar panel, between 0 and 1
EntityID player_who_is_inside_of_me ;
// cloaking only
float cloaking_power ; // 0.0 if unable to be used because no power, 1.0 if fully cloaking!
// scanner only stuff!
EntityID currently_scanning ;
float currently_scanning_progress ; // when 1.0, scans it!
BOX_UNLOCKS_TYPE blueprints_learned ; // @Robust make this same type as blueprints
float scanner_head_rotate_speed ; // not serialized, cosmetic
float scanner_head_rotate ;
V2 platonic_nearest_direction ; // normalized
float platonic_detection_strength ; // from zero to one
} Entity ;
typedef struct Player
{
bool connected ;
bool unlocked_bombs ;
BOX_UNLOCKS_TYPE box_unlocks ; // each bit is that box's unlock
enum Squad squad ;
EntityID entity ;
EntityID last_used_medbay ;
@ -254,13 +305,17 @@ typedef struct GameState
{
cpSpace * space ;
double time ; // @Robust separate tick integer not prone to precision issues
// @Robust for the integer tick, also store a float for how much time has been processed.
// Like a whole timestep then a float for subtimestep
double time ; // @Robust separate tick integer not prone to precision issues. Could be very large as is saved to disk!
V2 goldpos ;
Player players [ MAX_PLAYERS ] ;
EntityID cur_spacestation ;
V2 platonic_positions [ MAX_BOX_TYPES ] ; // don't want to search over every entity to get the nearest platonic box!
bool server_side_computing ; // some things only the server should know and calculate, like platonic locations
// Entity arena
// ent:ity pointers can't move around because of how the physics engine handles user data.
@ -306,7 +361,7 @@ static float rotangle(enum CompassRotation rot)
typedef struct OpusPacket
{
opus_int32 length ;
char data [ VOIP_PACKET_MAX_SIZE ] ;
unsigned char data [ VOIP_PACKET_MAX_SIZE ] ;
} OpusPacket ;
typedef struct ServerToClient
@ -327,21 +382,23 @@ typedef struct ClientToServer
// server
void server ( void * info ) ; // data parameter required from thread api...
void create_player ( Player * player ) ;
bool box_unlocked ( Player * player , enum BoxType box ) ;
// gamestate
EntityID create_spacestation ( GameState * gs ) ;
void create_initial_world ( GameState * gs ) ;
void initialize ( struct GameState * gs , void * entity_arena , size_t entity_arena_size ) ;
void destroy ( struct GameState * gs ) ;
void process_fixed_timestep ( GameState * gs ) ;
void process ( struct GameState * gs , float dt ) ; // does in place
Entity * closest_ to_point_in_radius( struct GameState * gs , V2 point , float radius ) ;
Entity * closest_ box_ to_point_in_radius( struct GameState * gs , V2 point , float radius , bool ( * filter_func ) ( Entity * ) ) ;
uint64_t tick ( struct GameState * gs ) ;
// all of these return if successful or not
bool server_to_client_serialize ( struct ServerToClient * msg , char * bytes , size_t * out_len , size_t max_len , Entity * for_this_player , bool to_disk ) ;
bool server_to_client_deserialize ( struct ServerToClient * msg , char * bytes , size_t max_len , bool from_disk ) ;
bool client_to_server_deserialize ( GameState * gs , struct ClientToServer * msg , char * bytes , size_t max_len ) ;
bool client_to_server_serialize ( GameState * gs , struct ClientToServer * msg , char * bytes , size_t * out_len , size_t max_len ) ;
bool server_to_client_serialize ( struct ServerToClient * msg , unsigned char* bytes , size_t * out_len , size_t max_len , Entity * for_this_player , bool to_disk ) ;
bool server_to_client_deserialize ( struct ServerToClient * msg , unsigned char* bytes , size_t max_len , bool from_disk ) ;
bool client_to_server_deserialize ( GameState * gs , struct ClientToServer * msg , unsigned char* bytes , size_t max_len ) ;
bool client_to_server_serialize ( GameState * gs , struct ClientToServer * msg , unsigned char* bytes , size_t * out_len , size_t max_len ) ;
// entities
Entity * get_entity ( struct GameState * gs , EntityID id ) ;
@ -359,6 +416,7 @@ void entity_destroy(GameState *gs, Entity *e);
// grid
void grid_create ( struct GameState * gs , Entity * e ) ;
void box_create ( struct GameState * gs , Entity * new_box , Entity * grid , V2 pos ) ;
Entity * box_grid ( Entity * box ) ;
V2 grid_com ( Entity * grid ) ;
V2 grid_vel ( Entity * grid ) ;
V2 box_vel ( Entity * box ) ;
@ -626,4 +684,6 @@ static void set_color(Color c)
( Color ) { . r = 1.0f , . g = 1.0f , . b = 1.0f , . a = 1.0f }
# define RED \
( Color ) { . r = 1.0f , . g = 0.0f , . b = 0.0f , . a = 1.0f }
# define BLUE \
( Color ) { . r = 0.0f , . g = 0.0f , . b = 1.0f , . a = 1.0f }
# define GOLD colhex(255, 215, 0)