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
fe4e5990
Commit
fe4e5990
authored
May 18, 2022
by
Melledy
Browse files
Merge branch 'development' into dev-world-scripts
parents
3cffdd97
e3ed3968
Changes
58
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java
View file @
fe4e5990
package
emu.grasscutter.net.packet
;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.List
;
public
class
PacketOpcodes
{
...
...
@@ -1556,5 +1557,8 @@ public class PacketOpcodes {
public
static
final
int
UNKNOWN_44
=
8983
;
public
static
final
int
UNKNOWN_45
=
943
;
public
static
final
List
<
Integer
>
BANNED_PACKETS
=
Arrays
.
asList
(
PacketOpcodes
.
WindSeedClientNotify
,
PacketOpcodes
.
PlayerLuaShellNotify
);
public
static
final
HashSet
<
Integer
>
BANNED_PACKETS
=
new
HashSet
<
Integer
>()
{{
add
(
PacketOpcodes
.
WindSeedClientNotify
);
add
(
PacketOpcodes
.
PlayerLuaShellNotify
);
}};
}
src/main/java/emu/grasscutter/net/packet/PacketOpcodesUtil.java
View file @
fe4e5990
...
...
@@ -17,10 +17,12 @@ public class PacketOpcodesUtil {
Field
[]
fields
=
PacketOpcodes
.
class
.
getFields
();
for
(
Field
f
:
fields
)
{
try
{
opcodeMap
.
put
(
f
.
getInt
(
null
),
f
.
getName
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
if
(
f
.
getType
().
equals
(
int
.
class
))
{
try
{
opcodeMap
.
put
(
f
.
getInt
(
null
),
f
.
getName
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
}
...
...
src/main/java/emu/grasscutter/server/event/game/CommandResponseEvent.java
0 → 100644
View file @
fe4e5990
package
emu.grasscutter.server.event.game
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.types.GameEvent
;
import
emu.grasscutter.server.event.types.ServerEvent
;
public
class
CommandResponseEvent
extends
ServerEvent
{
private
String
message
;
private
Player
player
;
public
CommandResponseEvent
(
Type
type
,
Player
player
,
String
message
)
{
super
(
type
);
this
.
message
=
message
;
this
.
player
=
player
;
}
public
String
getMessage
()
{
return
message
;
}
public
Player
getPlayer
()
{
return
player
;
}
}
src/main/java/emu/grasscutter/server/http/dispatch/DispatchHandler.java
View file @
fe4e5990
...
...
@@ -33,6 +33,14 @@ public final class DispatchHandler implements Router {
.
handleAccountCreation
(
AuthenticationSystem
.
fromExternalRequest
(
request
,
response
)));
express
.
post
(
"/authentication/change_password"
,
(
request
,
response
)
->
Grasscutter
.
getAuthenticationSystem
().
getExternalAuthenticator
()
.
handlePasswordReset
(
AuthenticationSystem
.
fromExternalRequest
(
request
,
response
)));
// OAuth login
express
.
post
(
"/hk4e_global/mdk/shield/api/loginByThirdparty"
,
(
request
,
response
)
->
Grasscutter
.
getAuthenticationSystem
().
getOAuthAuthenticator
().
handleLogin
(
AuthenticationSystem
.
fromOAuthRequest
(
request
,
response
)));
// OAuth querystring convert redirection
express
.
get
(
"/authentication/openid/redirect"
,
(
request
,
response
)
->
Grasscutter
.
getAuthenticationSystem
().
getOAuthAuthenticator
().
handleTokenProcess
(
AuthenticationSystem
.
fromOAuthRequest
(
request
,
response
)));
// OAuth redirection
express
.
get
(
"/Api/twitter_login"
,
(
request
,
response
)
->
Grasscutter
.
getAuthenticationSystem
().
getOAuthAuthenticator
().
handleDesktopRedirection
(
AuthenticationSystem
.
fromOAuthRequest
(
request
,
response
)));
express
.
get
(
"/sdkTwitterLogin.html"
,
(
request
,
response
)
->
Grasscutter
.
getAuthenticationSystem
().
getOAuthAuthenticator
().
handleMobileRedirection
(
AuthenticationSystem
.
fromOAuthRequest
(
request
,
response
)));
}
/**
...
...
src/main/java/emu/grasscutter/server/http/dispatch/RegionHandler.java
View file @
fe4e5990
...
...
@@ -60,7 +60,8 @@ public final class RegionHandler implements Router {
if
(
SERVER
.
runMode
!=
ServerRunMode
.
HYBRID
&&
configuredRegions
.
size
()
==
0
)
{
Grasscutter
.
getLogger
().
error
(
"[Dispatch] There are no game servers available. Exiting due to unplayable state."
);
System
.
exit
(
1
);
}
else
configuredRegions
.
add
(
new
Region
(
"os_usa"
,
DISPATCH_INFO
.
defaultName
,
}
else
if
(
configuredRegions
.
size
()
==
0
)
configuredRegions
.
add
(
new
Region
(
"os_usa"
,
DISPATCH_INFO
.
defaultName
,
lr
(
GAME_INFO
.
accessAddress
,
GAME_INFO
.
bindAddress
),
lr
(
GAME_INFO
.
accessPort
,
GAME_INFO
.
bindPort
)));
...
...
src/main/java/emu/grasscutter/server/http/documentation/DocumentationHandler.java
0 → 100644
View file @
fe4e5990
package
emu.grasscutter.server.http.documentation
;
import
express.http.Request
;
import
express.http.Response
;
interface
DocumentationHandler
{
void
handle
(
Request
request
,
Response
response
);
}
src/main/java/emu/grasscutter/server/http/documentation/DocumentationServerHandler.java
0 → 100644
View file @
fe4e5990
package
emu.grasscutter.server.http.documentation
;
import
emu.grasscutter.server.http.Router
;
import
express.Express
;
import
io.javalin.Javalin
;
public
final
class
DocumentationServerHandler
implements
Router
{
@Override
public
void
applyRoutes
(
Express
express
,
Javalin
handle
)
{
final
RootRequestHandler
root
=
new
RootRequestHandler
();
final
HandbookRequestHandler
handbook
=
new
HandbookRequestHandler
();
final
GachaMappingRequestHandler
gachaMapping
=
new
GachaMappingRequestHandler
();
express
.
get
(
"/documentation/handbook"
,
handbook:
:
handle
);
express
.
get
(
"/documentation/gachamapping"
,
gachaMapping:
:
handle
);
express
.
get
(
"/documentation"
,
root:
:
handle
);
}
}
src/main/java/emu/grasscutter/server/http/documentation/GachaMappingRequestHandler.java
0 → 100644
View file @
fe4e5990
package
emu.grasscutter.server.http.documentation
;
import
static
emu
.
grasscutter
.
Configuration
.
RESOURCE
;
import
com.google.gson.reflect.TypeToken
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.ResourceLoader
;
import
emu.grasscutter.data.def.AvatarData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.tools.Tools
;
import
emu.grasscutter.utils.Utils
;
import
express.http.Request
;
import
express.http.Response
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.nio.charset.StandardCharsets
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
final
class
GachaMappingRequestHandler
implements
DocumentationHandler
{
private
Map
<
Long
,
String
>
map
;
GachaMappingRequestHandler
()
{
ResourceLoader
.
loadResources
();
final
String
textMapFile
=
"TextMap/TextMap"
+
Tools
.
getLanguageOption
()
+
".json"
;
try
(
InputStreamReader
fileReader
=
new
InputStreamReader
(
new
FileInputStream
(
Utils
.
toFilePath
(
RESOURCE
(
textMapFile
))),
StandardCharsets
.
UTF_8
))
{
map
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
new
TypeToken
<
Map
<
Long
,
String
>>()
{
}.
getType
());
}
catch
(
IOException
e
)
{
Grasscutter
.
getLogger
().
warn
(
"Resource does not exist: "
+
textMapFile
);
map
=
new
HashMap
<>();
}
}
@Override
public
void
handle
(
Request
request
,
Response
response
)
{
if
(
map
.
isEmpty
())
{
response
.
status
(
500
);
}
else
{
response
.
set
(
"Content-Type"
,
"application/json"
)
.
ctx
()
.
result
(
createGachaMappingJson
());
}
}
private
String
createGachaMappingJson
()
{
List
<
Integer
>
list
;
final
StringBuilder
sb
=
new
StringBuilder
();
list
=
new
ArrayList
<>(
GameData
.
getAvatarDataMap
().
keySet
());
Collections
.
sort
(
list
);
final
String
newLine
=
System
.
lineSeparator
();
// if the user made choices for language, I assume it's okay to assign his/her selected language to "en-us"
// since it's the fallback language and there will be no difference in the gacha record page.
// The enduser can still modify the `gacha_mappings.js` directly to enable multilingual for the gacha record system.
sb
.
append
(
"{"
).
append
(
newLine
);
// Avatars
boolean
first
=
true
;
for
(
Integer
id
:
list
)
{
AvatarData
data
=
GameData
.
getAvatarDataMap
().
get
(
id
);
int
avatarID
=
data
.
getId
();
if
(
avatarID
>=
11000000
)
{
// skip test avatar
continue
;
}
if
(
first
)
{
// skip adding comma for the first element
first
=
false
;
}
else
{
sb
.
append
(
","
);
}
String
color
;
switch
(
data
.
getQualityType
())
{
case
"QUALITY_PURPLE"
:
color
=
"purple"
;
break
;
case
"QUALITY_ORANGE"
:
color
=
"yellow"
;
break
;
case
"QUALITY_BLUE"
:
default
:
color
=
"blue"
;
}
// Got the magic number 4233146695 from manually search in the json file
sb
.
append
(
"\""
)
.
append
(
avatarID
%
1000
+
1000
)
.
append
(
"\" : [\""
)
.
append
(
map
.
get
(
data
.
getNameTextMapHash
()))
.
append
(
"("
)
.
append
(
map
.
get
(
4233146695L
))
.
append
(
")\", \""
)
.
append
(
color
)
.
append
(
"\"]"
)
.
append
(
newLine
);
}
list
=
new
ArrayList
<>(
GameData
.
getItemDataMap
().
keySet
());
Collections
.
sort
(
list
);
// Weapons
for
(
Integer
id
:
list
)
{
ItemData
data
=
GameData
.
getItemDataMap
().
get
(
id
);
if
(
data
.
getId
()
<=
11101
||
data
.
getId
()
>=
20000
)
{
continue
;
//skip non weapon items
}
String
color
;
switch
(
data
.
getRankLevel
())
{
case
3
:
color
=
"blue"
;
break
;
case
4
:
color
=
"purple"
;
break
;
case
5
:
color
=
"yellow"
;
break
;
default
:
continue
;
// skip unnecessary entries
}
// Got the magic number 4231343903 from manually search in the json file
sb
.
append
(
",\""
)
.
append
(
data
.
getId
())
.
append
(
"\" : [\""
)
.
append
(
map
.
get
(
data
.
getNameTextMapHash
()).
replaceAll
(
"\""
,
""
))
.
append
(
"("
)
.
append
(
map
.
get
(
4231343903L
))
.
append
(
")\",\""
)
.
append
(
color
)
.
append
(
"\"]"
)
.
append
(
newLine
);
}
sb
.
append
(
",\"200\": \""
)
.
append
(
map
.
get
(
332935371L
))
.
append
(
"\", \"301\": \""
)
.
append
(
map
.
get
(
2272170627L
))
.
append
(
"\", \"302\": \""
)
.
append
(
map
.
get
(
2864268523L
))
.
append
(
"\""
)
.
append
(
"}\n}"
)
.
append
(
newLine
);
return
sb
.
toString
();
}
}
src/main/java/emu/grasscutter/server/http/documentation/HandbookRequestHandler.java
0 → 100644
View file @
fe4e5990
package
emu.grasscutter.server.http.documentation
;
import
static
emu
.
grasscutter
.
Configuration
.
DATA
;
import
static
emu
.
grasscutter
.
Configuration
.
RESOURCE
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
import
com.google.gson.reflect.TypeToken
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.ResourceLoader
;
import
emu.grasscutter.data.def.AvatarData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.data.def.SceneData
;
import
emu.grasscutter.tools.Tools
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.Utils
;
import
express.http.Request
;
import
express.http.Response
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.nio.charset.StandardCharsets
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
final
class
HandbookRequestHandler
implements
DocumentationHandler
{
private
final
String
template
;
private
Map
<
Long
,
String
>
map
;
public
HandbookRequestHandler
()
{
ResourceLoader
.
loadResources
();
final
File
templateFile
=
new
File
(
Utils
.
toFilePath
(
DATA
(
"documentation/handbook.html"
)));
if
(
templateFile
.
exists
())
{
template
=
new
String
(
FileUtils
.
read
(
templateFile
),
StandardCharsets
.
UTF_8
);
}
else
{
Grasscutter
.
getLogger
().
warn
(
"File does not exist: "
+
templateFile
);
template
=
null
;
}
final
String
textMapFile
=
"TextMap/TextMap"
+
Tools
.
getLanguageOption
()
+
".json"
;
try
(
InputStreamReader
fileReader
=
new
InputStreamReader
(
new
FileInputStream
(
Utils
.
toFilePath
(
RESOURCE
(
textMapFile
))),
StandardCharsets
.
UTF_8
))
{
map
=
Grasscutter
.
getGsonFactory
()
.
fromJson
(
fileReader
,
new
TypeToken
<
Map
<
Long
,
String
>>()
{
}.
getType
());
}
catch
(
IOException
e
)
{
Grasscutter
.
getLogger
().
warn
(
"Resource does not exist: "
+
textMapFile
);
map
=
new
HashMap
<>();
}
}
@Override
public
void
handle
(
Request
request
,
Response
response
)
{
if
(
template
==
null
)
{
response
.
status
(
500
);
return
;
}
final
CommandMap
cmdMap
=
new
CommandMap
(
true
);
final
Int2ObjectMap
<
AvatarData
>
avatarMap
=
GameData
.
getAvatarDataMap
();
final
Int2ObjectMap
<
ItemData
>
itemMap
=
GameData
.
getItemDataMap
();
final
Int2ObjectMap
<
SceneData
>
sceneMap
=
GameData
.
getSceneDataMap
();
final
Int2ObjectMap
<
MonsterData
>
monsterMap
=
GameData
.
getMonsterDataMap
();
// Add translated title etc. to the page.
String
content
=
template
.
replace
(
"{{TITLE}}"
,
translate
(
"documentation.handbook.title"
))
.
replace
(
"{{TITLE_COMMANDS}}"
,
translate
(
"documentation.handbook.title_commands"
))
.
replace
(
"{{TITLE_AVATARS}}"
,
translate
(
"documentation.handbook.title_avatars"
))
.
replace
(
"{{TITLE_ITEMS}}"
,
translate
(
"documentation.handbook.title_items"
))
.
replace
(
"{{TITLE_SCENES}}"
,
translate
(
"documentation.handbook.title_scenes"
))
.
replace
(
"{{TITLE_MONSTERS}}"
,
translate
(
"documentation.handbook.title_monsters"
))
.
replace
(
"{{HEADER_ID}}"
,
translate
(
"documentation.handbook.header_id"
))
.
replace
(
"{{HEADER_COMMAND}}"
,
translate
(
"documentation.handbook.header_command"
))
.
replace
(
"{{HEADER_DESCRIPTION}}"
,
translate
(
"documentation.handbook.header_description"
))
.
replace
(
"{{HEADER_AVATAR}}"
,
translate
(
"documentation.handbook.header_avatar"
))
.
replace
(
"{{HEADER_ITEM}}"
,
translate
(
"documentation.handbook.header_item"
))
.
replace
(
"{{HEADER_SCENE}}"
,
translate
(
"documentation.handbook.header_scene"
))
.
replace
(
"{{HEADER_MONSTER}}"
,
translate
(
"documentation.handbook.header_monster"
))
// Commands table
.
replace
(
"{{COMMANDS_TABLE}}"
,
cmdMap
.
getAnnotationsAsList
()
.
stream
()
.
map
(
cmd
->
"<tr><td><code>"
+
cmd
.
label
()
+
"</code></td><td>"
+
cmd
.
description
()
+
"</td></tr>"
)
.
collect
(
Collectors
.
joining
(
"\n"
)))
// Avatars table
.
replace
(
"{{AVATARS_TABLE}}"
,
GameData
.
getAvatarDataMap
().
keySet
()
.
intStream
()
.
sorted
()
.
mapToObj
(
avatarMap:
:
get
)
.
map
(
data
->
"<tr><td><code>"
+
data
.
getId
()
+
"</code></td><td>"
+
map
.
get
(
data
.
getNameTextMapHash
())
+
"</td></tr>"
)
.
collect
(
Collectors
.
joining
(
"\n"
)))
// Items table
.
replace
(
"{{ITEMS_TABLE}}"
,
GameData
.
getItemDataMap
().
keySet
()
.
intStream
()
.
sorted
()
.
mapToObj
(
itemMap:
:
get
)
.
map
(
data
->
"<tr><td><code>"
+
data
.
getId
()
+
"</code></td><td>"
+
map
.
get
(
data
.
getNameTextMapHash
())
+
"</td></tr>"
)
.
collect
(
Collectors
.
joining
(
"\n"
)))
// Scenes table
.
replace
(
"{{SCENES_TABLE}}"
,
GameData
.
getSceneDataMap
().
keySet
()
.
intStream
()
.
sorted
()
.
mapToObj
(
sceneMap:
:
get
)
.
map
(
data
->
"<tr><td><code>"
+
data
.
getId
()
+
"</code></td><td>"
+
data
.
getScriptData
()
+
"</td></tr>"
)
.
collect
(
Collectors
.
joining
(
"\n"
)))
.
replace
(
"{{MONSTERS_TABLE}}"
,
GameData
.
getMonsterDataMap
().
keySet
()
.
intStream
()
.
sorted
()
.
mapToObj
(
monsterMap:
:
get
)
.
map
(
data
->
"<tr><td><code>"
+
data
.
getId
()
+
"</code></td><td>"
+
map
.
get
(
data
.
getNameTextMapHash
())
+
"</td></tr>"
)
.
collect
(
Collectors
.
joining
(
"\n"
)));
response
.
send
(
content
);
}
}
src/main/java/emu/grasscutter/server/http/documentation/RootRequestHandler.java
0 → 100644
View file @
fe4e5990
package
emu.grasscutter.server.http.documentation
;
import
static
emu
.
grasscutter
.
Configuration
.
DATA
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.ResourceLoader
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.Utils
;
import
express.http.Request
;
import
express.http.Response
;
import
java.io.File
;
import
java.nio.charset.StandardCharsets
;
final
class
RootRequestHandler
implements
DocumentationHandler
{
private
final
String
template
;
public
RootRequestHandler
()
{
ResourceLoader
.
loadResources
();
final
File
templateFile
=
new
File
(
Utils
.
toFilePath
(
DATA
(
"documentation/index.html"
)));
if
(
templateFile
.
exists
())
{
template
=
new
String
(
FileUtils
.
read
(
templateFile
),
StandardCharsets
.
UTF_8
);
}
else
{
Grasscutter
.
getLogger
().
warn
(
"File does not exist: "
+
templateFile
);
template
=
null
;
}
}
@Override
public
void
handle
(
Request
request
,
Response
response
)
{
if
(
template
==
null
)
{
response
.
status
(
500
);
return
;
}
String
content
=
template
.
replace
(
"{{TITLE}}"
,
translate
(
"documentation.index.title"
))
.
replace
(
"{{ITEM_HANDBOOK}}"
,
translate
(
"documentation.index.handbook"
))
.
replace
(
"{{ITEM_GACHA_MAPPING}}"
,
translate
(
"documentation.index.gacha_mapping"
));
response
.
send
(
content
);
}
}
src/main/java/emu/grasscutter/server/http/handlers/AnnouncementsHandler.java
View file @
fe4e5990
package
emu.grasscutter.server.http.handlers
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.DataLoader
;
import
emu.grasscutter.server.http.objects.HttpJsonResponse
;
import
emu.grasscutter.server.http.Router
;
import
emu.grasscutter.utils.FileUtils
;
...
...
@@ -14,6 +15,7 @@ import io.javalin.Javalin;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Objects
;
...
...
@@ -41,9 +43,21 @@ public final class AnnouncementsHandler implements Router {
private
static
void
getAnnouncement
(
Request
request
,
Response
response
)
{
String
data
=
""
;
if
(
Objects
.
equals
(
request
.
baseUrl
(),
"/common/hk4e_global/announcement/api/getAnnContent"
))
{
data
=
readToString
(
new
File
(
Utils
.
toFilePath
(
DATA
(
"GameAnnouncement.json"
))));
try
{
data
=
FileUtils
.
readToString
(
DataLoader
.
load
(
"GameAnnouncement.json"
));
}
catch
(
Exception
e
)
{
if
(
e
.
getClass
()
==
IOException
.
class
)
{
Grasscutter
.
getLogger
().
info
(
"Unable to read file 'GameAnnouncementList.json'. \n"
+
e
);
}
}
}
else
if
(
Objects
.
equals
(
request
.
baseUrl
(),
"/common/hk4e_global/announcement/api/getAnnList"
))
{
data
=
readToString
(
new
File
(
Utils
.
toFilePath
(
DATA
(
"GameAnnouncementList.json"
))));
try
{
data
=
FileUtils
.
readToString
(
DataLoader
.
load
(
"GameAnnouncementList.json"
));
}
catch
(
Exception
e
)
{
if
(
e
.
getClass
()
==
IOException
.
class
)
{
Grasscutter
.
getLogger
().
info
(
"Unable to read file 'GameAnnouncementList.json'. \n"
+
e
);
}
}
}
else
{
response
.
send
(
"{\"retcode\":404,\"message\":\"Unknown request path\"}"
);
}
...
...
@@ -64,29 +78,15 @@ public final class AnnouncementsHandler implements Router {
}
private
static
void
getPageResources
(
Request
request
,
Response
response
)
{
String
file
n
am
e
=
Utils
.
toFilePath
(
DATA
(
request
.
path
()))
;
File
file
=
new
File
(
filename
);
if
(
file
.
exists
()
&&
file
.
isFile
())
{
MediaType
fromExtension
=
MediaType
.
getByExtension
(
f
ilename
.
substring
(
f
ilename
.
lastIndexOf
(
"."
)
+
1
));
try
(
InputStream
file
stre
am
=
DataLoader
.
load
(
request
.
path
()))
{
String
possibleFilename
=
Utils
.
toFilePath
(
DATA
(
request
.
path
())
);
MediaType
fromExtension
=
MediaType
.
getByExtension
(
possibleF
ilename
.
substring
(
possibleF
ilename
.
lastIndexOf
(
"."
)
+
1
));
response
.
type
((
fromExtension
!=
null
)
?
fromExtension
.
getMIME
()
:
"application/octet-stream"
);
response
.
send
(
F
ile
Utils
.
read
(
file
));
}
else
{
Grasscutter
.
getLogger
().
warn
(
"File does not exist: "
+
file
);
response
.
send
(
f
ile
stream
.
readAllBytes
(
));
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
warn
(
"File does not exist: "
+
request
.
path
()
);
response
.
status
(
404
);
}
}
@SuppressWarnings
(
"ResultOfMethodCallIgnored"
)
private
static
String
readToString
(
File
file
)
{
byte
[]
content
=
new
byte
[(
int
)
file
.
length
()];
try
{
FileInputStream
in
=
new
FileInputStream
(
file
);
in
.
read
(
content
);
in
.
close
();
}
catch
(
IOException
ignored
)
{
Grasscutter
.
getLogger
().
warn
(
"File does not exist: "
+
file
);
}
return
new
String
(
content
,
StandardCharsets
.
UTF_8
);
}
}
src/main/java/emu/grasscutter/server/http/handlers/GachaHandler.java
View file @
fe4e5990
...
...
@@ -29,18 +29,7 @@ import static emu.grasscutter.utils.Language.translate;
* Handles all gacha-related HTTP requests.
*/
public
final
class
GachaHandler
implements
Router
{
private
final
String
gachaMappings
;
public
GachaHandler
()
{
this
.
gachaMappings
=
Utils
.
toFilePath
(
DATA
(
"/gacha/mappings.js"
));
if
(!(
new
File
(
this
.
gachaMappings
).
exists
()))
{
try
{
Tools
.
createGachaMapping
(
this
.
gachaMappings
);
}
catch
(
Exception
exception
)
{
Grasscutter
.
getLogger
().
warn
(
"Failed to create gacha mappings."
,
exception
);
}
}
}
public
static
final
String
gachaMappings
=
DATA
(
Utils
.
toFilePath
(
"gacha/mappings.js"
));
@Override
public
void
applyRoutes
(
Express
express
,
Javalin
handle
)
{
express
.
get
(
"/gacha"
,
GachaHandler:
:
gachaRecords
);
...
...
src/main/java/emu/grasscutter/server/http/handlers/GenericHandler.java
View file @
fe4e5990
...
...
@@ -41,9 +41,7 @@ public final class GenericHandler implements Router {
express
.
all
(
"/perf/config/verify"
,
new
HttpJsonResponse
(
"{\"code\":0}"
));
// webstatic-sea.hoyoverse.com
express
.
get
(
"/admin/mi18n/plat_oversea/m202003048/m202003048-version.json"
,
new
HttpJsonResponse
(
"{\"version\":51}"
));
express
.
get
(
"/admin/mi18n/plat_oversea/m2020030410/m2020030410-version.json"
,
new
HttpJsonResponse
(
"{\"version\":51}"
));
express
.
get
(
"/admin/mi18n/plat_oversea/m2020030410/m2020030410-zh-cn.json"
,
new
HttpJsonResponse
(
"{\"version\":51}"
));
express
.
get
(
"/admin/mi18n/plat_oversea/*"
,
new
HttpJsonResponse
(
"{\"version\":51}"
));
express
.
get
(
"/status/server"
,
GenericHandler:
:
serverStatus
);
}
...
...
src/main/java/emu/grasscutter/utils/ConfigContainer.java
View file @
fe4e5990
...
...
@@ -84,7 +84,6 @@ public class ConfigContainer {
public
String
resources
=
"./resources/"
;
public
String
data
=
"./data/"
;
public
String
packets
=
"./packets/"
;
public
String
keys
=
"./keys/"
;
public
String
scripts
=
"./resources/scripts/"
;
public
String
plugins
=
"./plugins/"
;
...
...
src/main/java/emu/grasscutter/utils/Crypto.java
View file @
fe4e5990
...
...
@@ -20,11 +20,11 @@ public final class Crypto {
public
static
byte
[]
ENCRYPT_SEED_BUFFER
=
new
byte
[
0
];
public
static
void
loadKeys
()
{
DISPATCH_KEY
=
FileUtils
.
read
(
KEY
(
"
dispatchKey.bin"
)
)
;
DISPATCH_SEED
=
FileUtils
.
read
(
KEY
(
"
dispatchSeed.bin"
)
)
;
DISPATCH_KEY
=
FileUtils
.
read
Resource
(
"/keys/
dispatchKey.bin"
);
DISPATCH_SEED
=
FileUtils
.
read
Resource
(
"/keys/
dispatchSeed.bin"
);
ENCRYPT_KEY
=
FileUtils
.
read
(
KEY
(
"
secretKey.bin"
)
)
;
ENCRYPT_SEED_BUFFER
=
FileUtils
.
read
(
KEY
(
"
secretKeyBuffer.bin"
)
)
;
ENCRYPT_KEY
=
FileUtils
.
read
Resource
(
"/keys/
secretKey.bin"
);
ENCRYPT_SEED_BUFFER
=
FileUtils
.
read
Resource
(
"/keys/
secretKeyBuffer.bin"
);
}
public
static
void
xor
(
byte
[]
packet
,
byte
[]
key
)
{
...
...
@@ -37,25 +37,6 @@ public final class Crypto {
}
}
public
static
void
extractSecretKeyBuffer
(
byte
[]
data
)
{
try
{
GetPlayerTokenRsp
p
=
GetPlayerTokenRsp
.
parseFrom
(
data
);
FileUtils
.
write
(
KEY
(
"/secretKeyBuffer.bin"
),
p
.
getSecretKeyBytes
().
toByteArray
());
Grasscutter
.
getLogger
().
info
(
"Secret Key: "
+
p
.
getSecretKey
());
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
}
}
public
static
void
extractDispatchSeed
(
String
data
)
{
try
{
QueryCurrRegionHttpRsp
p
=
QueryCurrRegionHttpRsp
.
parseFrom
(
Base64
.
getDecoder
().
decode
(
data
));
FileUtils
.
write
(
KEY
(
"/dispatchSeed.bin"
),
p
.
getRegionInfo
().
getSecretKey
().
toByteArray
());
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
}
}
public
static
byte
[]
createSessionKey
(
int
length
)
{
byte
[]
bytes
=
new
byte
[
length
];
secureRandom
.
nextBytes
(
bytes
);
...
...
src/main/java/emu/grasscutter/utils/FileUtils.java
View file @
fe4e5990
...
...
@@ -4,9 +4,14 @@ import emu.grasscutter.Grasscutter;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.io.InputStream
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.*
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.stream.Collectors
;
public
final
class
FileUtils
{
public
static
void
write
(
String
dest
,
byte
[]
bytes
)
{
...
...
@@ -32,10 +37,34 @@ public final class FileUtils {
return
new
byte
[
0
];
}
public
static
InputStream
readResourceAsStream
(
String
resourcePath
)
{
return
Grasscutter
.
class
.
getResourceAsStream
(
resourcePath
);
}
public
static
byte
[]
readResource
(
String
resourcePath
)
{
try
(
InputStream
is
=
Grasscutter
.
class
.
getResourceAsStream
(
resourcePath
))
{
return
is
.
readAllBytes
();
}
catch
(
Exception
exception
)
{
Grasscutter
.
getLogger
().
warn
(
"Failed to read resource: "
+
resourcePath
);
exception
.
printStackTrace
();
}
return
new
byte
[
0
];
}
public
static
byte
[]
read
(
File
file
)
{
return
read
(
file
.
getPath
());
}
public
static
void
copyResource
(
String
resourcePath
,
String
destination
)
{
try
{
byte
[]
resource
=
FileUtils
.
readResource
(
resourcePath
);
FileUtils
.
write
(
destination
,
resource
);
}
catch
(
Exception
exception
)
{
Grasscutter
.
getLogger
().
warn
(
"Failed to copy resource: "
+
resourcePath
+
"\n"
+
exception
);
}
}
public
static
String
getFilenameWithoutPath
(
String
fileName
)
{
if
(
fileName
.
indexOf
(
"."
)
>
0
)
{
...
...
@@ -44,4 +73,33 @@ public final class FileUtils {
return
fileName
;
}
}
// From https://mkyong.com/java/java-read-a-file-from-resources-folder/
public
static
List
<
Path
>
getPathsFromResource
(
String
folder
)
throws
URISyntaxException
,
IOException
{
List
<
Path
>
result
;
// get path of the current running JAR
String
jarPath
=
Grasscutter
.
class
.
getProtectionDomain
()
.
getCodeSource
()
.
getLocation
()
.
toURI
()
.
getPath
();
// file walks JAR
URI
uri
=
URI
.
create
(
"jar:file:"
+
jarPath
);
try
(
FileSystem
fs
=
FileSystems
.
newFileSystem
(
uri
,
Collections
.
emptyMap
()))
{
result
=
Files
.
walk
(
fs
.
getPath
(
folder
))
.
filter
(
Files:
:
isRegularFile
)
.
collect
(
Collectors
.
toList
());
}
return
result
;
}
@SuppressWarnings
(
"ResultOfMethodCallIgnored"
)
public
static
String
readToString
(
InputStream
file
)
throws
IOException
{
byte
[]
content
=
file
.
readAllBytes
();
return
new
String
(
content
,
StandardCharsets
.
UTF_8
);
}
}
src/main/java/emu/grasscutter/utils/Utils.java
View file @
fe4e5990
...
...
@@ -9,6 +9,7 @@ import java.time.temporal.TemporalAdjusters;
import
java.util.*
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.DataLoader
;
import
io.netty.buffer.ByteBuf
;
import
io.netty.buffer.ByteBufUtil
;
import
io.netty.buffer.Unpooled
;
...
...
@@ -198,6 +199,9 @@ public final class Utils {
if
(!
fileExists
(
dataFolder
))
createFolder
(
dataFolder
);
// Make sure the data folder is populated, if there are any missing files copy them from resources
DataLoader
.
CheckAllFiles
();
if
(
exit
)
System
.
exit
(
1
);
}
...
...
data/Banners.json
→
src/main/resources/defaults/
data/Banners.json
View file @
fe4e5990
File moved
data/Drop.json
→
src/main/resources/defaults/
data/Drop.json
View file @
fe4e5990
File moved
data/ExpeditionReward.json
→
src/main/resources/defaults/
data/ExpeditionReward.json
View file @
fe4e5990
File moved
Prev
1
2
3
Next
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