nuclide/src/shared/materials.qc

237 lines
6.3 KiB
Plaintext

/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* general purpose functions to interact with the material system */
static void
Materials_LoadFromText(string filename)
{
#if 0
filestream fileMaterial;
string sTemp;
string mat_type;
string tex_name;
fileMaterial = fopen(filename, FILE_READ);
if (fileMaterial >= 0) {
//print(strcat("parsing material assignments from ", filename,"\n"));
while ((sTemp = fgets(fileMaterial))) {
/* tokenize and just parse this stuff in */
if (tokenize_console(sTemp) == 2) {
mat_type = strtoupper(argv(0));
tex_name = Materials_FixName(strtolower(argv(1)));
hash_add(g_hashMaterials, tex_name, str2chr(mat_type, 0), EV_STRING);
}
}
fclose(fileMaterial);
} else {
dprint(strcat("^1Failed to load ", filename,"!\n"));
}
#endif
}
static void
Materials_LoadFromMat(string filename)
{
filestream fileMaterial;
string sTemp;
string materialname = substring(filename, 0, -5);
string extension = substring(filename, strlen(filename) - 3, 3);
string command, parameters;
fileMaterial = fopen(filename, FILE_READ);
/* load the .mat and find which material we're supposed to be using */
if (fileMaterial >= 0) {
while ((sTemp = fgets(fileMaterial))) {
/* tokenize and just parse this stuff in */
if (tokenize_console(sTemp) == 2) {
command = strtolower(argv(0));
parameters = argv(1);
if (command == "surfaceprop") {
hash_add(g_hashMaterials, materialname, parameters, EV_STRING);
//print(sprintf("added Material %S type %S\n", materialname, parameters));
break;
}
}
}
fclose(fileMaterial);
}
}
/** FIXME: all this should be done exclusively in surfaceproperties.qc, however that
is currently server-side only. Make it shared and then we can get rid of this
whole file! */
/** loads a temporary mapper so we can map letters to class names. */
static void
Materials_Mapper_Init(void)
{
string sTemp;
int c = 0;
filestream fileLUT;
string spname;
bool inbrace = false;
fileLUT = fopen("scripts/surfaceproperties.txt", FILE_READ);
g_hlmlut_count = 0;
/* count valid entries. */
if (fileLUT >= 0) {
while ((sTemp = fgets(fileLUT))) {
if (tokenize_console(sTemp) == 2) {
if (argv(0) == "gamematerial")
g_hlmlut_count++;
}
}
}
/* back to the beginning... */
fseek(fileLUT, 0);
g_hlmlut = memalloc(sizeof(hlmaterials_lut) * g_hlmlut_count);
/* read in the elements */
if (fileLUT >= 0) {
while ((sTemp = fgets(fileLUT))) {
/* tokenize and just parse this stuff in */
if (tokenize_console(sTemp) == 2) {
if (argv(0) == "gamematerial") {
g_hlmlut[c].id = argv(1);
g_hlmlut[c].matclass = spname;
c++;
}
}
if (argv(0) == "{")
inbrace = true;
else if (argv(0) == "}")
inbrace = false;
else if (inbrace == false)
spname = argv(0);
}
}
}
/** takes a mat id and returns a classname */
static string
Materials_Mapper_Lookup(string character)
{
int i;
for (i = 0; i < g_hlmlut_count; i++)
if (g_hlmlut[i].id == character)
return g_hlmlut[i].matclass;
return __NULL__;
}
/** unallocates the mapper */
static void
Materials_Mapper_Shutdown(void)
{
g_hlmlut_count = 0;
memfree(g_hlmlut);
}
/** loads a materials.txt type file into our hashtable. */
static void
Materials_LoadFromLegacyText(string filename)
{
filestream fileMaterial;
string sTemp;
string mat_type;
string tex_name;
fileMaterial = fopen(filename, FILE_READ);
if (fileMaterial >= 0) {
//print(strcat("parsing material definitions from ", filename,"\n"));
while ((sTemp = fgets(fileMaterial))) {
/* tokenize and just parse this stuff in */
if (tokenize_console(sTemp) == 2) {
mat_type = Materials_Mapper_Lookup(strtoupper(argv(0)));
tex_name = Materials_FixName(strtolower(argv(1)));
hash_add(g_hashMaterials, tex_name, mat_type, EV_STRING);
///print(sprintf("hlmaterial: %S %S\n", tex_name, mat_type));
g_hlmaterial_entries++;
}
}
fclose(fileMaterial);
} else {
dprint(strcat("^1Failed to load ", filename,"!\n"));
}
}
/** Initialize our material backbone */
void
Materials_Init(void)
{
g_hashMaterials = __NULL__;
g_hashMaterials = hash_createtab(2, EV_STRING | HASH_REPLACE);
/* save away the type of material formats we're dealing with */
switch (serverkeyfloat("*bspversion")) {
case BSPVER_Q3: /* Q3 */
case BSPVER_RTCW: /* RtCW */
case BSPVER_RBSP: /* RFVBSP */
g_materialsAreLegacy = false;
break;
case BSPVER_HL:
default:
g_materialsAreLegacy = true;
}
/* we're dealing with legacy materials */
if (g_materialsAreLegacy) {
/* prepare the mapper */
Materials_Mapper_Init();
/* the base definition, every GoldSrc game has this */
Materials_LoadFromLegacyText("sound/materials.txt");
/* Sven Coop 5.0 loads it from a worldspawn key */
if (world.materials_file)
Materials_LoadFromLegacyText(world.materials_file);
/* search through our sound dir for material definitions */
searchhandle pm;
pm = search_begin("sound/materials_*.txt", TRUE, TRUE);
for (int i = 0; i < search_getsize(pm); i++) {
Materials_LoadFromLegacyText(search_getfilename(pm, i));
}
search_end(pm);
/* the way TW did it back in '03 */
Materials_LoadFromLegacyText(sprintf("maps/%s.mat", mapname));
/* Trinity-Renderer does it this way */
Materials_LoadFromLegacyText(sprintf("maps/%s_materials.txt", mapname));
/* no longer needed! */
Materials_Mapper_Shutdown();
} else {
/* iterate through our mat files */
searchhandle searchy = search_begin("textures/*/*.mat", SEARCH_NAMESORT, TRUE);
for (int i = 0; i < search_getsize(searchy); i++) {
Materials_LoadFromMat(search_getfilename(searchy, i));
}
}
}