1 /*
2
3 Client DLL functions. (New to r1q2). The client dll is a separate project that exports
4 a bunch of stuff that the client engine can hook up to to manipulate local entities and
5 in some way manipulate the renderer too... example:
6
7 Server sends event X on a dead body, client parses event x in normal entity parsing.
8 Event x is unhandled by the client, so it passes it on to the client DLL which could
9 do one of several things such as spawn local ents, create decals in the renderer, etc.
10
11 The interface between the client DLL and the engine/renderer is (attempted) to be
12 controlled from this file.
13
14 Eventually, most of the constants in the client parsing system should end up in
15 the client dll, for example, all tempents should be done via the client dll. A generic
16 dll will be supplied with r1q2 that maintains all the functionality of the default
17 engine - ie it can be dropped into any mod dir to emulate the functions that would
18 have been in the exe.
19
20 */
21
22 //shared by the client_dll project
23 #ifdef CLIENT_DLL
24 #include "client.h"
25 #include "../win32/winquake.h"
26
27 HINSTANCE cllib_library; // Handle to client DLL
28 qboolean cllib_active = false;
29 clexport_t ce;
30
31 /*
32 ==========
33 CL_FreeCllib
34 ==========
35 Unload the client dll and nuke anything it allocated.
36 */
CL_FreeCllib(void)37 void CL_FreeCllib (void)
38 {
39 if ( !FreeLibrary( cllib_library ) )
40 Com_Error( ERR_FATAL, "Cllib FreeLibrary failed" );
41
42 memset (&ce, 0, sizeof(ce));
43
44 //nuke anything the DLL allocated
45 Z_FreeTags (TAGMALLOC_CLIENT_DLL);
46
47 cllib_library = NULL;
48 cllib_active = false;
49 }
50
51 /*
52 ===========
53 CL_Z_Alloc
54 ===========
55 Allocate memory to the client DLL via Z_TagMalloc (but without the DLL
56 having to specify the tag) - used to free it all when the DLL is unloaded
57 above.
58 */
CL_Z_Alloc(int size)59 void *CL_Z_Alloc (int size)
60 {
61 return (void *)Z_TagMalloc (size, TAGMALLOC_CLIENT_DLL);
62 }
63
64 /*
65 ===========
66 CL_InitClientDLL
67 ===========
68 Attempt to load the dll, send it the exports and grab the imports.
69 */
CL_InitClientDLL(void)70 qboolean CL_InitClientDLL (void)
71 {
72 char name[MAX_OSPATH];
73 GetClAPI_t GetClAPI;
74 climport_t ci;
75
76 Com_sprintf (name, sizeof(name), "%s/client_dll.dll", FS_Gamedir());
77
78 if ( cllib_active )
79 {
80 ce.Shutdown();
81 CL_FreeCllib ();
82 }
83
84 Com_Printf( "------ Loading client_dll.dll ------\n", LOG_CLIENT);
85
86 if ( ( cllib_library = LoadLibrary( name ) ) == 0 )
87 {
88 Com_Printf( "LoadLibrary(\"%s\") failed\n", LOG_CLIENT, name );
89 return false;
90 }
91
92 if ( ( GetClAPI = (GetClAPI_t)GetProcAddress( cllib_library, "GetClAPI" ) ) == 0 ) {
93 Com_Printf("GetProcAddress failed on %s\n", LOG_CLIENT, name );
94 return false;
95 }
96
97 ci.MSG_ReadChar = MSG_ReadChar;
98 ci.MSG_ReadByte = MSG_ReadByte;
99 ci.MSG_ReadShort = MSG_ReadShort;
100 ci.MSG_ReadLong = MSG_ReadLong;
101 ci.MSG_ReadFloat = MSG_ReadFloat;
102 ci.MSG_ReadString = MSG_ReadString;
103 ci.MSG_ReadStringLine = MSG_ReadStringLine;
104
105 ci.MSG_ReadCoord= MSG_ReadCoord;
106 ci.MSG_ReadPos = MSG_ReadPos;
107 ci.MSG_ReadAngle = MSG_ReadAngle;
108 ci.MSG_ReadAngle16 = MSG_ReadAngle16;
109
110 ci.MSG_ReadDir = MSG_ReadDir;
111 ci.MSG_ReadData = MSG_ReadData;
112
113 ci.Cmd_AddCommand = Cmd_AddCommand;
114 ci.Cmd_RemoveCommand = Cmd_RemoveCommand;
115
116 ci.Cmd_Argc = Cmd_Argc;
117 ci.Cmd_Argv = Cmd_Argv;
118
119 ci.Cmd_ExecuteText = Cbuf_ExecuteText;
120
121 ci.Com_Printf = Com_Printf;
122 ci.Com_Error = Com_Error;
123
124 ci.FS_LoadFile = FS_LoadFile;
125 ci.FS_FreeFile = FS_FreeFile;
126 ci.FS_Gamedir = FS_Gamedir;
127
128 ci.Z_Alloc = CL_Z_Alloc;
129 ci.Z_Free = Z_Free;
130
131 ci.Cvar_Get = Cvar_Get;
132 ci.Cvar_Set = Cvar_Set;
133 ci.Cvar_SetValue = Cvar_SetValue;
134
135 ce = GetClAPI( ci );
136
137 switch (ce.api_version) {
138 case 1:
139 break;
140 default:
141 CL_FreeCllib ();
142 Com_Printf (PRODUCTNAME " doesn't support your client dll version (%s)\n", LOG_CLIENT, name);
143 return false;
144 }
145
146 if ( ce.Init( global_hInstance ) == -1 )
147 {
148 ce.Shutdown();
149 CL_FreeCllib ();
150 return false;
151 }
152
153 Com_Printf( "------------------------------------\n", LOG_CLIENT);
154 cllib_active = true;
155
156 return true;
157 }
158
159 /*
160 =============
161 CL_ClDLL_Restart_f
162 =============
163 (Re)load the client dll after switching games.
164 */
CL_ClDLL_Restart_f(void)165 void CL_ClDLL_Restart_f (void)
166 {
167 if (!CL_InitClientDLL ()) {
168 Com_Printf( "------------------------------------\n", LOG_CLIENT);
169 }
170 }
171 #endif
172