From 5e799823af89b3574aa47f536f1b779d16bd5b1e Mon Sep 17 00:00:00 2001 From: cypress Date: Sat, 6 Jan 2024 17:33:52 -0500 Subject: [PATCH] SERVER: Use generated hash table for model path conversion --- .gitignore | 1 + README.md | 2 + bin/qc_hash_generator.py | 176 +++++++++++ progs/fte-server.src | 1 + progs/standard.src | 1 + source/server/clientfuncs.qc | 3 +- source/server/defs/custom.qc | 2 + source/server/entities/map_entities.qc | 2 +- source/server/entities/pack_a_punch.qc | 6 +- source/server/main.qc | 315 +------------------ source/server/utilities/map_compatibility.qc | 66 +++- tools/asset_conversion_table.csv | 111 +++++++ tools/qc-compiler-lin.sh | 34 +- tools/qc-compiler-mac.sh | 34 +- tools/qc-compiler-win.bat | 31 +- 15 files changed, 400 insertions(+), 385 deletions(-) create mode 100644 bin/qc_hash_generator.py create mode 100644 tools/asset_conversion_table.csv diff --git a/.gitignore b/.gitignore index e3cf22d..509f920 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/* +source/server/hash_table.qc bin/fteqcc.log \ No newline at end of file diff --git a/README.md b/README.md index 7136dda..0c32c63 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ There are no prerequisites or dependancies needed to build QuakeC other than a w Before you can build the NZ:P QuakeC, you must either [download](https://github.com/nzp-team/quakec/archive/refs/heads/main.zip) this repository (easy) or [clone it](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) (for developers). +[Python](https://www.python.org/) 3.7 or above is required to execute additional required components for hash table generation. You can install the [required modules](https://raw.githubusercontent.com/nzp-team/QCHashTableGenerator/main/requirements.txt) with `pip -r requirements.txt` pointing to the provided file. + To build, simply navigate to the `tools` directory and run the `qc-compiler-*` script for your platform. If unfamiliar with executing shell (`.sh`) scripts on Linux systems, give this [itsFOSS article](https://itsfoss.com/run-shell-script-linux/) a read. After having done this, a `build` directory will have been created, and inside of it will be more directories named after every platform. Copy the contents of the platform directories into your `nzp` game directory. (Example: For PSP, copy `progs.dat` and `progs.lno` from `standard/handheld` to `PSP/GAME/nzportable/nzp`). diff --git a/bin/qc_hash_generator.py b/bin/qc_hash_generator.py new file mode 100644 index 0000000..cf38401 --- /dev/null +++ b/bin/qc_hash_generator.py @@ -0,0 +1,176 @@ +""" +Nazi Zombies: Portable QuakeC CRC generator + +Takes input .CSV files and outputs an FTEQCC-compilable +QuakeC struct with its contents, always assumes the first +entry should be IBM 3740 CRC16 hashed, adding its length +as an entry as well, for collision detection. +""" + +import argparse +import pandas +import sys +import os +from fastcrc import crc16 +from colorama import Fore, Style +from dataclasses import dataclass + +args = {} +struct_fields = [] +original_lengths = [] +original_names = [] + +COL_BLUE = Fore.BLUE +COL_RED = Fore.RED +COL_YEL = Fore.YELLOW +COL_GREEN = Fore.GREEN +COL_NONE = Style.RESET_ALL + +ITYPE_FLOAT = 0 +ITYPE_STRING = 1 +ITYPE_CRC = 2 + +@dataclass +class StructField: + ''' + Class for fields that are added to the QuakeC struct. + ''' + name: str + item_type: int = ITYPE_FLOAT + +def write_qc_file(csv_data): + ''' + Writes the data obtained into an FTEQCC-compilable + struct. + ''' + with open(args['output_file'], 'w') as output: + # Define the struct. + output.write('var struct {\n') + + # Write out all of it's types.. + for fields in struct_fields: + if fields.item_type == ITYPE_STRING: + output.write('string ') + else: + output.write('float ') + + output.write(f'{fields.name};\n') + + # Close the struct. + output.write('}') + + # Now, the name of it + struct_name = args['struct_name'] + output.write(f'{struct_name}[]=') + output.write('{\n') + + # We can begin writing the actual data.. + value_counter = 0 + for value in csv_data.values: + output.write('{') + entry_counter = 0 + for entry in value: + if struct_fields[entry_counter].item_type != ITYPE_STRING: + output.write(f'{str(entry)},') + else: + output.write(f'\"{entry}\",') + entry_counter += 1 + + # Write the length of the first entry + output.write(str(original_lengths[value_counter])) + + # Close entry, add comma if not the last.. + output.write('}') + if value_counter + 1 < len(csv_data.values): + output.write(',') + + # Leave comment referring to the unhashed-value + output.write(f' // {original_names[value_counter]}') + + output.write('\n') + + value_counter += 1 + + # End struct! + output.write('};\n') + +def create_qc_structfields(csv_data): + ''' + Parses the .CSV data to create new StructField + entries given the .CSV specific requirements. + ''' + global struct_fields + + column_count = 0 + for column in csv_data.columns: + # Assume first entry is what we always want + # to hash, append _crc to it, too. + if column_count == 0: + item_type = ITYPE_CRC + item_name = column + '_crc' + else: + item_type = ITYPE_STRING + item_name = column + struct_fields.append(StructField(item_name, item_type)) + column_count += 1 + + # Always append a field that will store the + # length of the unhashed-CRC. + struct_fields.append(StructField('crc_strlen', ITYPE_FLOAT)) + +def generate_qc_file(csv_data): + ''' + Calls for population of StructFields and prompts + for writing the .QC file output. + ''' + create_qc_structfields(csv_data) + write_qc_file(csv_data) + +def read_csv_data(): + ''' + Parses the input_file .CSV into a Pandas dictionary, + performs the hashing on the first indexes, and sorts + in ascending order. + ''' + global original_lengths, original_names + csv_data = pandas.read_csv(args['input_file']) + + # Grab every value and turn the first entry into a hash. + for value in csv_data.values: + original_lengths.append(len(value[0])) + original_names.append(value[0]) + value[0] = int(crc16.ibm_3740(str.encode(value[0]))) + + # Now order everything by ascending order + csv_data = csv_data.sort_values(csv_data.columns[0]) + original_lengths = [original_lengths[i] for i in csv_data.index] + original_names = [original_names[i] for i in csv_data.index] + + return csv_data + +def fetch_cli_arguments(): + ''' + Initiates ArgParser with all potential command line arguments. + ''' + global args + parser = argparse.ArgumentParser(description='IBM 3740 CRC16 hash generator in FTE QuakeC-readable data structure.') + parser.add_argument('-i', '--input-file', + help='.CSV input file to parse.', required=True) + parser.add_argument('-o', '--output-file', + help='File name for generated .QC file.', default='hashes.qc') + parser.add_argument('-n', '--struct-name', + help='Name of the struct generated.', default='asset_conversion_table') + args = vars(parser.parse_args()) + +def main(): + fetch_cli_arguments() + + if not os.path.isfile(args['input_file']): + print(f'{COL_RED}Error{COL_NONE}: Input .CSV file does not exist. Exiting.') + sys.exit() + + csv_data = read_csv_data() + generate_qc_file(csv_data) + +if __name__ == '__main__': + main() diff --git a/progs/fte-server.src b/progs/fte-server.src index 0eea243..f62dfd8 100644 --- a/progs/fte-server.src +++ b/progs/fte-server.src @@ -5,6 +5,7 @@ ../source/shared/weapon_defines.qc ../source/server/defs/custom.qc ../source/server/clientfuncs.qc +../source/server/hash_table.qc ../source/server/dummies.qc ../source/server/rounds.qc diff --git a/progs/standard.src b/progs/standard.src index e7b26b7..26e5900 100644 --- a/progs/standard.src +++ b/progs/standard.src @@ -7,6 +7,7 @@ ../source/shared/weapon_defines.qc ../source/server/defs/custom.qc ../source/server/clientfuncs.qc +../source/server/hash_table.qc ../source/server/non_fte_specifics.qc diff --git a/source/server/clientfuncs.qc b/source/server/clientfuncs.qc index 8f8b5ec..6ad4e74 100644 --- a/source/server/clientfuncs.qc +++ b/source/server/clientfuncs.qc @@ -24,7 +24,6 @@ Boston, MA 02111-1307, USA */ -string(string asset) convert_old_asset_path; void() NotifyGameEnd = { @@ -676,7 +675,7 @@ void(entity ent) Ent_FakeRemove = void(string modelname) Precache_Set = // Precache model, and set myself to it { - modelname = convert_old_asset_path(modelname); + modelname = Compat_ConvertOldAssetPath(modelname); precache_model(modelname); setmodel(self, modelname); }; diff --git a/source/server/defs/custom.qc b/source/server/defs/custom.qc index 12b0ce4..fa2ab34 100644 --- a/source/server/defs/custom.qc +++ b/source/server/defs/custom.qc @@ -244,6 +244,8 @@ void Set_W_Frame (float startframe, float endframe, float duration, float funcca .void() animend; .void(optional float t) animend2; +string(string path) Compat_ConvertOldAssetPath; + //Null functions void() SUB_Null = {}; void() SUB_Null2 = {}; diff --git a/source/server/entities/map_entities.qc b/source/server/entities/map_entities.qc index 752f299..44a3a22 100644 --- a/source/server/entities/map_entities.qc +++ b/source/server/entities/map_entities.qc @@ -348,7 +348,7 @@ void() place_model = self.classname = "place_model"; // Grab an updated model path. - self.model = convert_old_asset_path(self.model); + self.model = Compat_ConvertOldAssetPath(self.model); // Convert the VEC_HULL bounds to match mdlsz. self.mdlsz = '64 64 88'; diff --git a/source/server/entities/pack_a_punch.qc b/source/server/entities/pack_a_punch.qc index 4096adc..a2d4c55 100644 --- a/source/server/entities/pack_a_punch.qc +++ b/source/server/entities/pack_a_punch.qc @@ -407,9 +407,9 @@ void() perk_pap = self.oldmodel = "sounds/machines/packapunch/upgrade.wav"; } - self.model = convert_old_asset_path(self.model); - self.weapon2model = convert_old_asset_path(self.weapon2model); - self.door_model_name = convert_old_asset_path(self.door_model_name); + self.model = Compat_ConvertOldAssetPath(self.model); + self.weapon2model = Compat_ConvertOldAssetPath(self.weapon2model); + self.door_model_name = Compat_ConvertOldAssetPath(self.door_model_name); // Precaches // FIXME: Don't hardcode weapon precaches here. diff --git a/source/server/main.qc b/source/server/main.qc index 0fd2c65..add1a71 100644 --- a/source/server/main.qc +++ b/source/server/main.qc @@ -539,317 +539,4 @@ void() EndFrame = if (cheats_have_been_activated == false && cvar("sv_cheats") == 1) { cheats_have_been_activated = true; } -}; - -// -// convert_old_asset_path(asset) -// a large switch statement to convert asset paths made for -// older versions of nzp to the new standard -// -string(string asset) convert_old_asset_path = -{ - string lowered_asset = strzone(strtolower(asset)); - string ret = ""; - - switch(lowered_asset) { - case "progs/player.mdl": - ret = "models/player.mdl"; - break; - case "progs/ai/zal(.mdl": - ret = "models/ai/zal(.mdl"; - break; - case "models/machines/quick_revive.mdl": - ret = "models/machines/quake_scale/quick_revive.mdl"; - break; - case "models/machines/juggernog.mdl": - ret = "models/machines/quake_scale/juggernog.mdl"; - break; - case "models/machines/speed_cola.mdl": - ret = "models/machines/quake_scale/speed_cola.mdl"; - break; - case "progs/misc/double_tap.mdl": - case "models/machines/double_tap.mdl": - ret = "models/machines/quake_scale/double_tap.mdl"; - break; - case "progs/misc/flopper.mdl": - case "models/machines/flopper.mdl": - ret = "models/machines/quake_scale/flopper.mdl"; - break; - case "models/machines/staminup.mdl": - ret = "models/machines/quake_scale/staminup.mdl"; - break; - case "models/machines/deadshot.mdl": - ret = "models/machines/quake_scale/deadshot.mdl"; - break; - case "models/machines/mulekick.mdl": - ret = "models/machines/quake_scale/mulekick.mdl"; - break; - case "progs/misc/pap.mdl": - case "models/machines/pap.mdl": - ret = "models/machines/quake_scale/pap.mdl"; - break; - case "progs/sprites/lamp_glow.spr": - ret = "models/sprites/lamp_glow.spr"; - break; - case "progs/sprites/lamp_glow2.spr": - // HACK HACK -- old maps that used this sprite were working with - // a broken offset, fix it. - self.origin_z -= 32; - ret = "models/sprites/lamp_glow2.spr"; - break; - case "progs/sprites/lamp_glow3.spr": - ret = "models/sprites/lamp_glow.spr"; - break; - case "progs/props/kino_boxes2.mdl": - ret = "models/props/Kino_boxes2.mdl"; - break; - case "progs/props/kino_boxes3.mdl": - ret = "models/props/Kino_boxes3.mdl"; - break; - case "progs/props/kino_boxes4.mdl": - ret = "models/props/Kino_boxes4.mdl"; - break; - case "progs/body_bag_flat.mdl": - ret = "models/props/bodybag_flat.mdl"; - break; - case "progs/body_bag_head.mdl": - ret = "models/props/bodybag_head.mdl"; - break; - case "progs/body_bag_back_wall.mdl": - ret = "models/props/bodybag_back_wall.mdl"; - break; - case "progs/teddy.mdl": - case "progs/props/teddy.mdl": - case "progs/misc/teddy.mdl": - ret = "models/props/teddy.mdl"; - break; - case "progs/props/kino_box.mdl": - ret = "models/props/Kino_box.mdl"; - break; - case "progs/props/table_dinner.mdl": - ret = "models/props/table_dinner.mdl"; - break; - case "progs/props/table_sq.mdl": - ret = "models/props/table_sq.mdl"; - break; - case "progs/props/rebar.mdl": - ret = "models/props/rebar.mdl"; - break; - case "progs/props/kino_table.mdl": - ret = "models/props/Kino_table.mdl"; - break; - case "progs/props/kino_couch.mdl": - ret = "models/props/kino_couch.mdl"; - break; - case "progs/props/metal_chair.mdl": - ret = "models/props/metal_chair.mdl"; - break; - case "progs/props/sandbags.mdl": - case "progs/sandbags.mdl": - ret = "models/props/sandbags.mdl"; - break; - case "progs/dentist_chair.mdl": - case "progs/props/dentist_chair.mdl": - ret = "models/props/dentist_chair.mdl"; - break; - case "progs/props/bath.mdl": - ret = "models/props/bath.mdl"; - break; - case "progs/props/shelf.mdl": - ret = "models/props/shelf.mdl"; - break; - case "progs/props/dummy.mdl": - ret = "models/props/dummy.mdl"; - break; - case "progs/props/stand.mdl": - ret = "models/props/stand.mdl"; - break; - case "progs/props/radio.mdl": - ret = "models/props/radio.mdl"; - break; - case "progs/props/radiator.mdl": - ret = "models/props/radiator.mdl"; - break; - case "progs/props/lamp_ndu.mdl": - ret = "models/props/lamp_ndu.mdl"; - break; - case "progs/props/lamp_ndu45.mdl": - ret = "models/props/lamp_ndu45.mdl"; - break; - case "progs/jeep.mdl": - ret = "models/props/jeep.mdl"; - break; - case "progs/tree.mdl": - ret = "models/props/treeth.mdl"; - break; - case "progs/treef.mdl": - ret = "models/props/tree_swamp.mdl"; - break; - case "progs/props/barrel_m.mdl": - ret = "models/props/barrel_m.mdl"; - break; - case "progs/props/lamp_oil.mdl": - ret = "models/props/lamp_oil.mdl"; - break; - case "progs/props/piano.mdl": - ret = "models/props/piano.mdl"; - break; - case "progs/props/pisuar.mdl": - ret = "models/props/pisuar.mdl"; - break; - case "progs/props/teleporter.mdl": - ret = "models/props/teleporter.mdl"; - break; - case "progs/props/chandelier.mdl": - ret = "models/props/chandelier.mdl"; - break; - case "progs/props/vanity_table.mdl": - ret = "models/props/vanity_table.mdl"; - break; - case "progs/props/trash_con.mdl": - ret = "models/props/trash_con.mdl"; - break; - case "progs/flame2.mdl": - ret = "models/props/flame.mdl"; - break; - case "progs/toilet.mdl": - ret = "models/props/toilet.mdl"; - break; - case "progs/fridge.mdl": - case "progs/props/fridge.mdl": - ret = "models/props/fridge.mdl"; - break; - case "progs/props/kino_chairset.mdl": - ret = "models/props/kino_chairset.mdl"; - break; - case "progs/props/kino_lounge.mdl": - ret = "models/props/Kino_lounge.mdl"; - break; - case "progs/props/kino_stageprop.mdl": - ret = "models/props/kino_stageprop.mdl"; - break; - case "progs/props/mainframe_pad.mdl": - ret = "models/props/mainframe_pad.mdl"; - break; - case "progs/props/tree_ch.mdl": - ret = "models/props/tree_ch.mdl"; - break; - case "progs/props/treesl.mdl": - ret = "models/props/treesl.mdl"; - break; - case "progs/lamp.mdl": - ret = "models/props/lamp_oil.mdl"; - break; - case "progs/props/bed.mdl": - ret = "models/props/bed.mdl"; - break; - case "progs/gmodels/g_mp40.mdl": - case "progs/g_mp40.mdl": - ret = "models/weapons/mp40/g_mp40.mdl"; - break; - case "progs/gmodels/g_thomp.mdl": - case "progs/g_thomp.mdl": - ret = "models/weapons/thomp/g_thomp.mdl"; - break; - case "progs/gmodels/g_betty.mdl": - case "progs/g_betty.mdl": - ret = "models/weapons/grenade/g_betty.mdl"; - break; - case "progs/g_fg.mdl": - case "progs/gmodels/g_fg.mdl": - ret = "models/weapons/fg42/g_fg.mdl"; - break; - case "progs/g_m1a1.mdl": - ret = "models/weapons/m1carbine/g_m1a1.mdl"; - break; - case "progs/g_ray.mdl": - ret = "models/weapons/ray/g_ray.mdl"; - break; - case "progs/g_tesla.mdl": - ret = "models/weapons/tesla/g_tesla.mdl"; - break; - case "progs/g_mg.mdl": - ret = "models/weapons/mg/g_mg.mdl"; - break; - case "progs/g_colt.mdl": - ret = "models/weapons/m1911/g_colt.mdl"; - break; - case "progs/g_browning.mdl": - ret = "models/weapons/browning/g_browning.mdl"; - break; - case "progs/g_m1.mdl": - case "progs/gmodels/g_m1.mdl": - ret = "models/weapons/garand/g_m1.mdl"; - break; - case "progs/g_sawn.mdl": - case "progs/gmodels/g_sawnoff.mdl": - ret = "models/weapons/sawnoff/g_sawnoff.mdl"; - break; - case "progs/g_trench.mdl": - case "progs/gmodels/g_trench.mdl": - ret = "models/weapons/trench/g_trench.mdl"; - break; - case "progs/gmodels/g_bar.mdl": - ret = "models/weapons/bar/g_bar.mdl"; - break; - case "progs/grenade.mdl": - case "progs/gmodels/g_grenade.mdl": - ret = "models/weapons/grenade/g_grenade.mdl"; - break; - case "progs/g_gewehr.mdl": - case "progs/gmodels/g_gewehr.mdl": - ret = "models/weapons/gewehr/g_gewehr.mdl"; - break; - case "progs/g_db.mdl": - ret = "models/weapons/db/g_db.mdl"; - break; - case "progs/g_kar.mdl": - ret = "models/weapons/kar/g_kar.mdl"; - break; - case "progs/g_kars.mdl": - ret = "models/weapons/kar/g_kars.mdl"; - break; - case "progs/g_bowie.mdl": - case "progs/gmodels/g_bowie.mdl": - ret = "models/weapons/knife/g_bowie.mdl"; - break; - case "progs/g_mp5.mdl": - ret = "models/weapons/mp5k/g_mp5k.mdl"; - break; - case "progs/gmodels/g_type.mdl": - ret = "models/weapons/type/g_type.mdl"; - break; - case "progs/gmodels/g_ppsh.mdl": - case "progs/g_ppsh.mdl": - ret = "models/weapons/ppsh/g_ppsh.mdl"; - break; - case "progs/gmodels/g_stg.mdl": - case "progs/g_stg.mdl": - ret = "models/weapons/stg/g_stg.mdl"; - break; - case "models/misc/lightning.spr": - ret = "models/sprites/lightning.spr"; - break; - case "models/derped/wall_lamp.mdl": - ret = "models/props/lamp_wall.mdl"; - break; - case "models/machines/power_switch.mdl": - ret = "models/machines/quake_scale/power_switch.mdl"; - break; - case "models/machines/hl_scale/packapunch/p_machine.mdl": - ret = "models/machines/hl_scale/pap/p_machine.mdl"; - break; - case "models/machines/hl_scale/packapunch/p_roller.mdl": - ret = "models/machines/hl_scale/pap/p_roller.mdl"; - break; - case "models/machines/hl_scale/packapunch/p_flag.mdl": - ret = "models/machines/hl_scale/pap/p_flag.mdl"; - break; - default: - ret = asset; - break; - } - - strunzone(lowered_asset); - return ret; -}; +}; \ No newline at end of file diff --git a/source/server/utilities/map_compatibility.qc b/source/server/utilities/map_compatibility.qc index dd04047..4232cc0 100644 --- a/source/server/utilities/map_compatibility.qc +++ b/source/server/utilities/map_compatibility.qc @@ -128,7 +128,7 @@ void() Compat_TryLoadBetaWaypoints = } fclose(file_handle); -} +}; #endif // FTE // @@ -147,7 +147,7 @@ void(string model_path, float scale_factor) Compat_ConvertPropScale = props.scale = scale_factor; props = find(props, model, model_path); } -} +}; // // Compat_ConvertWorldModelScales() @@ -168,7 +168,7 @@ void() Compat_ConvertWorldModelScales = props = find(props, classname, "place_model"); } -} +}; // // Compat_ConvertPropScaling() @@ -184,7 +184,7 @@ void() Compat_ConvertPropScaling = // Automatic Compat_ConvertWorldModelScales(); -} +}; // // NZ:P Beta Wall Weapons @@ -262,7 +262,7 @@ void() Compat_ConvertBetaWallWeapons = weapons = find(weapons, classname, "buy_weapon"); } -} +}; // // NZ:P Beta Barricades @@ -287,7 +287,7 @@ void() Compat_ConvertBetaBarricade = self.hop_spot_x -= 5; self.hop_spot_z -= 20; self.scale = 0.75; -} +}; void() item_cover = {map_compatibility_mode = MAP_COMPAT_BETA; item_barricade(); Compat_ConvertBetaBarricade();}; @@ -323,7 +323,7 @@ void() Compat_FixMysteryBox = mystery_box_spots = find(mystery_box_spots, classname, "mystery_box_tp_spot"); } -} +}; // // NZ:P Beta Power Switch @@ -347,7 +347,7 @@ void() Compat_FixPowerSwitch = power_switches = find(power_switches, classname, "power_switch"); } -} +}; // // NZ:P Beta Perk-A-Cola Machines @@ -384,7 +384,7 @@ void(float mode) Compat_RelocateBetaPerkMachine = } self.scale = 0.85; -} +}; void() item_revive = {map_compatibility_mode = MAP_COMPAT_BETA; Compat_RelocateBetaPerkMachine(COMPAT_RELOCAT_NORM); perk_revive();}; void() item_speed = {map_compatibility_mode = MAP_COMPAT_BETA; Compat_RelocateBetaPerkMachine(COMPAT_RELOCAT_SPEED); perk_speed();}; @@ -420,7 +420,7 @@ float(string msg) Compat_TriggerCommandIsSafe = return false; return true; -} +}; void() touch_command = { @@ -432,7 +432,7 @@ void() touch_command = // Follow up with cl_insta because whoever wrote this way back // forgot to perform a line break.. stuffcmd(other, strcat(self.message, "cl_insta\n")); -} +}; #endif // FTE @@ -464,7 +464,47 @@ void() trigger_command = #endif // FTE -} +}; + +// +// General NZ:P Compatibility +// + +// +// Compat_ConvertOldAssetPath(path) +// Takes in a path as a string, hashes it, +// then performs a binary search to pick +// a redirected (updated) path. +// +string(string path) Compat_ConvertOldAssetPath = +{ + string return_string = path; + + // Generate a CRC16 IBM 3740 hash of the path + float input_hash = crc16(true, path); + float input_len = strlen(path); // Assists with hash collision detection. + + // Perform the binary search to locate it + float bs_left = 0; + float bs_right = asset_conversion_table.length - 1; + + while(bs_left <= bs_right) { + float bs_middle = (bs_left + bs_right) / 2; + bs_middle = bs_middle & ~0; + + if (asset_conversion_table[bs_middle].old_path_crc == input_hash && asset_conversion_table[bs_middle].crc_strlen == input_len) { + return_string = asset_conversion_table[bs_middle].current_path; + break; + } + + if (asset_conversion_table[bs_middle].old_path_crc < input_hash) + bs_left = bs_middle + 1; + else + bs_right = bs_middle - 1; + } + + return return_string; +}; // // Compat_Init() @@ -482,4 +522,4 @@ void() Compat_Init = Compat_ConvertPropScaling(); Compat_FixPowerSwitch(); Compat_FixMysteryBox(); -} \ No newline at end of file +}; \ No newline at end of file diff --git a/tools/asset_conversion_table.csv b/tools/asset_conversion_table.csv new file mode 100644 index 0000000..47b1ea5 --- /dev/null +++ b/tools/asset_conversion_table.csv @@ -0,0 +1,111 @@ +old_path,current_path +progs/player.mdl,models/player.mdl +progs/ai/zal(.mdl,models/ai/zal(.mdl +models/machines/quick_revive.mdl,models/machines/quake_scale/quick_revive.mdl +models/machines/juggernog.mdl,models/machines/quake_scale/juggernog.mdl +models/machines/speed_cola.mdl,models/machines/quake_scale/speed_cola.mdl +progs/misc/double_tap.mdl,models/machines/quake_scale/double_tap.mdl +models/machines/double_tap.mdl,models/machines/quake_scale/double_tap.mdl +progs/misc/flopper.mdl,models/machines/quake_scale/flopper.mdl +models/machines/flopper.mdl,models/machines/quake_scale/flopper.mdl +models/machines/staminup.mdl,models/machines/quake_scale/staminup.mdl +models/machines/deadshot.mdl,models/machines/quake_scale/deadshot.mdl +models/machines/mulekick.mdl,models/machines/quake_scale/mulekick.mdl +progs/misc/pap.mdl,models/machines/quake_scale/pap.mdl +models/machines/pap.mdl,models/machines/quake_scale/pap.mdl +progs/sprites/lamp_glow.spr,models/sprites/lamp_glow.spr +progs/sprites/lamp_glow3.spr,models/sprites/lamp_glow.spr +progs/props/kino_boxes2.mdl,models/props/Kino_boxes2.mdl +progs/props/kino_boxes3.mdl,models/props/Kino_boxes3.mdl +progs/props/kino_boxes4.mdl,models/props/Kino_boxes4.mdl +progs/body_bag_flat.mdl,models/props/bodybag_flat.mdl +progs/body_bag_head.mdl,models/props/bodybag_head.mdl +progs/body_bag_back_wall.mdl,models/props/bodybag_back_wall.mdl +progs/teddy.mdl,models/props/teddy.mdl +progs/props/teddy.mdl,models/props/teddy.mdl +progs/misc/teddy.mdl,models/props/teddy.mdl +progs/props/kino_box.mdl,models/props/Kino_box.mdl +progs/props/table_dinner.mdl,models/props/table_dinner.mdl +progs/props/table_sq.mdl,models/props/table_sq.mdl +progs/props/rebar.mdl,models/props/rebar.mdl +progs/props/kino_table.mdl,models/props/Kino_table.mdl +progs/props/kino_couch.mdl,models/props/kino_couch.mdl +progs/props/metal_chair.mdl,models/props/metal_chair.mdl +progs/props/sandbags.mdl,models/props/sandbags.mdl +progs/sandbags.mdl,models/props/sandbags.mdl +progs/dentist_chair.mdl,models/props/dentist_chair.mdl +progs/props/dentist_chair.mdl,models/props/dentist_chair.mdl +progs/props/bath.mdl,models/props/bath.mdl +progs/props/shelf.mdl,models/props/shelf.mdl +progs/props/dummy.mdl,models/props/dummy.mdl +progs/props/stand.mdl,models/props/stand.mdl +progs/props/radio.mdl,models/props/radio.mdl +progs/props/radiator.mdl,models/props/radiator.mdl +progs/props/lamp_ndu.mdl,models/props/lamp_ndu.mdl +progs/props/lamp_ndu45.mdl,models/props/lamp_ndu45.mdl +progs/jeep.mdl,models/props/jeep.mdl +progs/tree.mdl,models/props/treeth.mdl +progs/treef.mdl,models/props/tree_swamp.mdl +progs/props/barrel_m.mdl,models/props/barrel_m.mdl +progs/props/lamp_oil.mdl,models/props/lamp_oil.mdl +progs/props/piano.mdl,models/props/piano.mdl +progs/props/pisuar.mdl,models/props/pisuar.mdl +progs/props/teleporter.mdl,models/props/teleporter.mdl +progs/props/chandelier.mdl,models/props/chandelier.mdl +progs/props/vanity_table.mdl,models/props/vanity_table.mdl +progs/props/trash_con.mdl,models/props/trash_con.mdl +progs/flame2.mdl,models/props/flame.mdl +progs/toilet.mdl,models/props/toilet.mdl +progs/fridge.mdl,models/props/fridge.mdl +progs/props/fridge.mdl,models/props/fridge.mdl +progs/props/kino_chairset.mdl,models/props/kino_chairset.mdl +progs/props/kino_lounge.mdl,models/props/Kino_lounge.mdl +progs/props/kino_stageprop.mdl,models/props/kino_stageprop.mdl +progs/props/mainframe_pad.mdl,models/props/mainframe_pad.mdl +progs/props/tree_ch.mdl,models/props/tree_ch.mdl +progs/props/treesl.mdl,models/props/treesl.mdl +progs/lamp.mdl,models/props/lamp_oil.mdl +progs/props/bed.mdl,models/props/bed.mdl +progs/gmodels/g_mp40.mdl,models/weapons/mp40/g_mp40.mdl +progs/g_mp40.mdl,models/weapons/mp40/g_mp40.mdl +progs/gmodels/g_thomp.mdl,models/weapons/thomp/g_thomp.mdl +progs/g_thomp.mdl,models/weapons/thomp/g_thomp.mdl +progs/gmodels/g_betty.mdl,models/weapons/grenade/g_betty.mdl +progs/g_betty.mdl,models/weapons/grenade/g_betty.mdl +progs/g_fg.mdl,models/weapons/fg42/g_fg.mdl +progs/gmodels/g_fg.mdl,models/weapons/fg42/g_fg.mdl +progs/g_m1a1.mdl,models/weapons/m1carbine/g_m1a1.mdl +progs/g_ray.mdl,models/weapons/ray/g_ray.mdl +progs/g_tesla.mdl,models/weapons/tesla/g_tesla.mdl +progs/g_mg.mdl,models/weapons/mg/g_mg.mdl +progs/g_colt.mdl,models/weapons/m1911/g_colt.mdl +progs/g_browning.mdl,models/weapons/browning/g_browning.mdl +progs/g_m1.mdl,models/weapons/garand/g_m1.mdl +progs/gmodels/g_m1.mdl,models/weapons/garand/g_m1.mdl +progs/g_sawn.mdl,models/weapons/sawnoff/g_sawnoff.mdl +progs/gmodels/g_sawnoff.mdl,models/weapons/sawnoff/g_sawnoff.mdl +progs/g_trench.mdl,models/weapons/trench/g_trench.mdl +progs/gmodels/g_trench.mdl,models/weapons/trench/g_trench.mdl +progs/gmodels/g_bar.mdl,models/weapons/bar/g_bar.mdl +progs/grenade.mdl,models/weapons/grenade/g_grenade.mdl +progs/gmodels/g_grenade.mdl,models/weapons/grenade/g_grenade.mdl +progs/g_gewehr.mdl,models/weapons/gewehr/g_gewehr.mdl +progs/gmodels/g_gewehr.mdl,models/weapons/gewehr/g_gewehr.mdl +progs/g_db.mdl,models/weapons/db/g_db.mdl +progs/g_kar.mdl,models/weapons/kar/g_kar.mdl +progs/g_kars.mdl,models/weapons/kar/g_kars.mdl +progs/g_bowie.mdl,models/weapons/knife/g_bowie.mdl +progs/gmodels/g_bowie.mdl,models/weapons/knife/g_bowie.mdl +progs/g_mp5.mdl,models/weapons/mp5k/g_mp5k.mdl +progs/gmodels/g_type.mdl,models/weapons/type/g_type.mdl +progs/gmodels/g_ppsh.mdl,models/weapons/ppsh/g_ppsh.mdl +progs/g_ppsh.mdl,models/weapons/ppsh/g_ppsh.mdl +progs/gmodels/g_stg.mdl,models/weapons/stg/g_stg.mdl +progs/g_stg.mdl,models/weapons/stg/g_stg.mdl +models/misc/lightning.spr,models/sprites/lightning.spr +models/derped/wall_lamp.mdl,models/props/lamp_wall.mdl +models/machines/power_switch.mdl,models/machines/quake_scale/power_switch.mdl +models/machines/hl_scale/packapunch/p_machine.mdl,models/machines/hl_scale/pap/p_machine.mdl +models/machines/hl_scale/packapunch/p_roller.mdl,models/machines/hl_scale/pap/p_roller.mdl +models/machines/hl_scale/packapunch/p_flag.mdl,models/machines/hl_scale/pap/p_flag.mdl +progs/sprites/lamp_glow2.spr,models/sprites/lamp_glow2.spr \ No newline at end of file diff --git a/tools/qc-compiler-lin.sh b/tools/qc-compiler-lin.sh index c9387ed..54aa06d 100755 --- a/tools/qc-compiler-lin.sh +++ b/tools/qc-compiler-lin.sh @@ -1,24 +1,22 @@ #!/usr/bin/env bash cd ../ + +# generate hash table +echo "Generating Hash Table.." +python bin/qc_hash_generator.py -i tools/asset_conversion_table.csv -o source/server/hash_table.qc + # create build directories mkdir -p build/{fte,standard} + cd bin/ -echo "" -echo "========================" -echo " compiling FTE CCQC " -echo "========================" -echo "" -./fteqcc-cli-lin -srcfile ../progs/fte-client.src -echo "" -echo "========================" -echo " compiling FTE SSQC " -echo "========================" -echo "" -./fteqcc-cli-lin -O2 -srcfile ../progs/fte-server.src -echo "" -echo "========================" -echo " compiling STANDARD QC " -echo "========================" -echo "" -./fteqcc-cli-lin -O2 -srcfile ../progs/standard.src + +# build.. +echo "Compiling FTE CSQC.." +./fteqcc-cli-lin -srcfile ../progs/fte-client.src | grep -E -i "warning |error |defined |not |unknown" +echo "Compiling FTE SSQC.." +./fteqcc-cli-lin -O2 -srcfile ../progs/fte-server.src | grep -E -i "warning |error |defined |not |unknown" +echo "Compiling Standard/Id SSQC.." +./fteqcc-cli-lin -O2 -srcfile ../progs/standard.src | grep -E -i "warning |error |defined |not |unknown" + +echo "End of script." \ No newline at end of file diff --git a/tools/qc-compiler-mac.sh b/tools/qc-compiler-mac.sh index 1fdaf73..b9f804a 100755 --- a/tools/qc-compiler-mac.sh +++ b/tools/qc-compiler-mac.sh @@ -1,24 +1,22 @@ #!/usr/bin/env bash cd ../ + +# generate hash table +echo "Generating Hash Table.." +python bin/qc_hash_generator.py -i tools/asset_conversion_table.csv -o source/server/hash_table.qc + # create build directories mkdir -p build/{fte,standard} + cd bin/ -echo "" -echo "========================" -echo " compiling FTE CCQC " -echo "========================" -echo "" -./fteqcc-cli-mac -srcfile ../progs/fte-client.src -echo "" -echo "========================" -echo " compiling FTE SSQC " -echo "========================" -echo "" -./fteqcc-cli-mac -O2 -srcfile ../progs/fte-server.src -echo "" -echo "========================" -echo " compiling STANDARD QC " -echo "========================" -echo "" -./fteqcc-cli-mac -O2 -srcfile ../progs/standard.src + +# build.. +echo "Compiling FTE CSQC.." +./fteqcc-cli-mac -srcfile ../progs/fte-client.src | grep -E -i "warning |error |defined |not |unknown" +echo "Compiling FTE SSQC.." +./fteqcc-cli-mac -O2 -srcfile ../progs/fte-server.src | grep -E -i "warning |error |defined |not |unknown" +echo "Compiling Standard/Id SSQC.." +./fteqcc-cli-mac -O2 -srcfile ../progs/standard.src | grep -E -i "warning |error |defined |not |unknown" + +echo "End of script." \ No newline at end of file diff --git a/tools/qc-compiler-win.bat b/tools/qc-compiler-win.bat index 05f4b9e..c314f96 100644 --- a/tools/qc-compiler-win.bat +++ b/tools/qc-compiler-win.bat @@ -1,25 +1,24 @@ @ECHO OFF + CD ../ + +REM ****** generate hash table ****** +echo Generating Hash Table.. +python bin\qc_hash_generator.py -i tools\asset_conversion_table.csv -o source\server\hash_table.qc + REM ****** create build directories ****** MKDIR build\fte\ 2>nul MKDIR build\standard\ 2>nul + CD bin/ -echo. -echo ======================== -echo compiling FTE CCQC -echo ======================== -echo. + +REM ****** build.. ****** +echo Compiling FTE CSQC.. fteqcc-cli-win.exe -srcfile ../progs/fte-client.src -echo. -echo ======================== -echo compiling FTE SSQC -echo ======================== -echo. +echo Compiling FTE SSQC.. fteqcc-cli-win.exe -O2 -srcfile ../progs/fte-server.src -echo. -echo ======================== -echo compiling STANDARD QC -echo ======================== -echo. +echo Compiling Standard/Id SSQC.. fteqcc-cli-win.exe -O2 -srcfile ../progs/standard.src -pause + +echo End of script. +pause \ No newline at end of file