Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
ziqian zhang
Grasscutter
Commits
4790158a
Commit
4790158a
authored
Jul 23, 2022
by
AnimeGitB
Committed by
Luke H-W
Aug 09, 2022
Browse files
Load in all the textmaps!
parent
d56ca209
Changes
3
Show whitespace changes
Inline
Side-by-side
.gitignore
View file @
4790158a
...
@@ -64,7 +64,7 @@ tmp/
...
@@ -64,7 +64,7 @@ tmp/
/*.jar
/*.jar
/*.sh
/*.sh
GM Handbook.txt
GM Handbook
*
.txt
config.json
config.json
mitmdump.exe
mitmdump.exe
mongod.exe
mongod.exe
...
...
src/main/java/emu/grasscutter/Grasscutter.java
View file @
4790158a
...
@@ -98,6 +98,10 @@ public final class Grasscutter {
...
@@ -98,6 +98,10 @@ public final class Grasscutter {
Tools
.
createGmHandbook
();
Tools
.
createGmHandbook
();
exitEarly
=
true
;
exitEarly
=
true
;
}
}
case
"-handbooks"
->
{
Tools
.
createGmHandbooks
();
exitEarly
=
true
;
}
case
"-dumppacketids"
->
{
case
"-dumppacketids"
->
{
PacketOpcodesUtils
.
dumpPacketIds
();
PacketOpcodesUtils
.
dumpPacketIds
();
exitEarly
=
true
;
exitEarly
=
true
;
...
...
src/main/java/emu/grasscutter/tools/Tools.java
View file @
4790158a
package
emu.grasscutter.tools
;
package
emu.grasscutter.tools
;
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.FileOutputStream
;
import
java.io.FileReader
;
import
java.io.InputStreamReader
;
import
java.io.InputStreamReader
;
import
java.io.OutputStreamWriter
;
import
java.io.OutputStreamWriter
;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
...
@@ -10,12 +12,15 @@ import java.nio.charset.StandardCharsets;
...
@@ -10,12 +12,15 @@ import java.nio.charset.StandardCharsets;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.time.format.DateTimeFormatter
;
import
java.util.*
;
import
java.util.*
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
import
com.google.gson.reflect.TypeToken
;
import
com.google.gson.reflect.TypeToken
;
import
emu.grasscutter.GameConstants
;
import
emu.grasscutter.GameConstants
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.GameData
;
...
@@ -26,12 +31,234 @@ import emu.grasscutter.data.excels.ItemData;
...
@@ -26,12 +31,234 @@ import emu.grasscutter.data.excels.ItemData;
import
emu.grasscutter.data.excels.MonsterData
;
import
emu.grasscutter.data.excels.MonsterData
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.data.excels.SceneData
;
import
emu.grasscutter.data.excels.SceneData
;
import
emu.grasscutter.utils.Language
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
import
it.unimi.dsi.fastutil.ints.Int2IntMap
;
import
it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
it.unimi.dsi.fastutil.ints.IntArrayList
;
import
it.unimi.dsi.fastutil.ints.IntList
;
import
it.unimi.dsi.fastutil.ints.IntOpenHashSet
;
import
it.unimi.dsi.fastutil.ints.IntSet
;
import
it.unimi.dsi.fastutil.objects.Object2IntMap
;
import
it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap
;
import
lombok.EqualsAndHashCode
;
import
static
emu
.
grasscutter
.
config
.
Configuration
.*;
import
static
emu
.
grasscutter
.
config
.
Configuration
.*;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
public
final
class
Tools
{
public
final
class
Tools
{
@EqualsAndHashCode
public
static
class
TextStrings
{
public
static
final
String
[]
ARR_LANGUAGES
=
{
"EN"
,
"CHS"
,
"CHT"
,
"JP"
,
"KR"
,
"DE"
,
"ES"
,
"FR"
,
"ID"
,
"PT"
,
"RU"
,
"TH"
,
"VI"
};
public
static
final
String
[]
ARR_GC_LANGUAGES
=
{
"en-US"
,
"zh-CN"
,
"zh-TW"
,
"JP"
,
"KR"
,
"DE"
,
"es-ES"
,
"fr-FR"
,
"ID"
,
"PT"
,
"ru-RU"
,
"TH"
,
"VI"
};
public
static
final
int
NUM_LANGUAGES
=
ARR_LANGUAGES
.
length
;
public
static
final
List
<
String
>
LIST_LANGUAGES
=
Arrays
.
asList
(
ARR_LANGUAGES
);
public
static
final
Object2IntMap
<
String
>
MAP_LANGUAGES
=
// Map "EN": 0, "CHS": 1, ..., "VI": 12
new
Object2IntOpenHashMap
<>(
IntStream
.
range
(
0
,
ARR_LANGUAGES
.
length
)
.
boxed
()
.
collect
(
Collectors
.
toMap
(
i
->
ARR_LANGUAGES
[
i
],
i
->
i
)));
public
String
[]
strings
=
new
String
[
ARR_LANGUAGES
.
length
];
public
TextStrings
()
{};
public
TextStrings
(
String
init
)
{
for
(
int
i
=
0
;
i
<
NUM_LANGUAGES
;
i
++)
this
.
strings
[
i
]
=
init
;
};
public
TextStrings
(
Collection
<
String
>
strings
)
{
this
.
strings
=
strings
.
toArray
(
new
String
[
0
]);
}
public
String
get
(
String
languageCode
)
{
return
strings
[
MAP_LANGUAGES
.
getOrDefault
(
languageCode
,
0
)];
}
public
boolean
set
(
String
languageCode
,
String
string
)
{
int
index
=
MAP_LANGUAGES
.
getOrDefault
(
languageCode
,
-
1
);
if
(
index
<
0
)
return
false
;
strings
[
index
]
=
string
;
return
true
;
}
}
private
static
final
Pattern
textMapKeyValueRegex
=
Pattern
.
compile
(
"\"(\\d+)\": \"(.+)\""
);
private
static
Int2ObjectMap
<
String
>
loadTextMap
(
String
language
,
IntSet
nameHashes
)
{
Int2ObjectMap
<
String
>
output
=
new
Int2ObjectOpenHashMap
<>();
try
(
BufferedReader
file
=
new
BufferedReader
(
new
FileReader
(
Utils
.
toFilePath
(
RESOURCE
(
"TextMap/TextMap"
+
language
+
".json"
)),
StandardCharsets
.
UTF_8
)))
{
Matcher
matcher
=
textMapKeyValueRegex
.
matcher
(
""
);
return
new
Int2ObjectOpenHashMap
<>(
file
.
lines
()
.
sequential
()
.
map
(
matcher:
:
reset
)
// Side effects, but it's faster than making a new one
.
filter
(
Matcher:
:
find
)
.
filter
(
m
->
nameHashes
.
contains
((
int
)
Long
.
parseLong
(
m
.
group
(
1
))))
// TODO: Cache this parse somehow
.
collect
(
Collectors
.
toMap
(
m
->
(
int
)
Long
.
parseLong
(
m
.
group
(
1
)),
m
->
m
.
group
(
2
))));
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Error loading textmap: "
+
language
);
Grasscutter
.
getLogger
().
error
(
e
.
toString
());
}
return
output
;
}
public
static
Int2ObjectMap
<
TextStrings
>
loadTextMaps
(
IntSet
nameHashes
)
{
Map
<
Integer
,
Int2ObjectMap
<
String
>>
mapLanguageMaps
=
// Separate step to process the textmaps in parallel
TextStrings
.
LIST_LANGUAGES
.
parallelStream
().
collect
(
Collectors
.
toConcurrentMap
(
s
->
TextStrings
.
MAP_LANGUAGES
.
getInt
(
s
),
s
->
loadTextMap
(
s
,
nameHashes
)));
List
<
Int2ObjectMap
<
String
>>
languageMaps
=
IntStream
.
range
(
0
,
TextStrings
.
NUM_LANGUAGES
)
.
mapToObj
(
i
->
mapLanguageMaps
.
get
(
i
))
.
collect
(
Collectors
.
toList
());
Map
<
TextStrings
,
TextStrings
>
canonicalTextStrings
=
new
HashMap
<>();
return
new
Int2ObjectOpenHashMap
<
TextStrings
>(
nameHashes
.
intStream
()
.
boxed
()
.
collect
(
Collectors
.
toMap
(
key
->
key
,
key
->
{
TextStrings
t
=
new
TextStrings
(
IntStream
.
range
(
0
,
TextStrings
.
NUM_LANGUAGES
)
.
mapToObj
(
i
->
languageMaps
.
get
(
i
).
getOrDefault
((
int
)
key
,
"[N/A] - hash key %d"
.
formatted
(
key
)))
.
collect
(
Collectors
.
toList
()));
return
canonicalTextStrings
.
computeIfAbsent
(
t
,
x
->
t
);
}))
);
}
public
static
void
createGmHandbooks
()
throws
Exception
{
ResourceLoader
.
loadAll
();
Int2IntMap
avatarNames
=
new
Int2IntOpenHashMap
(
GameData
.
getAvatarDataMap
().
int2ObjectEntrySet
().
stream
().
collect
(
Collectors
.
toMap
(
e
->
(
int
)
e
.
getIntKey
(),
e
->
(
int
)
e
.
getValue
().
getNameTextMapHash
())));
Int2IntMap
itemNames
=
new
Int2IntOpenHashMap
(
GameData
.
getItemDataMap
().
int2ObjectEntrySet
().
stream
().
collect
(
Collectors
.
toMap
(
e
->
(
int
)
e
.
getIntKey
(),
e
->
(
int
)
e
.
getValue
().
getNameTextMapHash
())));
Int2IntMap
monsterNames
=
new
Int2IntOpenHashMap
(
GameData
.
getMonsterDataMap
().
int2ObjectEntrySet
().
stream
().
collect
(
Collectors
.
toMap
(
e
->
(
int
)
e
.
getIntKey
(),
e
->
(
int
)
e
.
getValue
().
getNameTextMapHash
())));
Int2IntMap
mainQuestTitles
=
new
Int2IntOpenHashMap
(
GameData
.
getMainQuestDataMap
().
int2ObjectEntrySet
().
stream
().
collect
(
Collectors
.
toMap
(
e
->
(
int
)
e
.
getIntKey
(),
e
->
(
int
)
e
.
getValue
().
getTitleTextMapHash
())));
Int2IntMap
questDescs
=
new
Int2IntOpenHashMap
(
GameData
.
getQuestDataMap
().
int2ObjectEntrySet
().
stream
().
collect
(
Collectors
.
toMap
(
e
->
(
int
)
e
.
getIntKey
(),
e
->
(
int
)
e
.
getValue
().
getDescTextMapHash
())));
IntSet
usedHashes
=
new
IntOpenHashSet
();
usedHashes
.
addAll
(
avatarNames
.
values
());
usedHashes
.
addAll
(
itemNames
.
values
());
usedHashes
.
addAll
(
monsterNames
.
values
());
usedHashes
.
addAll
(
mainQuestTitles
.
values
());
usedHashes
.
addAll
(
questDescs
.
values
());
Int2ObjectMap
<
TextStrings
>
textMaps
=
loadTextMaps
(
usedHashes
);
Language
savedLanguage
=
Grasscutter
.
getLanguage
();
// Preamble
StringBuilder
[]
handbookBuilders
=
new
StringBuilder
[
TextStrings
.
NUM_LANGUAGES
];
String
now
=
DateTimeFormatter
.
ofPattern
(
"yyyy/MM/dd HH:mm:ss"
).
format
(
LocalDateTime
.
now
());
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
]
=
new
StringBuilder
()
.
append
(
"// Grasscutter "
+
GameConstants
.
VERSION
+
" GM Handbook\n"
)
.
append
(
"// Created "
+
now
+
"\n\n"
)
.
append
(
"// Commands\n"
);
}
// Commands
List
<
CommandHandler
>
cmdList
=
new
CommandMap
(
true
).
getHandlersAsList
();
for
(
CommandHandler
cmd
:
cmdList
)
{
StringBuilder
cmdName
=
new
StringBuilder
(
cmd
.
getLabel
());
while
(
cmdName
.
length
()
<=
15
)
{
cmdName
.
insert
(
0
,
" "
);
}
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
Grasscutter
.
setLanguage
(
Language
.
getLanguage
(
TextStrings
.
ARR_GC_LANGUAGES
[
i
]));
// A bit hacky but eh whatever
handbookBuilders
[
i
]
.
append
(
cmdName
+
" : "
)
.
append
(
cmd
.
getDescriptionString
(
null
).
replace
(
"\n"
,
"\n\t\t\t\t"
).
replace
(
"\t"
,
" "
))
.
append
(
"\n"
);
}
}
// Avatars
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
].
append
(
"\n\n// Avatars\n"
);
}
avatarNames
.
keySet
().
intStream
().
sorted
().
forEach
(
id
->
{
TextStrings
t
=
textMaps
.
get
(
avatarNames
.
get
(
id
));
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
]
.
append
(
"%d : "
.
formatted
(
id
))
.
append
(
t
.
strings
[
i
])
.
append
(
"\n"
);
}
});
// Items
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
].
append
(
"\n\n// Items\n"
);
}
itemNames
.
keySet
().
intStream
().
sorted
().
forEach
(
id
->
{
TextStrings
t
=
textMaps
.
get
(
itemNames
.
get
(
id
));
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
]
.
append
(
"%d : "
.
formatted
(
id
))
.
append
(
t
.
strings
[
i
])
.
append
(
"\n"
);
}
});
// Monsters
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
].
append
(
"\n\n// Monsters\n"
);
}
monsterNames
.
keySet
().
intStream
().
sorted
().
forEach
(
id
->
{
TextStrings
t
=
textMaps
.
get
(
monsterNames
.
get
(
id
));
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
]
.
append
(
"%d : "
.
formatted
(
id
))
.
append
(
t
.
strings
[
i
])
.
append
(
"\n"
);
}
});
// Scenes - no translations
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
].
append
(
"\n\n// Scenes\n"
);
}
var
sceneDataMap
=
GameData
.
getSceneDataMap
();
sceneDataMap
.
keySet
().
intStream
().
sorted
().
forEach
(
id
->
{
String
data
=
sceneDataMap
.
get
(
id
).
getScriptData
();
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
]
.
append
(
"%d : "
.
formatted
(
id
))
.
append
(
data
)
.
append
(
"\n"
);
}
});
// Quests
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
].
append
(
"\n\n// Quests\n"
);
}
var
questDataMap
=
GameData
.
getQuestDataMap
();
questDataMap
.
keySet
().
intStream
().
sorted
().
forEach
(
id
->
{
QuestData
data
=
questDataMap
.
get
(
id
);
int
titleKey
=
(
int
)
mainQuestTitles
.
get
(
data
.
getMainId
());
int
descKey
=
(
int
)
data
.
getDescTextMapHash
();
TextStrings
title
=
textMaps
.
get
(
titleKey
);
TextStrings
desc
=
textMaps
.
get
(
descKey
);
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
handbookBuilders
[
i
]
.
append
(
id
)
.
append
(
" : "
)
.
append
(
title
.
strings
[
i
])
.
append
(
" - "
)
.
append
(
desc
.
strings
[
i
])
.
append
(
"\n"
);
}
});
Grasscutter
.
setLanguage
(
savedLanguage
);
// Write txt files
for
(
int
i
=
0
;
i
<
TextStrings
.
NUM_LANGUAGES
;
i
++)
{
String
fileName
=
"./GM Handbook - %s.txt"
.
formatted
(
TextStrings
.
ARR_LANGUAGES
[
i
]);
try
(
PrintWriter
writer
=
new
PrintWriter
(
new
OutputStreamWriter
(
new
FileOutputStream
(
fileName
),
StandardCharsets
.
UTF_8
),
false
))
{
writer
.
write
(
handbookBuilders
[
i
].
toString
());
}
}
Grasscutter
.
getLogger
().
info
(
"GM Handbooks generated!"
);
}
public
static
void
createGmHandbook
()
throws
Exception
{
public
static
void
createGmHandbook
()
throws
Exception
{
ToolsWithLanguageOption
.
createGmHandbook
(
getLanguageOption
());
ToolsWithLanguageOption
.
createGmHandbook
(
getLanguageOption
());
}
}
...
@@ -115,7 +342,7 @@ final class ToolsWithLanguageOption {
...
@@ -115,7 +342,7 @@ final class ToolsWithLanguageOption {
while
(
cmdName
.
length
()
<=
15
)
{
while
(
cmdName
.
length
()
<=
15
)
{
cmdName
.
insert
(
0
,
" "
);
cmdName
.
insert
(
0
,
" "
);
}
}
writer
.
println
(
cmdName
+
" : "
+
translate
(
cmd
.
getDescriptionString
(
null
))
)
;
writer
.
println
(
cmdName
+
" : "
+
cmd
.
getDescriptionString
(
null
));
}
}
writer
.
println
();
writer
.
println
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment