2012-12-19 21:53:34 +13:00

419 lines
8.8 KiB
C

/*
This file is part of Iceball.
Iceball is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Iceball is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Iceball. If not, see <http://www.gnu.org/licenses/>.
*/
#define VERSION_W 0
#define VERSION_X 0
#define VERSION_Y 0
#define VERSION_A 0
#define VERSION_Z 1
// Remember to bump "Z" basically every time you change the engine!
// Z can only be 0 for official releases!
#define MODEL_BONE_MAX 256
#define MODEL_POINT_MAX 4096
#define PACKET_LEN_MAX 1280
#define PATH_LEN_MAX 128
// i wouldn't go near this limit if i were you...
#define CLIENT_MAX 512
#define WAV_MFREQ 44100
//define RENDER_FACE_COUNT 2
#include <immintrin.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#ifndef WIN32
#include <signal.h>
#endif
#include <math.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#ifndef DEDI
#include <SDL.h>
#endif
#include <zlib.h>
#ifdef WIN32
// just so we can get getaddrinfo
// you will need Windows 2000 at least!
#define _WIN32_WINNT 0x0501
#include <winsock2.h>
#include <ws2tcpip.h>
extern WSADATA windows_sucks;
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <fcntl.h>
#endif
enum
{
UD_INVALID = 0,
UD_JSON,
UD_LOG,
UD_LUA,
UD_MAP_ICEMAP,
UD_MAP_VXL,
UD_MAP,
UD_PMF,
UD_IMG_TGA,
UD_WAV,
UD_MAX_SUPPORTED,
UD_IMG,
UD_MAX
};
// if this flag is set, free when finished sending
#define UDF_TEMPSEND 0x8000
#ifdef __SSE__
__attribute__((aligned(16)))
#endif
typedef union vec4f
{
struct { float x,y,z,w; } __attribute__((__packed__)) p;
float a[4];
#ifdef __SSE__
float __attribute__ ((vector_size (16))) m;
#endif
} __attribute__((__packed__)) vec4f_t;
#ifdef __SSE__
__attribute__((aligned(16)))
#endif
typedef struct matrix
{
//column-major!
vec4f_t c[4];
} __attribute__((__packed__)) matrix_t;
typedef struct camera
{
// camera bollocks
float mxx,mxy,mxz,mxpad;
float myx,myy,myz,mypad;
float mzx,mzy,mzz,mzpad;
float mpx,mpy,mpz,mppad;
} camera_t;
typedef struct model_point
{
uint16_t radius;
int16_t x,y,z;
uint8_t b,g,r,resv1;
} __attribute__((__packed__)) model_point_t;
typedef struct model model_t;
typedef struct model_bone
{
int udtype;
char name[16];
model_t *parent;
int parent_idx;
int ptlen, ptmax;
model_point_t pts[];
} model_bone_t;
struct model
{
int udtype;
int bonelen, bonemax;
model_bone_t *bones[];
};
// source: http://paulbourke.net/dataformats/tga/
typedef struct img_tgahead
{
uint8_t idlen;
uint8_t cmtype;
uint8_t imgtype;
uint16_t cmoffs;
uint16_t cmlen;
uint8_t cmbpp;
uint16_t xstart;
uint16_t ystart;
uint16_t width;
uint16_t height;
uint8_t bpp;
uint8_t flags;
} __attribute__((__packed__)) img_tgahead_t;
typedef struct img
{
int udtype;
img_tgahead_t head;
uint32_t pixels[];
} img_t;
/*
Pillar data:
Note, indices are like so:
0 1 2 3
Column header:
L - - -:
(L+1)*4 = length in bytes
- = reserved
Chunk header:
N S E A:
N = number of 4bytes including header this chunk has (N=0 => last chunk)
S = starting block for top part
E = ending block for top part
A = air start after bottom part (N=0 => E-S+1 blocks are stored)
Block data:
B G R T:
B = blue
G = green
R = red! suprised?
T = type of block.
In other words, VOXLAP vxl with a length header and different 4th data byte,
and you can actually store crap in the invisible sections.
(Trust me. This format packs incredibly well.)
If you're keen to store interesting stuff that's not visible,
feel free to store it in the "invisible" parts.
*Yes*, you can get away with this! We're not using a static 16MB heap.
*/
typedef struct map
{
int udtype;
int xlen, ylen, zlen;
uint8_t **pillars;
// TODO ? heap allocator ?
} map_t;
enum
{
BT_INVALID = 0, // don't use this type!
BT_SOLID_BREAKABLE,
BT_MAX
};
typedef struct packet packet_t;
struct packet
{
packet_t *p, *n;
int sockfd;
int len;
char data[];
};
typedef struct client
{
packet_t *head, *tail;
packet_t *send_head, *send_tail;
int sockfd;
int isfull;
// client only
char *cfetch_ubuf;
char *cfetch_cbuf;
int cfetch_ulen, cfetch_clen;
int cfetch_cpos;
int cfetch_udtype;
// server only
char *sfetch_ubuf;
char *sfetch_cbuf;
int sfetch_ulen, sfetch_clen;
int sfetch_cpos;
int sfetch_udtype;
// serialisation
char rpkt_buf[PACKET_LEN_MAX*2];
int rpkt_len;
char spkt_buf[PACKET_LEN_MAX*2];
int spkt_ppos,spkt_len;
} client_t;
struct netdata
{
int sockfd;
} netdata_t;
#define SOCKFD_NONE -1
#define SOCKFD_LOCAL -2
enum
{
PATH_INVALID_ENUM = 0, // don't use this!
PATH_CLSAVE_BASEDIR,
PATH_CLSAVE_BASEDIR_VOLATILE,
PATH_CLSAVE_PUBLIC,
PATH_CLSAVE_VOLATILE,
PATH_SVSAVE_BASEDIR,
PATH_SVSAVE_BASEDIR_VOLATILE,
PATH_SVSAVE_PUBLIC,
PATH_SVSAVE_VOLATILE,
PATH_PKG_BASEDIR,
PATH_PKG,
PATH_ERROR_BADCHARS,
PATH_ERROR_ACCDENIED,
PATH_ENUM_MAX
};
// img.c
void img_free(img_t *img);
img_t *img_parse_tga(int len, const char *data);
img_t *img_load_tga(const char *fname);
// json.c
int json_parse(lua_State *L, const char *p);
int json_load(lua_State *L, const char *fname);
// lua.c
extern lua_State *lstate_client;
extern lua_State *lstate_server;
int icelua_initfetch(void);
int icelua_init(void);
void icelua_deinit(void);
// main.c
extern camera_t tcam;
extern map_t *clmap, *svmap;
#ifndef DEDI
extern SDL_Surface *screen;
#endif
extern int force_redraw;
extern int net_port;
extern char *net_addr;
extern int boot_mode;
extern char *mod_basedir;
extern int main_argc;
extern char **main_argv;
extern int main_largstart;
int run_game_cont1(void);
int run_game_cont2(void);
int error_sdl(char *msg);
int error_perror(char *msg);
// map.c
map_t *map_parse_aos(int len, const char *data);
map_t *map_parse_icemap(int len, const char *data);
map_t *map_load_aos(const char *fname);
map_t *map_load_icemap(const char *fname);
char *map_serialise_icemap(map_t *map, int *len);
int map_save_icemap(map_t *map, const char *fname);
void map_free(map_t *map);
// model.c
model_bone_t *model_bone_new(model_t *pmf, int ptmax);
model_bone_t *model_bone_extend(model_bone_t *bone, int ptmax);
void model_bone_free(model_bone_t *bone);
model_t *model_new(int bonemax);
model_t *model_extend(model_t *pmf, int bonemax);
void model_free(model_t *pmf);
model_t *model_parse_pmf(int len, const char *data);
model_t *model_load_pmf(const char *fname);
int model_save_pmf(model_t *pmf, const char *fname);
// network.c
extern client_t to_server;
extern client_t to_clients[];
extern client_t to_client_local;
char *net_fetch_file(const char *fname, int *flen);
int net_packet_push(int len, const char *data, int sockfd, packet_t **head, packet_t **tail);
int net_packet_push_lua(int len, const char *data, int sockfd, packet_t **head, packet_t **tail);
packet_t *net_packet_pop(packet_t **head, packet_t **tail);
void net_packet_free(packet_t *pkt, packet_t **head, packet_t **tail);
void net_flush(void);
int net_connect(void);
void net_disconnect(void);
int net_bind(void);
void net_unbind(void);
int net_init(void);
void net_deinit(void);
// path.c
char *path_filter(const char *path);
int path_get_type(const char *path);
int path_type_client_local(int type);
int path_type_client_readable(int type);
int path_type_client_writable(int type);
int path_type_server_readable(int type);
int path_type_server_writable(int type);
// render.c
#ifdef RENDER_FACE_COUNT
extern int render_face_remain;
#endif
#define FOG_MAX_DISTANCE 511.5f /* that's not going to work well, by the way! */
#define FOG_INIT_DISTANCE 60.0f
extern float fog_distance;
extern uint32_t fog_color;
void render_vxl_redraw(camera_t *camera, map_t *map);
void render_cubemap(uint32_t *pixels, int width, int height, int pitch, camera_t *camera, map_t *map);
void render_pmf_bone(uint32_t *pixels, int width, int height, int pitch, camera_t *cam_base,
model_bone_t *bone, int islocal,
float px, float py, float pz, float ry, float rx, float ry2, float scale);
void render_blit_img(uint32_t *pixels, int width, int height, int pitch,
img_t *src, int dx, int dy, int bw, int bh, int sx, int sy, uint32_t color);
int render_init(int width, int height);
void render_deinit(void);
// vecmath.c
vec4f_t mtx_apply_vec(matrix_t *mtx, vec4f_t *vec);
void mtx_identity(matrix_t *mtx);
void cam_point_dir(camera_t *model, float dx, float dy, float dz, float zoom, float roll);
// wav.c
int wav_init(void);
void wav_deinit(void);