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
42 #define SAY(pEntity, text) {\
43 MESSAGE_BEGIN( MSG_ONE, GET_USER_MSG_ID(PLID, "SayText", NULL), NULL, pEntity );\
44 WRITE_BYTE( ENTINDEX(pEntity) );\
45 WRITE_STRING( text );\
49 extern char gGamedir
[];
52 #define MAXLENGTH_PLAYERNAME 64
53 #define MAXLENGTH_MODELNAME 64
54 #define MAXLENGTH_MODELPATH 256
56 char model
[MAXLENGTH_MODELPATH
];
57 char bmp
[MAXLENGTH_MODELPATH
];
61 char playername
[MAXLENGTH_PLAYERNAME
];
62 char modelname
[MAXLENGTH_MODELNAME
];
66 #define MAX_PRECACHE_COUNT 32
67 precache_entry precache_list
[MAX_PRECACHE_COUNT
];
68 unsigned short int precache_count
= 0;
70 bool fileExists(const char* path
) {
72 snprintf(fullpath
, sizeof(fullpath
), "%s/%s", &gGamedir
[0], path
);
73 return access(fullpath
, R_OK
) == 0;
76 bool addPrecacheEntry(const char* playername
, const char* model
) {
79 while ((i
< precache_count
) && ((streq
= strcmp(precache_list
[i
].modelname
, model
)) != 0)) i
++;
80 if ((i
== precache_count
) && (i
< MAX_PRECACHE_COUNT
) && (streq
!= 0)) {
81 strncpy(precache_list
[i
].playername
, playername
, MAXLENGTH_PLAYERNAME
- 1);
82 strncpy(precache_list
[i
].modelname
, model
, MAXLENGTH_MODELNAME
- 1);
83 // Ensure null-termination
84 precache_list
[i
].playername
[MAXLENGTH_PLAYERNAME
- 1] = 0;
85 precache_list
[i
].modelname
[MAXLENGTH_MODELNAME
- 1] = 0;
87 snprintf(precache_list
[i
].paths
.model
, MAXLENGTH_MODELPATH
, "models/player/%s/%s.mdl", model
, model
);
88 snprintf(precache_list
[i
].paths
.bmp
, MAXLENGTH_MODELPATH
, "models/player/%s/%s.bmp", model
, model
);
91 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
);
98 void ClientPutInServer( edict_t
*pEntity
) {
99 const char* playername
= STRING(pEntity
->v
.netname
);
100 char* modelname
= g_engfuncs
.pfnInfoKeyValue( g_engfuncs
.pfnGetInfoKeyBuffer( pEntity
), "model" );
102 snprintf(modelfile
, sizeof(modelfile
), "models/player/%s/%s.mdl", modelname
, modelname
);
103 LOG_MESSAGE(PLID
, "Player %s is using model %s", playername
, modelname
);
104 if (fileExists( modelfile
)) {
105 LOG_MESSAGE(PLID
, "Model %s is present on server", modelname
);
106 SAY(pEntity
, "Your model is present on the server, it will be precached for the next round!");
107 if (addPrecacheEntry( playername
, modelname
))
108 LOG_MESSAGE(PLID
, "Added model %s to precache list", modelname
);
110 LOG_MESSAGE(PLID
, "Model %s will not be precached - reduntant or precache list is full", modelname
);
113 LOG_MESSAGE(PLID
, "Unable to precache due to FILE MISSING: %s!", modelfile
);
114 SAY(pEntity
, "Your model is not present on the server, can't distribute for other players!");
116 RETURN_META(MRES_IGNORED
);
119 void ServerActivate(edict_t
*pEdictList
, int edictCount
, int clientMax
) {
121 LOG_MESSAGE(PLID
, "Precaching %d player models", precache_count
);
122 for (int i
= 0; i
< precache_count
; i
++) {
123 hasBMP
= fileExists(precache_list
[i
].paths
.bmp
);
124 LOG_MESSAGE(PLID
, "Precaching model %s: %s (contributed by %s)",
125 hasBMP
? "(with bmp)" : "(without bmp)",
126 precache_list
[i
].modelname
, precache_list
[i
].playername
);
127 g_engfuncs
.pfnPrecacheModel(precache_list
[i
].paths
.model
);
129 g_engfuncs
.pfnPrecacheGeneric(precache_list
[i
].paths
.bmp
);
132 RETURN_META(MRES_HANDLED
);
135 static DLL_FUNCTIONS gFunctionTable
=
146 NULL
, // pfnSetAbsBox
148 NULL
, // pfnSaveWriteFields
149 NULL
, // pfnSaveReadFields
151 NULL
, // pfnSaveGlobalState
152 NULL
, // pfnRestoreGlobalState
153 NULL
, // pfnResetGlobalState
155 NULL
, // pfnClientConnect
156 NULL
, // pfnClientDisconnect
157 NULL
, // pfnClientKill
158 ClientPutInServer
, // pfnClientPutInServer
159 NULL
, // pfnClientCommand
160 NULL
, // pfnClientUserInfoChanged
161 ServerActivate
, // pfnServerActivate
162 NULL
, // pfnServerDeactivate
164 NULL
, // pfnPlayerPreThink
165 NULL
, // pfnPlayerPostThink
167 NULL
, // pfnStartFrame
168 NULL
, // pfnParmsNewLevel
169 NULL
, // pfnParmsChangeLevel
171 NULL
, // pfnGetGameDescription
172 NULL
, // pfnPlayerCustomization
174 NULL
, // pfnSpectatorConnect
175 NULL
, // pfnSpectatorDisconnect
176 NULL
, // pfnSpectatorThink
178 NULL
, // pfnSys_Error
182 NULL
, // pfnPM_FindTextureType
184 NULL
, // pfnSetupVisibility
185 NULL
, // pfnUpdateClientData
186 NULL
, // pfnAddToFullPack
187 NULL
, // pfnCreateBaseline
188 NULL
, // pfnRegisterEncoders
189 NULL
, // pfnGetWeaponData
192 NULL
, // pfnConnectionlessPacket
193 NULL
, // pfnGetHullBounds
194 NULL
, // pfnCreateInstancedBaselines
195 NULL
, // pfnInconsistentFile
196 NULL
, // pfnAllowLagCompensation
199 C_DLLEXPORT
int GetEntityAPI2(DLL_FUNCTIONS
*pFunctionTable
,
200 int *interfaceVersion
)
202 if(!pFunctionTable
) {
203 UTIL_LogPrintf("GetEntityAPI2 called with null pFunctionTable");
206 else if(*interfaceVersion
!= INTERFACE_VERSION
) {
207 UTIL_LogPrintf("GetEntityAPI2 version mismatch; requested=%d ours=%d", *interfaceVersion
, INTERFACE_VERSION
);
208 //! Tell metamod what version we had, so it can figure out who is out of date.
209 *interfaceVersion
= INTERFACE_VERSION
;
212 memcpy(pFunctionTable
, &gFunctionTable
, sizeof(DLL_FUNCTIONS
));