#ifndef __PLUGIN_H__ #define __PLUGIN_H__ #ifdef FTEENGINE //included from fte itself, to borrow typedefs #elif defined(FTEPLUGIN) //plugin that needs fte internals #include "quakedef.h" #else //moderately generic plugin #ifdef __cplusplus typedef enum {qfalse, qtrue} qboolean; #else typedef enum {qfalse, qtrue} qboolean; #define false qfalse #define true qtrue #endif typedef float vec3_t[3]; typedef unsigned char qbyte; #include #define quint64_t uint64_t typedef quint64_t qofs_t; typedef struct cvar_s cvar_t; typedef struct usercmd_s usercmd_t; typedef struct vfsfile_s vfsfile_t; typedef struct netadr_s netadr_t; enum fs_relative; struct searchpathfuncs_s; #endif #ifdef _WIN32 # ifndef strcasecmp # define strcasecmp stricmp # define strncasecmp strnicmp # endif # if defined(_MSC_VER) && _MSC_VER >= 1900 # define Q_vsnprintf vsnprintf # define Q_snprintf snprintf # endif #else # define stricmp strcasecmp # define strnicmp strncasecmp #endif #include #include #include #include #include #ifndef _VM_H #if __STDC_VERSION__ >= 199901L || defined(__GNUC__) //C99 has a stdint header which hopefully contains an intptr_t //its optional... but if its not in there then its unlikely you'll actually be able to get the engine to a stage where it *can* load anything #include #define qintptr_t intptr_t #define quintptr_t uintptr_t #else #ifdef _WIN64 typedef long long qintptr_t; typedef unsigned long long quintptr_t; #else #if !defined(_MSC_VER) || _MSC_VER < 1300 #define __w64 #endif typedef long __w64 qintptr_t; typedef unsigned long __w64 quintptr_t; #endif #endif #endif #ifndef NATIVEEXPORT #ifdef _WIN32 #define NATIVEEXPORTPROTO __declspec(dllexport) #define NATIVEEXPORT NATIVEEXPORTPROTO #else #define NATIVEEXPORTPROTO #define NATIVEEXPORT __attribute__((visibility("default"))) #endif #endif #ifdef __cplusplus extern "C" { #endif //DLLs need a wrapper to add the extra parameter and call a boring function. #ifndef QDECL #ifdef _WIN32 #define QDECL __cdecl #else #define QDECL #endif #endif #ifndef LIKEPRINTF #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) #define LIKEPRINTF(x) __attribute__((format(printf,x,x+1))) #else #define LIKEPRINTF(x) #endif #endif #ifndef NATIVEEXPORT #define NATIVEEXPORT QDECL #endif typedef int qhandle_t; typedef void* funcptr_t; #define PLUGMAX_SCOREBOARDNAME 64 typedef struct { int topcolour; int bottomcolour; int frags; char name[PLUGMAX_SCOREBOARDNAME]; int ping; int pl; int activetime; int userid; int spectator; char userinfo[2048]; char team[64]; } plugclientinfo_t; typedef struct { unsigned int client; unsigned int items; float armor; float health; vec3_t org; char nick[16]; } teamplayerinfo_t; typedef struct { size_t structsize; int seats; struct { float s_avg; float s_mn; float s_mx; float ms_stddev; //calculated in milliseconds for more sane numbers float fr_avg; int fr_mn; int fr_mx; } ping; struct { //decimals float dropped; float choked; float invalid; } loss; float mlatency; float mrate; float vlatency; float vrate; vec3_t speed; //player speed struct { float in_pps; float in_bps; float out_pps; float out_bps; } clrate; struct { float in_pps; float in_bps; float out_pps; float out_bps; } svrate; int capturing; //avi capturing } plugnetinfo_t; struct wstats_s; #define F(t, n, args) t (QDECL *n) args #define dllhandle_t void struct dllfunction_s; typedef struct //core stuff { //Basic builtins: F(void*, GetEngineInterface, (const char *interfacename, size_t structsize)); //retrieve a named interface struct from the engine F(qboolean, ExportFunction, (const char *funcname, funcptr_t funcptr)); //export a named function to the engine F(qboolean, ExportInterface, (const char *interfacename, void *interfaceptr, size_t structsize)); //export a named interface struct to the engine F(qboolean, GetPluginName, (int plugnum, char *buffer, size_t bufsize)); //query loaded plugin names. -1 == active plugin F(void, Print, (const char *message)); //print on (main) console. F(void, Error, (const char *message)); //abort the entire engine. F(quintptr_t,GetMilliseconds, (void)); F(dllhandle_t*,LoadDLL, (const char *modulename, struct dllfunction_s *funcs)); F(void*, GetDLLSymbol, (dllhandle_t *handle, const char *symbolname)); F(void, CloseDLL, (dllhandle_t *handle)); //not guarenteed to actually do anything, of course. //general memory (mallocs and frees over dll boundaries is not usable on windows) F(void*, Malloc, (size_t size)); F(void*, Realloc, (void *memptr, size_t size)); //doesn't zero-fill, so faster (when memptr is NULL). F(void, Free, (void *memptr)); //for lazy mallocs F(void*, GMalloc, (struct zonegroup_s *ctx, size_t size)); F(void, GFreeAll, (struct zonegroup_s *ctx)); #define plugcorefuncs_name "Core" } plugcorefuncs_t; typedef struct //subconsole handling { F(qhandle_t,POpen, (const char *conname)); F(qboolean, SubPrint, (const char *subname, const char *text)); //on to sub console. F(qboolean, RenameSub, (const char *oldname, const char *newname)); //rename a console. F(qboolean, IsActive, (const char *conname)); F(qboolean, SetActive, (const char *conname)); F(qboolean, Destroy, (const char *conname)); F(qboolean, NameForNum, (qintptr_t connum, char *conname, size_t connamelen)); F(float, GetConsoleFloat, (const char *conname, const char *attribname)); F(qboolean, SetConsoleFloat, (const char *conname, const char *attribname, float newvalue)); F(qboolean, GetConsoleString, (const char *conname, const char *attribname, char *outvalue, size_t valuesize)); F(qboolean, SetConsoleString, (const char *conname, const char *attribname, const char *newvalue)); #define plugsubconsolefuncs_name "SubConsole" } plugsubconsolefuncs_t; enum com_tokentype_e; typedef struct //console command/tokenizing/cbuf functions { F(const char *,QuotedString, (const char *string, char *buf, int buflen, qboolean omitquotes)); //generates a string with c-style markup and relevant quote types. F(char *, ParseToken, (const char *data, char *token, size_t tokenlen, enum com_tokentype_e *tokentype)); //standard quake-style token parsing. F(char *, ParsePunctuation, (const char *data, const char *punctuation, char *token, size_t tokenlen, enum com_tokentype_e *tokentype)); //use explicit punctuation. F(void, TokenizeString, (const char *msg)); //tokenize a string. F(void, Args, (char *buffer, int bufsize)); //Gets the extra args F(void, Argv, (int argnum, char *buffer, size_t bufsize)); //Gets a 0-based token F(int, Argc, (void)); //gets the number of tokens available. F(qboolean, AddCommand, (const char *cmdname)); //Registers a console command. F(void, AddText, (const char *text, qboolean insert)); #define plugcmdfuncs_name "Cmd" } plugcmdfuncs_t; typedef struct //console command and cbuf functions { F(void, SetString, (const char *name, const char *value)); F(void, SetFloat, (const char *name, float value)); F(qboolean, GetString, (const char *name, char *retstring, quintptr_t sizeofretstring)); F(float, GetFloat, (const char *name)); F(qhandle_t,Register, (const char *name, const char *defaultval, int flags, const char *grouphint)); F(qboolean, Update, (qhandle_t handle, int *modificationcount, char *outstringv, size_t stringsize, float *outfloatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged. F(cvar_t*, GetNVFDG, (const char *name, const char *defaultval, unsigned int flags, const char *description, const char *groupname)); #define plugcvarfuncs_name "Cvar" } plugcvarfuncs_t; typedef struct { F(void, LocalSound, (const char *soundname, int channel, float volume)); F(void, RawAudio, (int sourceid, void *data, int speed, int samples, int channels, int width, float volume)); #define plugaudiofuncs_name "Audio" } plugaudiofuncs_t; typedef struct { F(void, BlockSizeForEncoding,(uploadfmt_t encoding, unsigned int *blockbytes, unsigned int *blockwidth, unsigned int *blockheight, unsigned int *blockdepth)); F(const char *,FormatName, (uploadfmt_t encoding)); #define plugimagefuncs_name "Image" } plugimagefuncs_t; typedef struct //q1 client/network info { F(int, GetStats, (int seat, unsigned int *stats, int maxstats)); F(void, GetPlayerInfo, (int seat, plugclientinfo_t *info)); F(size_t, GetNetworkInfo, (plugnetinfo_t *ni, size_t sizeofni)); F(size_t, GetLocalPlayerNumbers,(size_t firstseat, size_t numseats, int *playernums, int *spectracks)); F(void, GetLocationName, (const float *pos, char *outbuffer, size_t bufferlen)); F(qboolean, GetLastInputFrame, (int seat, usercmd_t *outcmd)); F(void, GetServerInfo, (char *info, size_t infolen)); F(void, SetUserInfo, (int seat, const char *key, const char *value)); //EBUILTIN(void, SCR_CenterPrint, (const char *s)); //FIXME: does this belong here? F(qboolean, MapLog_Query, (const char *packagename, const char *mapname, float *stats)); F(size_t, GetTeamInfo, (teamplayerinfo_t *clients, size_t maxclients, qboolean showenemies, int seat)); F(int, GetWeaponStats, (int player, struct wstats_s *result, size_t maxresults)); F(float, GetTrackerOwnFrags, (int seat, char *text, size_t textsize)); F(void, GetPredInfo, (int seat, vec3_t outvel)); #define plugclientfuncs_name "Client" } plugclientfuncs_t; typedef struct //for menu-like stuff { //for menus F(qboolean, SetMenuFocus, (qboolean wantkeyfocus, const char *cursorname, float hot_x, float hot_y, float scale)); //null cursorname=relmouse, set/empty cursorname=absmouse F(qboolean, HasMenuFocus, (void)); //for menu input F(int, GetKeyCode, (const char *keyname, int *out_modifier)); F(const char*,GetKeyName, (int keycode, int modifier)); F(int, FindKeysForCommand,(int bindmap, const char *command, int *out_keycodes, int *out_modifiers, int maxkeys)); F(const char*,GetKeyBind, (int bindmap, int keynum, int modifier)); F(void, SetKeyBind, (int bindmap, int keycode, int modifier, const char *newbinding)); unsigned int (*GetKeyDest) (void); void (*KeyEvent) (unsigned int devid, int down, int keycode, int unicode); void (*MouseMove) (unsigned int devid, int abs, float x, float y, float z, float size); void (*JoystickAxisEvent) (unsigned int devid, int axis, float value); void (*Accelerometer) (unsigned int devid, float x, float y, float z); void (*Gyroscope) (unsigned int devid, float pitch, float yaw, float roll); qboolean (*SetHandPosition) (const char *devname, vec3_t org, vec3_t ang, vec3_t vel, vec3_t avel); //for VR. #define pluginputfuncs_name "Input" } pluginputfuncs_t; typedef struct //for huds and menus alike { //note: these use handles instead of shaders, to make them persistent over renderer restarts. F(qhandle_t,LoadImageData, (const char *name, const char *mime, void *data, size_t datasize)); //load/replace a named texture F(qhandle_t,LoadImageShader,(const char *name, const char *defaultshader)); //loads a shader. F(qhandle_t,LoadImage, (const char *name, qboolean iswadimage)); //wad image is ONLY for loading out of q1 gfx.wad. loads a shader. F(void, UnloadImage, (qhandle_t image)); F(int, Image, (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image)); F(int, ImageSize, (qhandle_t image, float *x, float *y)); F(void, Fill, (float x, float y, float w, float h)); F(void, Line, (float x1, float y1, float x2, float y2)); F(void, Character, (float x, float y, unsigned int character)); F(void, String, (float x, float y, const char *string)); F(void, CharacterH, (float x, float y, float h, unsigned int flags, unsigned int character)); F(void, StringH, (float x, float y, float h, unsigned int flags, const char *string)); //returns the vpixel width of the (coloured) string, in the current (variable-width) font. F(float, StringWidth, (float h, unsigned int flags, const char *string)); F(void, Colourpa, (int palcol, float a)); //for legacy code F(void, Colour4f, (float r, float g, float b, float a)); F(void, LocalSound, (const char *soundname, int channel, float volume)); #define plug2dfuncs_name "2D" } plug2dfuncs_t; typedef struct //for plugins that need to read/write files... { F(int, Open, (const char *name, qhandle_t *handle, int mode)); F(void, Close, (qhandle_t handle)); F(int, Write, (qhandle_t handle, void *data, int len)); F(int, Read, (qhandle_t handle, void *data, int len)); F(int, Seek, (qhandle_t handle, qofs_t offset)); F(qboolean, GetLen, (qhandle_t handle, qofs_t *outsize)); F(vfsfile_t*,OpenVFS, (const char *filename, const char *mode, enum fs_relative relativeto)); //opens a direct vfs file, without any access checks, and so can be used in threaded plugins F(qboolean, NativePath, (const char *name, enum fs_relative relativeto, char *out, int outlen)); F(void, EnumerateFiles, (const char *match, int (QDECL *callback)(const char *fname, qofs_t fsize, time_t mtime, void *ctx, struct searchpathfuncs_s *package), void *ctx)); //helpers F(int, WildCmp, (const char *wild, const char *string)); F(const char *,GetExtension,(const char *filename, const char *ignoreext)); F(void, FileBase, (const char *in, char *out, int outlen)); F(void, CleanUpPath, (char *str)); F(unsigned int,BlockChecksum,(const void *buffer, int length)); //mostly for pack hashes. F(qbyte*, LoadFile, (const char *fname, size_t *fsize)); //plugfuncs->Free #define plugfsfuncs_name "Filesystem" } plugfsfuncs_t; typedef struct //for when you need basic socket access, hopefully rare... { F(qhandle_t,TCPConnect, (const char *ip, int port)); F(qhandle_t,TCPListen, (const char *localip, int port, int maxcount)); F(qhandle_t,Accept, (qhandle_t socket, char *address, int addresssize)); F(int, Recv, (qhandle_t socket, void *buffer, int len)); F(int, Send, (qhandle_t socket, void *buffer, int len)); F(int, SendTo, (qhandle_t handle, void *data, int datasize, netadr_t *dest)); F(void, Close, (qhandle_t socket)); F(int, SetTLSClient, (qhandle_t sock, const char *certhostname)); //adds a tls layer to the socket (and specifies the peer's required hostname) F(int, GetTLSBinding, (qhandle_t sock, char *outdata, int *datalen)); //to avoid MITM attacks with compromised cert authorities //for (d)tls plugins to use. F(qboolean, RandomBytes, (qbyte *string, int len)); F(void *, TLS_GetKnownCertificate, (const char *certname, size_t *size)); F(qboolean, CertLog_ConnectOkay, (const char *hostname, void *cert, size_t certsize, unsigned int certlogproblems)); #define N_WOULDBLOCK -1 #define N_FATALERROR -2 #define NET_CLIENTPORT -1 #define NET_SERVERPORT -2 #define plugnetfuncs_name "Net" } plugnetfuncs_t; #undef F extern plugcorefuncs_t *plugfuncs; extern plugcmdfuncs_t *cmdfuncs; extern plugcvarfuncs_t *cvarfuncs; #ifdef FTEENGINE extern plugcorefuncs_t plugcorefuncs; #else void Q_strlncpy(char *d, const char *s, int sizeofd, int lenofs); void Q_strlcpy(char *d, const char *s, int n); void Q_strlcat(char *d, const char *s, int n); qboolean VARGS Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr); qboolean VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...) LIKEPRINTF(3); #define Q_snprintf (void)Q_snprintfz #define Q_vsnprintf (void)Q_vsnprintfz char *va(const char *format, ...); qboolean Plug_Init(void); void Con_Printf(const char *format, ...); void Con_DPrintf(const char *format, ...); //not a particuarly efficient implementation, so beware. void Sys_Errorf(const char *format, ...); void QDECL Q_strncpyz(char *d, const char *s, int n); #define PLUG_SHARED_BEGIN(t,p,b) \ { \ t *p; \ char inputbuffer[8192]; \ *(b) = ReadInputBuffer(inputbuffer, sizeof(inputbuffer)); \ if (*(b)) \ p = (t*)inputbuffer; \ else \ p = NULL; #define PLUG_SHARED_END(p,b) UpdateInputBuffer(inputbuffer, b);} typedef struct { char *name; char string[256]; char *group; int flags; float value; qhandle_t handle; int modificationcount; } vmcvar_t; #define VMCvar_Register(cv) (cv->handle=cvarfuncs->Register(cv->name, cv->string, cv->flags, cv->group)) #define VMCvar_Update(cv) cvarfuncs->Update(handle, &cv->modcount, cv->string, sizeof(cv->string), &cv->value) #define VMCvar_SetString(c,v) \ do{ \ strcpy(c->string, v); \ c->value = (float)atof(v); \ Cvar_SetString(c->name, c->string); \ } while (0) #define VMCvar_SetFloat(c,v) \ do { \ snprintf(c->string, sizeof(c->string), "%f", v);\ c->value = (float)(v); \ Cvar_SetFloat(c->name, c->value); \ } while(0) \ char *Plug_Info_ValueForKey (const char *s, const char *key, char *out, size_t outsize); #endif #ifdef __cplusplus } #endif #endif