forked from BEEmod/BEE2-items
-
Notifications
You must be signed in to change notification settings - Fork 0
/
reverse_cache.py
155 lines (142 loc) · 5.89 KB
/
reverse_cache.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# coding=utf-8
"""
This script applies any changes made to the game files to matching resources
in any packages.
"""
import os
import shutil
import sys
EXTRA_FILE_LOC = 'extra_files'
try:
GAME_FOLDER = os.environ['PORTAL_2_LOC']
except KeyError:
raise Exception('Set the PORTAL_2_LOC environment variable to the location of Portal 2.') from None
# Skip these files, if they exist in the source folders.
# Users won't need them.
SKIPPED_EXTENSIONS = ('vmx', 'log', 'bsp', 'prt', 'lin')
resource_paths = set()
IGNORE_PROPS = [
'"mapversion"',
'"bsnaptogrid"',
'"bshowgrid"',
'"bshowlogicalgrid"',
'"ngridspacing"',
'"bshow3dgrid"'
]
def check_vmf_modified(file1, file2):
"""Check to see if a VMF was modified.
This ignores changes in the map version, and prefs like the
grid sizing or camera position.
"""
with open(file1) as f1:
with open(file2) as f2:
for line1, line2 in zip(f1, f2):
line1 = line1.casefold()
line2 = line2.casefold()
if (
line1.strip() == 'camera' or
line2.strip() == 'camera'
):
# We got to the camera block, abort checking now
# We just ignore this entire section; since it's the last,
# the files must be identical
return False
if line1 == line2:
continue
for ignore_text in IGNORE_PROPS:
if (
ignore_text in line1 or
ignore_text in line2
):
break
else:
return True # The line is different!
else:
return False # No modification
def check_file(pack_path, rel_path):
if rel_path.startswith('instances'):
game_path = os.path.join(
GAME_FOLDER,
'sdk_content',
'maps',
'instances',
'bee2',
rel_path[10:],
)
else:
game_path = os.path.join(GAME_FOLDER, 'bee2_dev', rel_path)
if os.path.isfile(game_path):
if os.path.getmtime(game_path) == os.path.getmtime(pack_path):
return # Same mod times = same file...
if rel_path.endswith('.vmf'):
if check_vmf_modified(game_path, pack_path):
print('Applying changes to "{}"'.format(rel_path))
shutil.copy(game_path, pack_path)
elif rel_path[:-3].casefold() in SKIPPED_EXTENSIONS:
return # Never copy .log, .vmx, etc!
else:
# Assume everything else is changed!
print('Applying changes to "{}"'.format(rel_path))
shutil.copy(game_path, pack_path)
else:
print('Removing "{}"'.format(rel_path), file=sys.stderr)
os.remove(pack_path)
def do_folder(path):
"""Check a folder to see if it's a package.
If it is, check any resources.
"""
for package in os.listdir(path):
package_path = os.path.join(path, package)
if os.path.isdir(package_path):
if os.path.isfile(os.path.join(package_path,'info.txt')):
res_folder = os.path.join(package_path, 'resources')
if not os.path.isdir(res_folder):
print('Package has no resources!')
for base, dirs, files in os.walk(res_folder):
if base.casefold() == res_folder.casefold():
# For the root, stop us from looking in the BEE2 or music_samp folder
for ind, folder in enumerate(dirs[:]):
if folder.casefold() in ('bee2', 'music_samp'):
dirs.remove(folder)
continue # There aren't any resources in the package/resources/ folder itself
for file in files:
full_path = os.path.normpath(os.path.join(base, file))
rel_path = os.path.relpath(full_path, res_folder)
resource_paths.add(rel_path.casefold())
check_file(
full_path,
rel_path,
)
else:
do_folder(package_path)
def check_extra(game_subfolder, set_prefix, skip_folder=''):
full_folder = os.path.join(GAME_FOLDER, game_subfolder)
for base, dirs, files in os.walk(full_folder):
if skip_folder and base == full_folder and skip_folder in dirs:
dirs.remove(skip_folder)
for file in files:
if file[-3:] in SKIPPED_EXTENSIONS:
continue
full_path = os.path.normpath(os.path.join(base, file))
rel_path = os.path.relpath(full_path, full_folder)
if os.path.join(set_prefix, rel_path).casefold() not in resource_paths:
print('Extra file: "{}"'.format(
os.path.join(set_prefix, rel_path)
))
dest = os.path.join(EXTRA_FILE_LOC, set_prefix, rel_path)
os.makedirs(os.path.dirname(dest), exist_ok=True)
# Make it a symlink, easy to delete and create.
shutil.copy(full_path, dest)
if __name__ == '__main__':
do_folder(os.path.join(os.getcwd(), 'packages'))
print('Cleaning extra_files\\!')
shutil.rmtree(EXTRA_FILE_LOC + '/', ignore_errors=True)
print('Done!')
check_extra('bee2_dev\\models\\', 'models')
check_extra('bee2_dev\\materials\\', 'materials')
# Skip the Mel and Tag music.
check_extra('bee2_dev\\sound\\', 'sound', skip_folder='music')
check_extra('bee2_dev\\scripts\\', 'scripts')
check_extra('bee2_dev\\particles\\', 'particles')
check_extra('sdk_content\\maps\\instances\\bee2', 'instances')
print('Complete!')