eliminated qbyte type, now uses unsigned char throughout the engine for this purpose
[xonotic/darkplaces.git] / cgamevm.c
1
2 #include "quakedef.h"
3 #include "cgame_api.h"
4 #include "cl_collision.h"
5
6 #define CGVM_RENDERENTITIES 1024
7
8 static entity_render_t cgvm_renderentities[CGVM_RENDERENTITIES];
9 static int cgvm_renderentity;
10
11 static mempool_t *cgvm_mempool;
12
13 static void (*cgvm_networkcode[256])(unsigned char num);
14
15 static unsigned char *cgvm_netbuffer;
16 static int cgvm_netbufferlength;
17 static int cgvm_netbufferpos;
18
19 #define MAX_CGVM_MODELS 128
20 #define MAX_CGVM_MODELNAME 32
21 static char cgvm_modelname[MAX_CGVM_MODELS][MAX_CGVM_MODELNAME];
22 static model_t *cgvm_model[MAX_CGVM_MODELS];
23
24 void CL_CGVM_Init(void)
25 {
26         cgvm_mempool = Mem_AllocPool("CGVM", 0, NULL);
27 }
28
29 void CL_CGVM_Shutdown(void)
30 {
31         Mem_FreePool (&cgvm_mempool);
32 }
33
34 void CL_CGVM_Clear(void)
35 {
36         Mem_EmptyPool(cgvm_mempool);
37         memset(cgvm_networkcode, 0, sizeof(cgvm_networkcode));
38         memset(cgvm_modelname, 0, sizeof(cgvm_modelname));
39         memset(cgvm_model, 0, sizeof(cgvm_model));
40 }
41
42 void CL_CGVM_Frame(void)
43 {
44         cgvm_renderentity = 0;
45         CG_Frame(cl.time); // API call
46 }
47
48 // starts the cgame code
49 void CL_CGVM_Start(void)
50 {
51         CL_CGVM_Clear();
52         CG_Init(); // API call
53 }
54
55 void CL_CGVM_ParseNetwork(unsigned char *netbuffer, int length)
56 {
57         int num;
58         cgvm_netbuffer = netbuffer;
59         cgvm_netbufferlength = length;
60         cgvm_netbufferpos = 0;
61         while (cgvm_netbufferpos < cgvm_netbufferlength)
62         {
63                 num = CGVM_MSG_ReadByte();
64                 if (cgvm_networkcode[num])
65                         cgvm_networkcode[num]((unsigned char)num);
66                 else
67                         Host_Error("CL_CGVM_ParseNetwork: unregistered network code %i", num);
68         }
69 }
70
71
72
73
74
75
76
77
78 void CGVM_RegisterNetworkCode(const unsigned char num, void (*netcode)(unsigned char num))
79 {
80         if (cgvm_networkcode[num])
81                 Host_Error("CGVM_RegisterNetworkCode: value %i already registered", num);
82         cgvm_networkcode[num] = netcode;
83 }
84
85 unsigned char CGVM_MSG_ReadByte(void)
86 {
87         if (cgvm_netbufferpos < cgvm_netbufferlength)
88                 return cgvm_netbuffer[cgvm_netbufferpos++];
89         else
90                 return 0;
91 }
92
93 short CGVM_MSG_ReadShort(void)
94 {
95         short num;
96         num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8);
97         return num;
98 }
99
100 int CGVM_MSG_ReadLong(void)
101 {
102         int num;
103         num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
104         return num;
105 }
106
107 float CGVM_MSG_ReadFloat(void)
108 {
109         unsigned int num;
110         num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
111         return *((float *)&num);
112 }
113
114 float CGVM_MSG_ReadCoord(void)
115 {
116         return CGVM_MSG_ReadFloat();
117 }
118
119 float CGVM_MSG_ReadAngle(void)
120 {
121         return CGVM_MSG_ReadByte() * 360.0f / 256.0f;
122 }
123
124 float CGVM_MSG_ReadPreciseAngle(void)
125 {
126         return ((unsigned short)CGVM_MSG_ReadShort()) * 360.0f / 65536.0f;
127 }
128
129 void CGVM_Draw_Entity(const cgdrawentity_t *e)
130 {
131         entity_render_t *r;
132         //Con_Printf("CGVM_Draw_Entity: origin %f %f %f angles %f %f %f alpha %f scale %f model %i frame1 %i frame2 %i framelerp %f skinnum %i\n", e->origin[0], e->origin[1], e->origin[2], e->angles[0], e->angles[1], e->angles[2], e->alpha, e->scale, e->model, e->frame1, e->frame2, e->framelerp, e->skinnum);
133
134         if (!e->model)
135                 return;
136
137         if (cgvm_renderentity >= CGVM_RENDERENTITIES
138          || r_refdef.numentities >= r_refdef.maxentities)
139                 return;
140
141         r = cgvm_renderentities + cgvm_renderentity;
142         VectorCopy(e->origin, r->origin);
143         VectorCopy(e->angles, r->angles);
144         r->alpha = e->alpha;
145         r->scale = e->scale;
146         if (e->model < 0 || e->model >= MAX_CGVM_MODELS || !cgvm_model[e->model])
147         {
148                 Con_Printf("CGVM_Draw_Entity: invalid model index %i\n", e->model);
149                 return;
150         }
151         r->model = cgvm_model[e->model];
152
153         r->frame = e->frame2;
154         // FIXME: support colormapping?
155         r->colormap = -1;
156         // FIXME: support effects?
157         r->effects = 0;
158         r->skinnum = e->skinnum;
159         // FIXME: any flags worth setting?
160         r->flags = 0;
161
162         r->frame1 = e->frame1;
163         r->frame2 = e->frame2;
164         r->framelerp = e->framelerp;
165         r->frame1time = 0;
166         r->frame2time = 0;
167
168         r_refdef.entities[r_refdef.numentities++] = r;
169
170         cgvm_renderentity++;
171 }
172
173 void CGVM_Draw_Light(const cgdrawlight_t *l)
174 {
175         matrix4x4_t matrix;
176         Matrix4x4_CreateTranslate(&matrix, l->origin[0], l->origin[1], l->origin[2]);
177         CL_AllocDlight(NULL, &matrix, l->radius, l->color[0], l->color[1], l->color[2], 0, 0, 0, -1, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
178 }
179
180 void *CGVM_Malloc(const int size)
181 {
182         return Mem_Alloc(cgvm_mempool, size);
183 }
184
185 void CGVM_Free(void *mem)
186 {
187         Mem_Free(mem);
188 }
189
190 float CGVM_RandomRange(const float r1, const float r2)
191 {
192         return lhrandom(r1, r2);
193 }
194
195 float CGVM_TracePhysics(const float *start, const float *end, const float *worldmins, const float *worldmaxs, const float *entitymins, const float *entitymaxs, const cgphysentity_t *physentities, const int numphysentities, float *impactpos, float *impactnormal, int *impactentnum)
196 {
197         trace_t trace;
198         // FIXME: do tracing agains network entities and physentities here
199         trace = CL_TraceBox(start, vec3_origin, vec3_origin, end, true, NULL, SUPERCONTENTS_SOLID, false);
200         VectorCopy(trace.endpos, impactpos);
201         VectorCopy(trace.plane.normal, impactnormal);
202         *impactentnum = -1;
203         return trace.fraction;
204 }
205
206 char *CGVM_GetCvarString(const char *name)
207 {
208         cvar_t *cvar;
209         cvar = Cvar_FindVar((char *)name);
210         if (cvar)
211                 return cvar->string;
212         else
213                 return 0;
214 }
215
216 float CGVM_GetCvarFloat(const char *name)
217 {
218         cvar_t *cvar;
219         cvar = Cvar_FindVar((char *)name);
220         if (cvar)
221                 return cvar->value;
222         else
223                 return 0;
224 }
225
226 int CGVM_GetCvarInt(const char *name)
227 {
228         cvar_t *cvar;
229         cvar = Cvar_FindVar((char *)name);
230         if (cvar)
231                 return cvar->integer;
232         else
233                 return 0;
234 }
235
236 double CGVM_Time(void)
237 {
238         return cl.time;
239 }
240
241 int CGVM_Model(const char *name)
242 {
243         int i;
244         model_t *model;
245         if (strlen(name) > (MAX_CGVM_MODELNAME - 1))
246                 return 0;
247         for (i = 1;i < MAX_CGVM_MODELS;i++)
248         {
249                 if (!cgvm_modelname[i][0])
250                         break;
251                 if (!strcmp(name, cgvm_modelname[i]))
252                         return i;
253         }
254         if (i >= MAX_CGVM_MODELS)
255                 return 0;
256         model = Mod_ForName(name, false, false, false);
257         if (!model)
258                 return 0;
259         strcpy(cgvm_modelname[i], name);
260         cgvm_model[i] = model;
261         return i;
262 }
263
264 void CGVM_Stain(const float *origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
265 {
266         if (cl_stainmaps.integer)
267                 R_Stain((float *)origin, radius, cr1, cg1, cb1, ca1, cr2, cg2, cb2, ca2);
268 }
269