5 * Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
7 * This file is part of Metamod.
9 * Metamod is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
14 * Metamod is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with Metamod; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * In addition, as a special exception, the author gives permission to
24 * link the code of this program with the Half-Life Game Engine ("HL
25 * Engine") and Modified Game Libraries ("MODs") developed by Valve,
26 * L.L.C ("Valve"). You must obey the GNU General Public License in all
27 * respects for all of the code used other than the HL Engine and MODs
28 * from Valve. If you modify this file, you may extend this exception
29 * to your version of the file, but you are not obligated to do so. If
30 * you do not wish to do so, delete this exception statement from your
40 #define SAY(pEntity, text) {\
41 MESSAGE_BEGIN( MSG_ONE, GET_USER_MSG_ID(PLID, "SayText", NULL), NULL, pEntity );\
42 WRITE_BYTE( ENTINDEX(pEntity) );\
43 WRITE_STRING( text );\
47 extern char gGamedir
[];
50 #define MAXLENGTH_PLAYERNAME 64
51 #define MAXLENGTH_MODELNAME 64
52 #define MAXLENGTH_MODELPATH 256
54 char model
[MAXLENGTH_MODELPATH
];
55 char bmp
[MAXLENGTH_MODELPATH
];
59 char playername
[MAXLENGTH_PLAYERNAME
];
60 char modelname
[MAXLENGTH_MODELNAME
];
64 #define MAX_PRECACHE_COUNT 32
65 precache_entry precache_list
[MAX_PRECACHE_COUNT
];
66 unsigned short int precache_count
= 0;
68 bool fileExists(char* path
) {
69 return g_engfuncs
.pfnGetFileSize(path
) != -1;
72 bool addPrecacheEntry(const char* playername
, const char* model
) {
75 while ((i
< precache_count
) && ((streq
= strcmp(precache_list
[i
].modelname
, model
)) != 0)) i
++;
76 if ((i
== precache_count
) && (i
< MAX_PRECACHE_COUNT
) && (streq
!= 0)) {
77 strncpy(precache_list
[i
].playername
, playername
, MAXLENGTH_PLAYERNAME
- 1);
78 strncpy(precache_list
[i
].modelname
, model
, MAXLENGTH_MODELNAME
- 1);
79 // Ensure null-termination
80 precache_list
[i
].playername
[MAXLENGTH_PLAYERNAME
- 1] = 0;
81 precache_list
[i
].modelname
[MAXLENGTH_MODELNAME
- 1] = 0;
83 snprintf(precache_list
[i
].paths
.model
, MAXLENGTH_MODELPATH
, "models/player/%s/%s.mdl", model
, model
);
84 snprintf(precache_list
[i
].paths
.bmp
, MAXLENGTH_MODELPATH
, "models/player/%s/%s.bmp", model
, model
);
87 LOG_MESSAGE(PLID
, "Precache entry %d: playername=\"%s\" modelname=\"%s\" paths.model=\"%s\" paths.bmp=\"%s\"", i
, precache_list
[i
].playername
, precache_list
[i
].modelname
, precache_list
[i
].paths
.model
, precache_list
[i
].paths
.bmp
);
94 void ClientPutInServer( edict_t
*pEntity
) {
95 const char* playername
= STRING(pEntity
->v
.netname
);
96 char* modelname
= g_engfuncs
.pfnInfoKeyValue( g_engfuncs
.pfnGetInfoKeyBuffer( pEntity
), "model" );
98 snprintf(modelfile
, sizeof(modelfile
), "models/player/%s/%s.mdl", modelname
, modelname
);
99 LOG_MESSAGE(PLID
, "Player %s is using model %s", playername
, modelname
);
100 if (fileExists( modelfile
)) {
101 LOG_MESSAGE(PLID
, "Model %s is present on server", modelname
);
102 SAY(pEntity
, "Your model is present on the server, it will be precached for the next round!");
103 if (addPrecacheEntry( playername
, modelname
))
104 LOG_MESSAGE(PLID
, "Added model %s to precache list", modelname
);
106 LOG_MESSAGE(PLID
, "Model %s will not be precached - reduntant or precache list is full", modelname
);
109 LOG_MESSAGE(PLID
, "Unable to precache due to FILE MISSING: %s!", modelfile
);
110 SAY(pEntity
, "Your model is not present on the server, can't distribute for other players!");
112 RETURN_META(MRES_IGNORED
);
115 void ServerActivate(edict_t
*pEdictList
, int edictCount
, int clientMax
) {
117 LOG_MESSAGE(PLID
, "Precaching %d player models", precache_count
);
118 for (int i
= 0; i
< precache_count
; i
++) {
119 hasBMP
= fileExists(precache_list
[i
].paths
.bmp
);
120 LOG_MESSAGE(PLID
, "Precaching model %s: %s (contributed by %s)",
121 hasBMP
? "(with bmp)" : "(without bmp)",
122 precache_list
[i
].modelname
, precache_list
[i
].playername
);
123 g_engfuncs
.pfnPrecacheModel(precache_list
[i
].paths
.model
);
125 g_engfuncs
.pfnPrecacheGeneric(precache_list
[i
].paths
.bmp
);
128 RETURN_META(MRES_HANDLED
);
131 static DLL_FUNCTIONS gFunctionTable
=
142 NULL
, // pfnSetAbsBox
144 NULL
, // pfnSaveWriteFields
145 NULL
, // pfnSaveReadFields
147 NULL
, // pfnSaveGlobalState
148 NULL
, // pfnRestoreGlobalState
149 NULL
, // pfnResetGlobalState
151 NULL
, // pfnClientConnect
152 NULL
, // pfnClientDisconnect
153 NULL
, // pfnClientKill
154 ClientPutInServer
, // pfnClientPutInServer
155 NULL
, // pfnClientCommand
156 NULL
, // pfnClientUserInfoChanged
157 ServerActivate
, // pfnServerActivate
158 NULL
, // pfnServerDeactivate
160 NULL
, // pfnPlayerPreThink
161 NULL
, // pfnPlayerPostThink
163 NULL
, // pfnStartFrame
164 NULL
, // pfnParmsNewLevel
165 NULL
, // pfnParmsChangeLevel
167 NULL
, // pfnGetGameDescription
168 NULL
, // pfnPlayerCustomization
170 NULL
, // pfnSpectatorConnect
171 NULL
, // pfnSpectatorDisconnect
172 NULL
, // pfnSpectatorThink
174 NULL
, // pfnSys_Error
178 NULL
, // pfnPM_FindTextureType
180 NULL
, // pfnSetupVisibility
181 NULL
, // pfnUpdateClientData
182 NULL
, // pfnAddToFullPack
183 NULL
, // pfnCreateBaseline
184 NULL
, // pfnRegisterEncoders
185 NULL
, // pfnGetWeaponData
188 NULL
, // pfnConnectionlessPacket
189 NULL
, // pfnGetHullBounds
190 NULL
, // pfnCreateInstancedBaselines
191 NULL
, // pfnInconsistentFile
192 NULL
, // pfnAllowLagCompensation
195 C_DLLEXPORT
int GetEntityAPI2(DLL_FUNCTIONS
*pFunctionTable
,
196 int *interfaceVersion
)
198 if(!pFunctionTable
) {
199 UTIL_LogPrintf("GetEntityAPI2 called with null pFunctionTable");
202 else if(*interfaceVersion
!= INTERFACE_VERSION
) {
203 UTIL_LogPrintf("GetEntityAPI2 version mismatch; requested=%d ours=%d", *interfaceVersion
, INTERFACE_VERSION
);
204 //! Tell metamod what version we had, so it can figure out who is out of date.
205 *interfaceVersion
= INTERFACE_VERSION
;
208 memcpy(pFunctionTable
, &gFunctionTable
, sizeof(DLL_FUNCTIONS
));