1 // the interface the game uses to access the engine
2 
3 extern int verbose, curtime, lastmillis, totalmillis, timescale, paused;
4 extern uint totalsecs;
5 extern time_t clocktime, currenttime, clockoffset;
6 extern int servertype, serverport, serverlanport, servermasterport;
7 extern char *servermaster, *serverip;
8 #ifdef STANDALONE
9 #define servercheck(x) (x)
10 #else
11 #define servercheck(x) (servertype >= 3 && (x))
12 #endif
13 extern ENetAddress masteraddress;
14 extern void fatal(const char *s, ...) PRINTFARGS(1, 2);
15 extern void console(int type, const char *s, ...) PRINTFARGS(2, 3);
16 extern void conoutft(int type, const char *s, ...) PRINTFARGS(2, 3);
17 extern void conoutf(const char *s, ...) PRINTFARGS(1, 2);
18 
19 extern FILE *logfile;
20 extern FILE *getlogfile();
21 extern void setlogfile(const char *fname);
22 extern void closelogfile();
23 extern void logoutfv(const char *fmt, va_list args);
24 extern void logoutf(const char *fmt, ...) PRINTFARGS(1, 2);
25 
26 #ifdef __GNUC__
27 #define _dbg_ fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
28 #else
29 #define _dbg_ fprintf(stderr, "%s:%d\n", __FILE__, __LINE__);
30 #endif
31 
32 struct namemap { const char *name; int id; };
33 
34 extern void lightent(extentity &e, float height = 8);
35 extern void lightreaching(const vec &target, vec &color, vec &dir, bool fast = false, extentity *e = 0, float ambient = 0.4f);
36 extern const extentity *brightestlight(const vec &target, const vec &dir);
37 
38 enum { RAY_BB = 1, RAY_POLY = 3, RAY_ALPHAPOLY = 7, RAY_ENTS = 9, RAY_CLIPMAT = 16, RAY_SKIPFIRST = 32, RAY_EDITMAT = 64, RAY_SHADOW = 128, RAY_PASS = 256, RAY_SKIPSKY = 512 };
39 
40 extern float raycube   (const vec &o, const vec &ray,     float radius = 0, int mode = RAY_CLIPMAT, int size = 0, extentity *t = 0);
41 extern float raycubepos(const vec &o, const vec &ray, vec &hit, float radius = 0, int mode = RAY_CLIPMAT, int size = 0);
42 extern float rayfloor  (const vec &o, vec &floor, int mode = 0, float radius = 0);
43 extern bool  raycubelos(const vec &o, const vec &dest, vec &hitpos);
44 
45 struct Texture;
46 
47 extern bool settexture(const char *name, int clamp = 0);
48 
49 // world
50 extern bool emptymap(int scale, bool force = false, const char *mname = NULL, bool usecfg = true);
51 extern bool enlargemap(bool split = false, bool force = false);
52 extern int findentity(int type, int index, vector<int> &attr);
53 extern void mpeditent(int i, const vec &o, int type, attrvector &attr, bool local = true);
54 
55 // octa
56 extern int lookupmaterial(const vec &o);
57 
insideworld(const vec & o)58 static inline bool insideworld(const vec &o)
59 {
60     extern int worldsize;
61     return o.x>=0 && o.x<worldsize && o.y>=0 && o.y<worldsize && o.z>=0 && o.z<worldsize;
62 }
63 
insideworld(const ivec & o)64 static inline bool insideworld(const ivec &o)
65 {
66     extern int worldsize;
67     return uint(o.x)<uint(worldsize) && uint(o.y)<uint(worldsize) && uint(o.z)<uint(worldsize);
68 }
69 
70 // octaedit
71 
72 enum { EDIT_FACE = 0, EDIT_TEX, EDIT_MAT, EDIT_FLIP, EDIT_COPY, EDIT_PASTE, EDIT_ROTATE, EDIT_REPLACE, EDIT_DELCUBE, EDIT_CALCLIGHT, EDIT_REMIP, EDIT_VSLOT, EDIT_UNDO, EDIT_REDO };
73 
74 struct selinfo
75 {
76     int corner;
77     int cx, cxs, cy, cys;
78     ivec o, s;
79     int grid, orient;
selinfoselinfo80     selinfo() : corner(0), cx(0), cxs(0), cy(0), cys(0), o(0, 0, 0), s(0, 0, 0), grid(8), orient(0) {}
sizeselinfo81     int size() const    { return s.x*s.y*s.z; }
usselinfo82     int us(int d) const { return s[d]*grid; }
83     bool operator==(const selinfo &sel) const { return o==sel.o && s==sel.s && grid==sel.grid && orient==sel.orient; }
validateselinfo84     bool validate()
85     {
86         extern int worldsize;
87         if(grid <= 0 || grid >= worldsize) return false;
88         if(o.x >= worldsize || o.y >= worldsize || o.z >= worldsize) return false;
89         if(o.x < 0) { s.x -= (grid - 1 - o.x)/grid; o.x = 0; }
90         if(o.y < 0) { s.y -= (grid - 1 - o.y)/grid; o.y = 0; }
91         if(o.z < 0) { s.z -= (grid - 1 - o.z)/grid; o.z = 0; }
92         s.x = clamp(s.x, 0, (worldsize - o.x)/grid);
93         s.y = clamp(s.y, 0, (worldsize - o.y)/grid);
94         s.z = clamp(s.z, 0, (worldsize - o.z)/grid);
95         return s.x > 0 && s.y > 0 && s.z > 0;
96     }
97 };
98 extern selinfo sel;
99 extern bool havesel;
100 
101 struct editinfo;
102 
103 extern bool editmode;
104 
105 extern int shouldpacktex(int index);
106 extern bool packeditinfo(editinfo *e, int &inlen, uchar *&outbuf, int &outlen);
107 extern bool unpackeditinfo(editinfo *&e, const uchar *inbuf, int inlen, int outlen);
108 extern void freeeditinfo(editinfo *&e);
109 extern void rendereditcursor();
110 extern void boxs(int orient, vec o, const vec &s, float size);
111 extern void boxs(int orient, vec o, const vec &s);
112 extern void boxs3D(const vec &o, vec s, int g);
113 extern void boxsgrid(int orient, vec o, vec s, int g);
114 extern void renderboundboxes();
115 extern void pruneundos(int maxremain = 0);
116 extern bool packundo(int op, int &inlen, uchar *&outbuf, int &outlen);
117 extern bool unpackundo(const uchar *inbuf, int inlen, int outlen);
118 extern bool noedit(bool view = false, bool msg = true);
119 extern void toggleedit(bool force = true);
120 extern void mpeditface(int dir, int mode, selinfo &sel, bool local);
121 extern void mpedittex(int tex, int allfaces, selinfo &sel, bool local);
122 extern bool mpedittex(int tex, int allfaces, selinfo &sel, ucharbuf &buf);
123 extern void mpeditmat(int matid, int filter, int style, selinfo &sel, bool local);
124 extern void mpflip(selinfo &sel, bool local);
125 extern void mpcopy(editinfo *&e, selinfo &sel, bool local);
126 extern void mppaste(editinfo *&e, selinfo &sel, bool local);
127 extern void mprotate(int cw, selinfo &sel, bool local);
128 extern void mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, bool local);
129 extern bool mpreplacetex(int oldtex, int newtex, bool insel, selinfo &sel, ucharbuf &buf);
130 extern void mpdelcube(selinfo &sel, bool local);
131 extern void mpremip(bool local);
132 extern bool mpeditvslot(int delta, int allfaces, selinfo &sel, ucharbuf &buf);
133 extern void mpcalclight(bool local);
134 
135 // console
136 extern int changedkeys;
137 
138 extern void processtextinput(const char *str, int len);
139 extern void processkey(int code, bool isdown);
140 extern void resetcomplete();
141 extern void complete(char *s, const char *cmdprefix, bool reverse);
142 extern const char *searchbind(const char *action, int type);
143 extern void searchbindlist(const char *action, int type, int limit, const char *s1, const char *s2, const char *sep1, const char *sep2, vector<char> &names, bool force = true);
144 
145 extern bool capslockon, numlockon;
146 extern bool capslocked();
147 extern bool numlocked();
148 
149 struct bindlist
150 {
151     vector<char> names;
152     int lastsearch;
153 
bindlistbindlist154     bindlist() : lastsearch(-1) {}
155 
156     const char *search(const char *action, int type = 0, const char *s1 = "\f{", const char *s2 = "}", const char *sep1 = " ", const char *sep2 = " ", int limit = 5)
157     {
158         if(names.empty() || lastsearch != changedkeys)
159         {
160             names.shrink(0);
161             searchbindlist(action, type, limit, s1, s2, sep1, sep2, names);
162             lastsearch = changedkeys;
163         }
164         return names.getbuf();
165     }
166 };
167 
168 // rendertext
169 extern int colourblack, colourwhite,
170     colourgreen, colourblue, colouryellow, colourred, colourgrey, colourmagenta, colourorange, colourcyan, colourpink, colourviolet, colourpurple, colourbrown,
171     colourdarkgreen, colourdarkblue, colourdarkyellow, colourdarkred, colourdarkgrey, colourdarkmagenta, colourdarkorange, colourdarkcyan, colourdarkpink, colourdarkviolet, colourdarkpurple, colourdarkbrown;
172 
173 // texture
174 
175 struct VSlot;
176 
177 extern void packvslot(vector<uchar> &buf, int index);
178 extern void packvslot(vector<uchar> &buf, const VSlot *vs);
179 
180 // renderlights
181 
182 enum { L_NOSHADOW = 1<<0, L_NODYNSHADOW = 1<<1, L_VOLUMETRIC = 1<<2, L_NOSPEC = 1<<3, L_ALL = L_NOSHADOW|L_NODYNSHADOW|L_VOLUMETRIC|L_NOSPEC };
183 
184 // dynlight
185 enum
186 {
187     DL_SHRINK = 1<<8,
188     DL_EXPAND = 1<<9,
189     DL_FLASH  = 1<<10
190 };
191 
192 extern void adddynlight(const vec &o, float radius, const vec &color, int fade = 0, int peak = 0, int flags = 0, float initradius = 0, const vec &initcolor = vec(0, 0, 0), physent *owner = NULL, const vec &dir = vec(0, 0, 0), int spot = 0);
193 extern void dynlightreaching(const vec &target, vec &color, vec &dir, bool hud = false);
194 
195 // rendergl
196 extern vec worldpos, camdir, camright, camup;
197 extern void gettextres(int &w, int &h);
198 
199 extern vec calcmodelpreviewpos(const vec &radius, float &yaw);
200 
201 extern vec minimapcenter, minimapradius, minimapscale;
202 extern void bindminimap();
203 
204 extern matrix4 hudmatrix;
205 extern void resethudmatrix();
206 extern void pushhudmatrix();
207 extern void flushhudmatrix(bool flushparams = true);
208 extern void pophudmatrix(bool flush = true, bool flushparams = true);
209 extern void pushhudscale(float sx, float sy = 0);
210 extern void pushhudtranslate(float tx, float ty, float sx = 0, float sy = 0);
211 extern void resethudshader();
212 
213 // renderparticles
214 enum
215 {
216     PT_PART = 0,
217     PT_TAPE,
218     PT_TRAIL,
219     PT_TEXT,
220     PT_EXPLOSION,
221     PT_LIGHTNING,
222     PT_FLARE,
223     PT_PORTAL,
224     PT_ICON,
225     PT_LINE,
226     PT_TRIANGLE,
227     PT_ELLIPSE,
228     PT_CONE,
229     PT_TYPE     = 0xFF,
230 
231     PT_MOD      = 1<<8,
232     PT_RND4     = 1<<9,     // uses random image quarters
233     PT_LERP     = 1<<10,    // use very sparingly - order of blending issues
234     PT_BRIGHT   = 1<<11,
235     PT_SOFT     = 1<<12,    // use soft quad rendering when available
236     PT_HFLIP    = 1<<13,    // uses random horizontal flipping
237     PT_VFLIP    = 1<<14,    // uses random vertical flipping
238     PT_ROT      = 1<<15,    // uses random rotation
239     PT_CULL     = 1<<16,
240     PT_FEW      = 1<<17,    // allocate smaller number of particles
241     PT_ONTOP    = 1<<18,    // render on top of everything else, remove depth testing
242     PT_NOTEX    = 1<<19,
243     PT_SHADER   = 1<<20,
244     PT_NOLAYER  = 1<<21,
245     PT_SHRINK   = 1<<22,    // shrink particle as it fades
246     PT_GROW     = 1<<23,    // grow particle as it fades
247     PT_WIND     = 1<<24,    // particles affected by the wind
248     PT_FLIP     = PT_HFLIP | PT_VFLIP | PT_ROT
249 };
250 
251 enum
252 {
253     PART_TELEPORT = 0, PART_ICON,
254     PART_LINE, PART_LINE_ONTOP, PART_TRIANGLE, PART_TRIANGLE_ONTOP,
255     PART_ELLIPSE, PART_ELLIPSE_ONTOP, PART_CONE, PART_CONE_ONTOP,
256     PART_FIREBALL_LERP, PART_PLASMA_LERP, PART_FLARE_LERP, PART_MUZZLE_FLARE_LERP,
257     PART_SMOKE_LERP_SOFT, PART_SMOKE_LERP, PART_HINT_LERP_SOFT, PART_HINT_LERP, PART_HINT_BOLD_LERP_SOFT, PART_HINT_BOLD_LERP,
258     PART_HINT_VERT_LERP_SOFT, PART_VERT_BOLD_LERP, PART_HINT_HORZ_LERP_SOFT, PART_HORZ_BOLD_LERP,
259     PART_SMOKE_SOFT, PART_SMOKE, PART_HINT_SOFT, PART_HINT, PART_HINT_BOLD_SOFT, PART_HINT_BOLD,
260     PART_HINT_VERT_SOFT, PART_VERT_BOLD, PART_HINT_HORZ_SOFT, PART_HORZ_BOLD,
261     PART_BLOOD,
262     PART_EDIT, PART_EDIT_ONTOP,
263     PART_SPARK,
264     PART_FIREBALL_SOFT, PART_FIREBALL,
265     PART_PLASMA_SOFT, PART_PLASMA,
266     PART_ELECTRIC_SOFT, PART_ELECTRIC,
267     PART_ELECZAP_SOFT, PART_ELECZAP,
268     PART_FLAME,
269     PART_FLARE, PART_MUZZLE_FLARE, PART_LIGHTNING_FLARE, PART_LIGHTZAP_FLARE,
270     PART_MUZZLE_FLASH,
271     PART_SNOW,
272     PART_TEXT, PART_TEXT_ONTOP,
273     PART_EXPLOSION, PART_SHOCKWAVE, PART_SHOCKBALL, PART_GLIMMERY,
274     PART_LIGHTNING, PART_LIGHTZAP,
275     PART_LENS_FLARE,
276     PART_MAX
277 };
278 
279 struct particle
280 {
281     vec o, d, m;
282     int collide, fade, gravity, millis;
283     bvec color;
284     uchar flags;
285     windprobe wind;
286     float size, blend;
287     union
288     {
289         const char *text;
290         float val;
291         struct
292         {
293             uchar color2[3];
294             uchar progress;
295         };
296     };
297     physent *owner;
298 };
299 
300 extern void regular_part_create(int type, int fade, const vec &p, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL, int delay = 0);
301 extern void part_create(int type, int fade, const vec &p, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL);
302 extern void regular_part_splash(int type, int num, int fade, const vec &p, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0, float radius = 150, float vel = 1, int delay = 0);
303 extern void part_splash(int type, int num, int fade, const vec &p, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0, float radius = 4, float vel = 1);
304 extern void part_trail(int type, int fade, const vec &s, const vec &e, int color = colourwhite, float size = .8f, float blend = 1, float gravity = 0, int collide = 0);
305 extern void part_text(const vec &s, const char *t, int type = PART_TEXT, int fade = 1, int color = colourwhite, float size = 2, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL);
306 extern void part_textcopy(const vec &s, const char *t, int type = PART_TEXT, int fade = 1, int color = colourwhite, float size = 2, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL);
307 extern void part_flare(const vec &p, const vec &dest, int fade, int type, int color = colourwhite, float size = 2, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL);
308 extern void regular_part_explosion(const vec &dest, float maxsize, int type, int fade = 1, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0);
309 extern void part_explosion(const vec &dest, float maxsize, int type, int fade = 1, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0);
310 extern void part_spawn(const vec &o, const vec &v, float z, uchar type, int amt = 1, int fade = 1, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0);
311 extern void part_flares(const vec &o, const vec &v, float z1, const vec &d, const vec &w, float z2, uchar type, int amt = 1, int fade = 1, int color = colourwhite, float size = 4, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL);
312 extern void part_portal(const vec &o, float size, float blend = 1, float yaw = 0, float pitch = 0, int type = PART_TELEPORT, int fade = 1, int color = colourwhite);
313 extern void part_icon(const vec &o, Texture *tex, float size = 2, float blend = 1, float gravity = 0, int collide = 0, int fade = 1, int color = colourwhite, float start = 0, float length = 1, physent *pl = NULL);
314 extern void part_line(const vec &o, const vec &v, float size = 1, float blend = 1, int fade = 1, int color = colourwhite, int type = PART_LINE);
315 extern void part_triangle(const vec &o, float yaw, float pitch, float size = 1, float blend = 1, int fade = 1, int color = colourwhite, bool fill = true, int type = PART_TRIANGLE);
316 extern void part_dir(const vec &o, float yaw, float pitch, float length = 1, float size = 1, float blend = 1, int fade = 1, int color = colourpink, int interval = 0, bool fill = true);
317 extern void part_trace(const vec &o, const vec &v, float size = 1, float blend = 1, int fade = 1, int color = colourwhite, int interval = 0, bool fill = true);
318 extern void part_ellipse(const vec &o, const vec &v, float size = 1, float blend = 1, int fade = 1, int color = colourwhite, int axis = 0, bool fill = false, int type = PART_ELLIPSE);
319 extern void part_radius(const vec &o, const vec &v, float size = 1, float blend = 1, int fade = 1, int color = colourcyan, bool fill = false);
320 extern void part_cone(const vec &o, const vec &dir, float radius, float angle = 0.f, float size = 1, float blend = 1, int fade = 1, int color = colourcyan, bool fill = false, int spokenum = 15, int type = PART_CONE);
321 
322 extern void removetrackedparticles(physent *pl = NULL);
323 extern int particletext, maxparticledistance;
324 
325 extern particle *newparticle(const vec &o, const vec &d, int fade, int type, int color = colourwhite, float size = 2, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL);
326 extern void create(int type, int color, int fade, const vec &p, float size = 2, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL);
327 extern void regularcreate(int type, int color, int fade, const vec &p, float size = 2, float blend = 1, float gravity = 0, int collide = 0, physent *pl = NULL, int delay = 0);
328 extern void splash(int type, int color, float radius, int num, int fade, const vec &p, float size = 2, float blend = 1, float gravity = 0, int collide = 0, float vel = 1);
329 extern void regularsplash(int type, int color, float radius, int num, int fade, const vec &p, float size = 2, float blend = 1, float gravity = 0, int collide = 0, float vel = 1, int delay = 0);
330 extern void createshape(int type, float radius, int color, int dir, int num, int fade, const vec &p, float size = 2, float blend = 1, float gravity = 0, int collide = 0, float vel = 1);
331 extern void regularshape(int type, float radius, int color, int dir, int num, int fade, const vec &p, float size = 2, float blend = 1, float gravity = 0, int collide = 0, float vel = 1);
332 extern void regularflame(int type, const vec &p, float radius, float height, int color, int density = 3, int fade = 500, float size = 2, float blend = 1, float gravity = -1, int collide = 0, float vel = 1);
333 
334 // stain
335 enum
336 {
337     STAIN_NONE = 0,
338     STAIN_SCORCH, STAIN_SCORCH_SHORT,
339     STAIN_BLOOD,
340     STAIN_BULLET,
341     STAIN_ENERGY,
342     STAIN_STAIN,
343     STAIN_SMOKE,
344     STAIN_MAX
345 };
346 
347 extern void addstain(int type, const vec &center, const vec &surface, float radius, const bvec &color = bvec(0xFF, 0xFF, 0xFF), int info = 0);
348 
349 static inline void addstain(int type, const vec &center, const vec &surface, float radius, int color, int info = 0)
350 {
351     addstain(type, center, surface, radius, bvec::fromcolor(color), info);
352 }
353 
354 // worldio
355 extern void setnames(const char *fname, int crc = 0);
356 extern bool load_world(const char *mname, int crc = 0, int variant = MPV_DEF);
357 extern void save_world(const char *mname, bool nodata = false, bool forcesave = false);
358 extern char *mapctitle(const char *s);
359 extern char *mapcauthor(const char *s);
360 extern char *mapcdesc(const char *s);
361 
362 // physics
363 extern bool ellipsecollide(physent *d, const vec &dir, const vec &o, const vec &center, float yaw, float xr, float yr, float hi, float lo);
364 extern bool collide(physent *d, const vec &dir = vec(0, 0, 0), float cutoff = 0, bool playercol = true, bool insideplayercol = false, float guard = 0);
365 extern bool plcollide(physent *d, const vec &dir = vec(0, 0, 0), bool insideplayercol = false, float guard = 0);
366 extern bool plcollide(physent *d, const vec &dir, physent *o, float guard = 0);
367 extern float pltracecollide(physent *d, const vec &o, const vec &ray, float maxdist, float guard = 0);
368 extern float tracecollide(physent *d, const vec &o, const vec &ray, float maxdist, int mode = RAY_CLIPMAT|RAY_ALPHAPOLY, bool playercol = true, float guard = 0);
369 extern bool intersect(physent *d, const vec &from, const vec &to, float &dist, float guard);
370 extern bool overlapsbox(const vec &d, float h1, float r1, const vec &v, float h2, float r2);
371 extern const vector<physent *> &checkdynentcache(int x, int y);
372 extern void updatedynentcache(physent *d);
373 extern void cleardynentcache();
374 
375 // rendermodel
376 extern void rendermodel(const char *mdl, modelstate &state, dynent *d = NULL);
377 extern int intersectmodel(const char *mdl, modelstate &state, const vec &o, const vec &ray, float &dist, int mode = 0, dynent *d = NULL);
378 extern void abovemodel(vec &o, const char *mdl);
379 extern void interpolateorientation(dynent *d, float &interpyaw, float &interppitch);
380 extern void setbbfrommodel(dynent *d, const char *mdl, float size = 1);
381 extern const char *mapmodelname(int i);
382 extern model *loadmodel(const char *name, int i = -1, bool msg = false);
383 extern model *loadlodmodel(model *m, const vec &pos);
384 extern void preloadmodel(const char *name);
385 extern void flushpreloadedmodels(bool msg = true);
386 extern void resetmapmodels(int n = 0);
387 
388 // ragdoll
389 extern bool validragdoll(dynent *d, int millis);
390 extern void moveragdoll(dynent *d);
391 extern void cleanragdoll(dynent *d);
392 extern void warpragdoll(dynent *d, const vec &vel, const vec &offset = vec(0, 0, 0));
393 extern void twitchragdoll(dynent *d, float vel);
394 
395 // server
396 #define MAXCLIENTS 256  // in a multiplayer game, can be arbitrarily changed
397 #define MAXTRANS 5000   // max amount of data to swallow in 1 go
398 #define MAXSDESCLEN 80  // max length of server description field
399 
400 enum { DISC_NONE = 0, DISC_EOP, DISC_CN, DISC_KICK, DISC_MSGERR, DISC_IPBAN, DISC_PRIVATE, DISC_PASSWORD, DISC_PURE, DISC_MAXCLIENTS, DISC_INCOMPATIBLE, DISC_TIMEOUT, DISC_OVERFLOW, DISC_SHUTDOWN, DISC_HOSTFAIL, DISC_AUTH, DISC_NUM };
401 
402 extern void *getinfo(int i);
403 extern const char *gethostip(int i);
404 extern void sendf(int cn, int chan, const char *format, ...);
405 extern void sendfile(int cn, int chan, stream *file, const char *format = "", ...);
406 extern void sendpacket(int cn, int chan, ENetPacket *packet, int exclude = -1);
407 extern void flushserver(bool force);
408 extern int getservermtu();
409 extern int getnumclients();
410 extern uint getclientip(int n);
411 extern bool filterword(char *src, const char *list);
412 extern bool filterstring(char *dst, const char *src, bool newline, bool colour, bool whitespace, bool wsstrip, size_t len);
413 template<size_t N> static inline bool filterstring(char (&dst)[N], const char *src, bool newline = true, bool colour = true, bool whitespace = true, bool wsstrip = false) { return filterstring(dst, src, newline, colour, whitespace, wsstrip, N-1); }
414 extern void disconnect_client(int n, int reason);
415 extern void kicknonlocalclients(int reason);
416 extern bool hasnonlocalclients();
417 extern bool haslocalclients();
418 extern void limitdupclients();
419 extern void sendqueryreply(ucharbuf &p);
420 extern bool resolverwait(const char *name, ENetAddress *address);
421 extern int connectwithtimeout(ENetSocket sock, const char *hostname, const ENetAddress &address);
422 extern bool connectedmaster();
423 extern ENetSocket connectmaster(bool reuse = true);
424 extern void disconnectmaster();
425 extern bool requestmaster(const char *req);
426 extern bool requestmasterf(const char *fmt, ...) PRINTFARGS(1, 2);
427 extern void flushmasteroutput();
428 extern void flushmasterinput();
429 
430 extern void setverinfo(const char *bin);
431 extern void setlocations(const char *bin);
432 
433 // client
434 struct serverinfo
435 {
436     enum
437     {
438         MAXPINGS = 3,
439         WAITING = INT_MAX
440     };
441     enum { UNRESOLVED = 0, RESOLVING, RESOLVED };
442 
443     string name, map, sdesc, authhandle, flags, branch;
444     int numplayers, lastping, lastinfo, nextping, ping, resolved, port, priority;
445     int pings[MAXPINGS];
446     vector<int> attr;
447     vector<char *> players, handles;
448     ENetAddress address;
449 
450     serverinfo(uint ip, int port, int priority = 0)
451      : numplayers(0), resolved(ip==ENET_HOST_ANY ? UNRESOLVED : RESOLVED), port(port), priority(priority)
452     {
453         name[0] = map[0] = sdesc[0] = authhandle[0] = flags[0] = branch[0] = '\0';
454         address.host = ip;
455         address.port = port+1;
456         clearpings();
457     }
~serverinfoserverinfo458     ~serverinfo() { cleanup(); }
459 
clearpingsserverinfo460     void clearpings()
461     {
462         ping = WAITING;
463         loopk(MAXPINGS) pings[k] = WAITING;
464         nextping = 0;
465         lastping = lastinfo = -1;
466     }
467 
cleanupserverinfo468     void cleanup()
469     {
470         clearpings();
471         attr.setsize(0);
472         players.deletearrays();
473         handles.deletearrays();
474         numplayers = 0;
475     }
476 
resetserverinfo477     void reset()
478     {
479         lastping = lastinfo = -1;
480     }
481 
checkdecayserverinfo482     void checkdecay(int decay)
483     {
484         if(lastping >= 0 && totalmillis - lastping >= decay)
485             cleanup();
486         if(lastping < 0) lastping = totalmillis ? totalmillis : 1;
487     }
488 
calcpingserverinfo489     void calcping()
490     {
491         int numpings = 0, totalpings = 0;
492         loopk(MAXPINGS) if(pings[k] != WAITING) { totalpings += pings[k]; numpings++; }
493         ping = numpings ? totalpings/numpings : WAITING;
494     }
495 
addpingserverinfo496     void addping(int rtt, int millis)
497     {
498         if(millis >= lastping) lastping = -1;
499         pings[nextping] = rtt;
500         nextping = (nextping+1)%MAXPINGS;
501         calcping();
502     }
503 };
504 
505 extern vector<serverinfo *> servers;
506 
507 extern void sendclientpacket(ENetPacket *packet, int chan);
508 extern void flushclient();
509 extern void disconnect(bool onlyclean = false, bool async = false);
510 extern bool multiplayer(bool msg = true);
511 extern void neterr(const char *s);
512 extern void gets2c();
513 
514 // crypto
515 extern void genprivkey(const char *seed, vector<char> &privstr, vector<char> &pubstr);
516 extern bool calcpubkey(const char *privstr, vector<char> &pubstr);
517 extern bool hashstring(const char *str, char *result, int maxlen);
518 extern void answerchallenge(const char *privstr, const char *challenge, vector<char> &answerstr);
519 extern void *parsepubkey(const char *pubstr);
520 extern void freepubkey(void *pubkey);
521 extern void *genchallenge(void *pubkey, const void *seed, int seedlen, vector<char> &challengestr);
522 extern void freechallenge(void *answer);
523 extern bool checkchallenge(const char *answerstr, void *correct);
524 
525 // UI
526 enum { EDITORFOCUSED = 1, EDITORUSED, EDITORFOREVER, EDITORREADONLY };
527 struct editor;
528 
529 enum { CURSOR_DEFAULT = 0, CURSOR_HOVER, CURSOR_HIDDEN, CURSOR_MAX };
530 
531 namespace UI
532 {
533     extern int uihidden, cursortype;
534     extern char *uiopencmd, *uiclosecmd;
535     extern bool showui(const char *name);
536     extern bool hideui(const char *name);
537     extern bool toggleui(const char *name);
538 
539     extern int openui(const char *name);
540     extern int closeui(const char *name);
541 
542     extern void holdui(const char *name, bool on);
543     extern void pressui(const char *name, bool on);
544     extern bool uivisible(const char *name);
545     extern bool hasinput();
546     extern bool hasmenu(bool pass = true);
547     extern bool keypress(int code, bool isdown);
548     extern bool textinput(const char *str, int len);
549 
550     extern void setup();
551     extern void update();
552     extern void render();
553     extern void cleanup();
554 }
555 
556 // menus
557 extern void addchange(const char *desc, int type);
558 extern void clearchanges(int type);
559 
560 // client
561 enum { ST_EMPTY, ST_LOCAL, ST_TCPIP, ST_REMOTE };
562 
563 struct clientdata
564 {
565     int type;
566     int num;
567     ENetPeer *peer;
568     string hostip;
569     void *info;
570 };
571 
572 extern void process(ENetPacket *packet, int sender, int chan);
573 extern void delclient(int n);
574 extern int addclient(int type = ST_EMPTY);
575 extern ENetHost *serverhost;
576 
577 // world
578 
579 extern int collideinside;
580 extern physent *collideplayer;
581 extern int collidezones;
582 extern vec collidewall, hitsurface;
583 
584 enum { CLZ_NONE = 0, CLZ_HEAD = 1<<0, CLZ_TORSO = 1<<1, CLZ_LIMB = 1<<2 };
585 
586 enum
587 {
588     MATF_INDEX_SHIFT  = 0,
589     MATF_VOLUME_SHIFT = 2,
590     MATF_CLIP_SHIFT   = 5,
591     MATF_FLAG_SHIFT   = 8,
592 
593     MATF_INDEX  = 3 << MATF_INDEX_SHIFT,
594     MATF_VOLUME = 7 << MATF_VOLUME_SHIFT,
595     MATF_CLIP   = 7 << MATF_CLIP_SHIFT,
596     MATF_FLAGS  = 0xFF << MATF_FLAG_SHIFT
597 };
598 
599 enum // cube empty-space materials
600 {
601     MAT_AIR   = 0,                      // the default, fill the empty space with air
602     MAT_WATER = 1 << MATF_VOLUME_SHIFT, // fill with water, showing waves at the surface
603     MAT_LAVA  = 2 << MATF_VOLUME_SHIFT, // fill with lava
604     MAT_GLASS = 3 << MATF_VOLUME_SHIFT, // behaves like clip but is blended blueish
605 
606     MAT_NOCLIP = 1 << MATF_CLIP_SHIFT,  // collisions always treat cube as empty
607     MAT_CLIP   = 2 << MATF_CLIP_SHIFT,  // collisions always treat cube as solid
608     MAT_AICLIP = 3 << MATF_CLIP_SHIFT,  // clip waypoints etc
609 
610     MAT_DEATH  = 1 << MATF_FLAG_SHIFT,  // force player suicide
611     MAT_LADDER = 2 << MATF_FLAG_SHIFT,  // acts as ladder (move up/down)
612     MAT_ALPHA  = 4 << MATF_FLAG_SHIFT,  // alpha blended
613     MAT_HURT   = 8 << MATF_FLAG_SHIFT,  // hurt at intervals
614     MAT_NOGI   = 16 << MATF_FLAG_SHIFT  // disable global illumination FIXME
615 };
616