Skip to content

Commit 82d81ba

Browse files
committed
Merge remote-tracking branch 'origin/master' into italian
2 parents b45ddd7 + 5adde5b commit 82d81ba

File tree

5 files changed

+149
-22
lines changed

5 files changed

+149
-22
lines changed

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ which should show an error message and list available chapters
8383

8484
Then run
8585

86-
```python build.py onikakushi --translation```
86+
```python build.py onikakushi```
8787

8888
Then the output files will be located in the `output/translation` folder. You can then merge the `HigurashiEp0X_Data` folder with the one in your release. **Please include all the files (not just the `sharedassets0.assets` file), so the installer can select the correct file at install time.**
8989

90-
If you want to rebuild all chapters, run `python build.py all --translation` to build all chapters.
90+
If you want to rebuild all chapters, run `python build.py all` to build all chapters.
9191

9292
### Common Problems
9393

@@ -99,15 +99,11 @@ You may encounter the following problems:
9999

100100
**NOTE: The script should automatically detect if the vanilla assets or UABE has changed, and re-download them. But if that doesn't work, use the '--force-download' option like so:**
101101

102-
```python build.py rei --translation --force-download```
102+
```python build.py rei --force-download```
103103

104104
## Instructions for Dev Team
105105

106-
For our dev team, the instructions are nearly the same, just remove the `--translation` argument.
107-
108-
```python build.py onikakushi```
109-
110-
Archive files will be automatically created in the `output` folder
106+
Instructions are the same as for translators, but archive files will be automatically created in the `output` folder
111107

112108
----
113109

@@ -133,6 +129,8 @@ Click on the 'Actions' tab to observe the build process.
133129

134130
Once the build is complete, go to the 'Releases' page, and a new draft release should appear. You can check everything is OK before publishing the release, or just download the files without publishing the release.
135131

132+
Note that doing this will build both the `translation.7z` file for translators to use, and also the individual archives for the 07th-mod developers to use.
133+
136134
### Building `ui-compiler.exe` using Github Actions
137135

138136
To build just the `ui-compiler.exe` using Github Actions (on Github's server), push any tag to the repository.
@@ -145,6 +143,12 @@ The following information is only used when adding support for a new episode.
145143

146144
Please look through the detailed documentation, especially if you're working on a new chapter, new language, or using UABE - this file does not contain information on those topics.
147145

146+
### WARNING about Unix/MacOS `sharedassets0.assets`
147+
148+
We've found that the MacOS sharedassets can be used on Linux, **but the Linux sharedassets CANNOT be used on MacOS in certain cases**, giving you the "purple text" issue.
149+
150+
For this reason, whenever a new chapter is prepared, the 'vanilla' unix `sharedassets0.assets` should be taken from the MacOS version.
151+
148152
### Preparing font files
149153

150154
You'll need to extract the 'msgothic' font files from the stock `.assets` file before starting:

build.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,19 @@ def get_translation_sharedassets_name(self) -> str:
113113
# 'matsuribayashi 5.6.7f1 unix'
114114
],
115115
"matsuribayashi": [
116-
BuildVariant("M_GOG-M_MG-Steam", "matsuribayashi", "2017.2.5", "unix"),
116+
# Based on the GOG MacOS sharedassets, but works on Linux too.
117+
# Working on:
118+
# - Linux Steam (2023-07-09)
119+
# - Linux GOG (2023-07-09)
120+
# - MacOS GOG (2023-07-09)
121+
BuildVariant("GOG-MG-Steam", "matsuribayashi", "2017.2.5", "unix"),
122+
123+
# NOTE: I'm 99% certain this file is no longer used, as we just upgrade the entire GOG/Mangagamer game
117124
# Special version for GOG/Mangagamer Linux with SHA256:
118125
# A200EC2A85349BC03B59C8E2F106B99ED0CBAAA25FC50928BB8BA2E2AA90FCE9
119126
# CRC32L 51100D6D
120-
BuildVariant("L_GOG-L_MG", "matsuribayashi", "2017.2.5", "unix", "51100D6D"),
127+
# BuildVariant("GOG-MG", "matsuribayashi", "2017.2.5", "unix", "51100D6D"), # TO BE REMOVED
128+
121129
BuildVariant("GOG-MG-Steam", "matsuribayashi", "2017.2.5", "win", translation_default=True),
122130
],
123131
'rei': [
@@ -240,6 +248,13 @@ def save(self):
240248
with open(LastModifiedManager.savePath, 'w') as handle:
241249
json.dump(self.lastModifiedDict, handle)
242250

251+
if sys.version_info < (2, 7):
252+
print(">>>> ERROR: This script does not work on Python 2.7")
253+
exit(-1)
254+
255+
if not (sys.version_info < (3, 11)):
256+
print(">>>> WARNING: This script probably does not work on Python 3.11 because unitypack uses old version of decrunch which does not build. Use Python 3.10 or below if you have this error.")
257+
243258
lastModifiedManager = LastModifiedManager()
244259

245260
# Parse command line arguments
@@ -252,14 +267,11 @@ def save(self):
252267
choices=["all", "github_actions"] + list(chapter_to_build_variants.keys()),
253268
)
254269
parser.add_argument("--force-download", default=False, action='store_true')
255-
parser.add_argument("--translation", default=False, action='store_true')
270+
parser.add_argument("--disable-translation", default=False, action='store_true')
256271
args = parser.parse_args()
257272

258273
force_download = args.force_download
259274

260-
# NOTE: For now, translation archive output is always enabled, as most of the time this script will be used for translators
261-
translation = args.translation
262-
263275
# Get chapter name from git tag if "github_actions" specified as the chapter
264276
chapter_name = args.chapter
265277
if chapter_name == "github_actions":
@@ -270,13 +282,21 @@ def save(self):
270282
)
271283
exit(0)
272284

273-
# NOTE: For now, translation archive output is always enabled, as most of the time this script will be used for translators
285+
# NOTE: For now, translation archive output is enabled by default, as most of the time this script will be used for translators
274286
translation = True
275287

288+
if args.disable_translation:
289+
translation = False
290+
276291
# Get a list of build variants (like 'onikakushi 5.2.2f1 win') depending on commmand line arguments
277292
build_variants = get_build_variants(chapter_name)
278293
build_variants_list = "\n - ".join([b.get_build_command() for b in build_variants])
279-
print(f"For chapter '{chapter_name}' building:\n - {build_variants_list}")
294+
print(f"-------- Build Started --------")
295+
print(f"Chapter: [{chapter_name}] | Translation Archive Output: [{('Enabled' if translation else 'Disabled')}]")
296+
print(f"Variants:")
297+
print(f" - {build_variants_list}")
298+
print(f"-------------------------------")
299+
print()
280300

281301
# Install python dependencies
282302
print("Installing python dependencies")

compileall.sh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@ cargo run meakashi 5.5.3p1 win && \
1515
cargo run meakashi 5.5.3p1 unix && \
1616
cargo run tsumihoroboshi 5.5.3p3 win && \
1717
cargo run tsumihoroboshi 5.5.3p3 unix && \
18-
cargo run tsumihoroboshi 5.6.7f1 win && \
1918
cargo run minagoroshi 5.6.7f1 win && \
2019
cargo run minagoroshi 5.6.7f1 unix && \
2120
cargo run matsuribayashi 5.6.7f1 win && \
2221
cargo run matsuribayashi 5.6.7f1 unix && \
23-
cargo run matsuribayashi 2017.2.5 unix && \
24-
cargo run matsuribayashi 2017.2.5 win && \
2522
cargo run rei 2019.4.3 win && \
2623
cargo run rei 2019.4.4 win && \
2724
cargo run rei 2019.4.3 unix && \
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Use this script to merge together multiple text-edits.json files together
2+
# It expects all .json files to be in a folder called 'text-edits' next to this script
3+
# It outputs to a file called merged-translations.json
4+
# Files will be output in alphabetical order, so it is recommended to prepend each file with the chapter number
5+
# If there are any conflicts, and exception will be raised.
6+
#
7+
# This script is usually never needed, unless translators have been swapping out the text-edits.json for each chapter
8+
# rather than maintaining a common text-edits.json for all chapters.
9+
10+
import os
11+
import json
12+
13+
14+
class Fragment:
15+
order = 0
16+
17+
def __init__(self, fragment_as_dictionary: dict[str, str]):
18+
self.current_english = fragment_as_dictionary['CurrentEnglish']
19+
self.current_japanese = fragment_as_dictionary['CurrentJapanese']
20+
self.new_english = fragment_as_dictionary['NewEnglish']
21+
self.new_japanese = fragment_as_dictionary['NewJapanese']
22+
self.discriminator = fragment_as_dictionary.get('Discriminator')
23+
self.order = Fragment.order
24+
Fragment.order += 1
25+
26+
# Generate a key for this Fragment, used later to check for conflicting fragments
27+
self.key = self.current_english + self.current_japanese
28+
if self.discriminator is not None:
29+
self.key += str(self.discriminator)
30+
31+
32+
def equals(self, other: 'Fragment'):
33+
return (
34+
self.current_english == other.current_english and
35+
self.current_japanese == other.current_japanese and
36+
self.new_english == other.new_english and
37+
self.new_japanese == other.new_japanese and
38+
self.discriminator == other.discriminator
39+
)
40+
41+
def __repr__(self) -> str:
42+
return f"{self.order} ce: {self.current_english} cj: {self.current_japanese} ne: {self.new_english} nj: {self.new_japanese} d: {self.discriminator}"
43+
44+
def as_dict(self):
45+
retval = {
46+
'CurrentEnglish': self.current_english,
47+
'CurrentJapanese': self.current_japanese,
48+
'NewEnglish': self.new_english,
49+
'NewJapanese': self.new_japanese,
50+
}
51+
52+
if self.discriminator is not None:
53+
retval['Discriminator'] = self.discriminator
54+
55+
return retval
56+
57+
def merge(all_translations: dict[str, Fragment], fragment: Fragment):
58+
59+
if not fragment.key in all_translations:
60+
all_translations[fragment.key] = fragment
61+
else:
62+
existing_item = all_translations[fragment.key]
63+
64+
if existing_item.equals(fragment):
65+
print(f"Skipping duplicate item {fragment}")
66+
else:
67+
raise Exception(f"Warning: non duplicate item existing:{existing_item} new: {fragment}")
68+
69+
70+
71+
in_folder = "text-edits"
72+
73+
files = os.listdir(in_folder)
74+
75+
all_fragments = [] # type: list[Fragment]
76+
77+
for filename in files:
78+
path = os.path.join(in_folder, filename)
79+
print(f"Parsing {path}")
80+
81+
with open(path, encoding='utf-8') as f:
82+
chapter_list_dict = json.loads(f.read())
83+
84+
all_fragments.extend(Fragment(f) for f in chapter_list_dict)
85+
86+
all_translations = {}
87+
88+
# Merge all fragments into one dict, ignoring duplicates
89+
for f in all_fragments:
90+
print(f.current_english)
91+
merge(all_translations, f)
92+
print()
93+
94+
# Convert to list and sort by 'order' which is the order the fragments were loaded
95+
sorted_translations = list(sorted(all_translations.values(), key=lambda f: f.order))
96+
for item in sorted_translations:
97+
print(item)
98+
99+
with open("merged-translations.json", 'w', encoding='utf-8') as out:
100+
out.write(json.dumps([f.as_dict() for f in sorted_translations], indent=4, ensure_ascii=False))

scripts/UnityTextModifier.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,14 @@ def findInAssetBundle(self, bundle):
7272
offsets.append(offset)
7373
start = offset + 1
7474
if len(offsets) == 0:
75-
raise IndexError(f"No asset found for {self.shortString}")
75+
raise IndexError(f"WARNING: No asset found for {self.shortString}")
7676
if self.discriminator == None:
7777
if len(offsets) > 1:
78-
raise IndexError(f"Multiple assets found for {self.shortString}, candidates are " + ", ".join(f"{index}: 0x{offset:x}" for index, offset in enumerate(offsets)) + ". Please add a field like 'Discriminator: 0' to indicate which block should apply to which asset (do NOT use quotes around the number, do not use the raw address). For an example, see https://github.com/07th-mod/higurashi-dev-guides/wiki/UI-editing-scripts#unitytextmodifier")
78+
raise IndexError(f"WARNING: Multiple assets found for {self.shortString}, candidates are " + ", ".join(f"{index}: 0x{offset:x}" for index, offset in enumerate(offsets)) + ". Please add a field like 'Discriminator: 0' to indicate which block should apply to which asset (do NOT use quotes around the number, do not use the raw address). For an example, see https://github.com/07th-mod/higurashi-dev-guides/wiki/UI-editing-scripts#unitytextmodifier")
7979
self.offset = offsets[0]
8080
else:
8181
if len(offsets) <= self.discriminator:
82-
raise IndexError(f"Not enough offsets found for ${self.trimmedE} / {self.trimmedJ} to meet request for #{self.discriminator}, there were only {len(offsets)}")
82+
raise IndexError(f"WARNING: Not enough offsets found for {self.shortString} to meet request for #{self.discriminator}, there were only {len(offsets)}")
8383
self.offset = offsets[self.discriminator]
8484

8585
def checkObject(self, id, object, bundle):
@@ -113,6 +113,7 @@ def __str__(self):
113113
try: return f"<ScriptEdit for position 0x{self.offset:x}>"
114114
except: return "<ScriptEdit for unknown position>"
115115

116+
warning_count = 0
116117

117118
with open(sys.argv[2], encoding="utf-8") as jsonFile:
118119
edits = [ScriptEdit.fromJSON(x) for x in json.load(jsonFile)]
@@ -127,6 +128,8 @@ def __str__(self):
127128
print(f"Found {edit.shortString} at offset 0x{edit.offset:x}")
128129
except IndexError as e:
129130
print(e)
131+
warning_count =+ 1
132+
130133
edits = newEdits
131134

132135
assetsFile.seek(0)
@@ -136,3 +139,6 @@ def __str__(self):
136139
edit.checkObject(id, obj, bundle)
137140
for edit in edits:
138141
edit.write(sys.argv[3])
142+
143+
if warning_count > 0:
144+
print(">>>>>>>> ONE OR MORE WARNINGS OCCURRED, please check logs! <<<<<<<<<")

0 commit comments

Comments
 (0)