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
9eca5123
Commit
9eca5123
authored
Apr 22, 2022
by
Benjamin Elsdon
Browse files
Merge remote-tracking branch 'upstream/development' into development
parents
beb86751
0e7976f9
Changes
11
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
9eca5123
...
@@ -60,10 +60,14 @@ There is a dummy user named "Server" in every player's friends list that you can
...
@@ -60,10 +60,14 @@ There is a dummy user named "Server" in every player's friends list that you can
`!resetconst`
- Resets the constellation level on your current active character, will need to relog after using the command to see any changes.
`!resetconst`
- Resets the constellation level on your current active character, will need to relog after using the command to see any changes.
`!set
hp [hp]`
`!set
stats [stats] [amount]`
- Changes the current character's specified stat.
`!clearartifacts`
- Deletes all unequipped and unlocked level 0 artifacts,
**including yellow rarity ones**
from your inventory
`!clearartifacts`
- Deletes all unequipped and unlocked level 0 artifacts,
**including yellow rarity ones**
from your inventory
`!pos`
- Gets your current coordinate.
`!weather [weather id]`
- Changes the current weather.
*More commands will be updated in the [wiki](https://github.com/Melledy/Grasscutter/wiki/).*
*More commands will be updated in the [wiki](https://github.com/Melledy/Grasscutter/wiki/).*
### Bonus
### Bonus
...
...
proxy.py
View file @
9eca5123
...
@@ -16,12 +16,14 @@
...
@@ -16,12 +16,14 @@
# - mitmdump from mitmproxy
# - mitmdump from mitmproxy
#
#
# @author MlgmXyysd
# @author MlgmXyysd
# @version 1.
0
# @version 1.
1
#
#
##
##
from
mitmproxy
import
http
from
mitmproxy
import
http
from
proxy_config
import
USE_SSL
from
proxy_config
import
REMOTE_HOST
from
proxy_config
import
REMOTE_HOST
from
proxy_config
import
REMOTE_PORT
class
MlgmXyysd_Genshin_Impact_Proxy
:
class
MlgmXyysd_Genshin_Impact_Proxy
:
...
@@ -60,7 +62,12 @@ class MlgmXyysd_Genshin_Impact_Proxy:
...
@@ -60,7 +62,12 @@ class MlgmXyysd_Genshin_Impact_Proxy:
def
request
(
self
,
flow
:
http
.
HTTPFlow
)
->
None
:
def
request
(
self
,
flow
:
http
.
HTTPFlow
)
->
None
:
if
flow
.
request
.
host
in
self
.
LIST_DOMAINS
:
if
flow
.
request
.
host
in
self
.
LIST_DOMAINS
:
if
USE_SSL
:
flow
.
request
.
scheme
=
"https"
else
:
flow
.
request
.
scheme
=
"http"
flow
.
request
.
host
=
REMOTE_HOST
flow
.
request
.
host
=
REMOTE_HOST
flow
.
request
.
port
=
REMOTE_PORT
addons
=
[
addons
=
[
MlgmXyysd_Genshin_Impact_Proxy
()
MlgmXyysd_Genshin_Impact_Proxy
()
...
...
proxy_config.py
View file @
9eca5123
# This can also be replaced with another IP address.
# This can also be replaced with another IP address.
REMOTE_HOST
=
"localhost"
USE_SSL
=
True
\ No newline at end of file
REMOTE_HOST
=
"127.0.0.1"
REMOTE_PORT
=
443
\ No newline at end of file
src/main/java/emu/grasscutter/Config.java
View file @
9eca5123
...
@@ -6,7 +6,7 @@ public final class Config {
...
@@ -6,7 +6,7 @@ public final class Config {
public
String
DatabaseUrl
=
"mongodb://localhost:27017"
;
public
String
DatabaseUrl
=
"mongodb://localhost:27017"
;
public
String
DatabaseCollection
=
"grasscutter"
;
public
String
DatabaseCollection
=
"grasscutter"
;
public
String
RESOURCE_FOLDER
=
"./resources/"
;
public
String
RESOURCE_FOLDER
=
"./resources/"
;
public
String
DATA_FOLDER
=
"./data/"
;
public
String
DATA_FOLDER
=
"./data/"
;
public
String
PACKETS_FOLDER
=
"./packets/"
;
public
String
PACKETS_FOLDER
=
"./packets/"
;
...
@@ -24,11 +24,9 @@ public final class Config {
...
@@ -24,11 +24,9 @@ public final class Config {
public
DispatchServerOptions
getDispatchOptions
()
{
return
DispatchServer
;
}
public
DispatchServerOptions
getDispatchOptions
()
{
return
DispatchServer
;
}
public
static
class
DispatchServerOptions
{
public
static
class
DispatchServerOptions
{
public
String
Ip
=
"
127
.0.0.
1
"
;
public
String
Ip
=
"
0
.0.0.
0
"
;
public
String
PublicIp
=
""
;
public
String
PublicIp
=
"
127.0.0.1
"
;
public
int
Port
=
443
;
public
int
Port
=
443
;
public
int
OverseaLogPort
=
8888
;
public
int
UploadLogPort
=
80
;
public
String
KeystorePath
=
"./keystore.p12"
;
public
String
KeystorePath
=
"./keystore.p12"
;
public
String
KeystorePassword
=
""
;
public
String
KeystorePassword
=
""
;
public
Boolean
UseSSL
=
true
;
public
Boolean
UseSSL
=
true
;
...
@@ -51,8 +49,8 @@ public final class Config {
...
@@ -51,8 +49,8 @@ public final class Config {
public
static
class
GameServerOptions
{
public
static
class
GameServerOptions
{
public
String
Name
=
"Test"
;
public
String
Name
=
"Test"
;
public
String
Ip
=
"
127
.0.0.
1
"
;
public
String
Ip
=
"
0
.0.0.
0
"
;
public
String
PublicIp
=
""
;
public
String
PublicIp
=
"
127.0.0.1
"
;
public
int
Port
=
22102
;
public
int
Port
=
22102
;
public
String
DispatchServerDatabaseUrl
=
"mongodb://localhost:27017"
;
public
String
DispatchServerDatabaseUrl
=
"mongodb://localhost:27017"
;
...
...
src/main/java/emu/grasscutter/command/commands/GiveCommand.java
View file @
9eca5123
...
@@ -95,18 +95,19 @@ public final class GiveCommand implements CommandHandler {
...
@@ -95,18 +95,19 @@ public final class GiveCommand implements CommandHandler {
}
}
private
void
item
(
GenshinPlayer
player
,
ItemData
itemData
,
int
amount
)
{
private
void
item
(
GenshinPlayer
player
,
ItemData
itemData
,
int
amount
)
{
GenshinItem
genshinItem
=
new
GenshinItem
(
itemData
);
if
(
itemData
.
isEquip
())
{
if
(
itemData
.
isEquip
())
{
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
amount
;
i
++)
{
for
(
int
i
=
0
;
i
<
amount
;
i
++)
{
items
.
add
(
g
enshinItem
);
items
.
add
(
new
G
enshinItem
(
itemData
)
);
}
}
player
.
getInventory
().
addItems
(
items
);
player
.
getInventory
().
addItems
(
items
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
}
else
{
}
else
{
GenshinItem
genshinItem
=
new
GenshinItem
(
itemData
);
genshinItem
.
setCount
(
amount
);
genshinItem
.
setCount
(
amount
);
player
.
getInventory
().
addItem
(
genshinItem
);
player
.
getInventory
().
addItem
(
genshinItem
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
genshinItem
,
ActionReason
.
SubfieldDrop
));
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
genshinItem
,
ActionReason
.
SubfieldDrop
));
}
}
}
}
}
}
src/main/java/emu/grasscutter/command/commands/ListCommand.java
0 → 100644
View file @
9eca5123
package
emu.grasscutter.command.commands
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.game.GenshinPlayer
;
import
java.util.List
;
import
java.util.Map
;
@Command
(
label
=
"list"
,
description
=
"List online players"
)
public
class
ListCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
sender
,
List
<
String
>
args
)
{
Map
<
Integer
,
GenshinPlayer
>
playersMap
=
Grasscutter
.
getGameServer
().
getPlayers
();
CommandHandler
.
sendMessage
(
sender
,
String
.
format
(
"There are %s player(s) online:"
,
playersMap
.
size
()));
if
(
playersMap
.
size
()
!=
0
)
{
StringBuilder
playerSet
=
new
StringBuilder
();
for
(
Map
.
Entry
<
Integer
,
GenshinPlayer
>
entry
:
playersMap
.
entrySet
())
{
playerSet
.
append
(
entry
.
getValue
().
getNickname
());
playerSet
.
append
(
", "
);
}
String
players
=
playerSet
.
toString
();
CommandHandler
.
sendMessage
(
sender
,
players
.
substring
(
0
,
players
.
length
()
-
2
));
}
}
}
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
9eca5123
package
emu.grasscutter.server.dispatch
;
package
emu.grasscutter.server.dispatch
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.io.UnsupportedEncodingException
;
import
java.net.InetAddress
;
import
java.net.InetSocketAddress
;
import
java.net.URI
;
import
java.net.URLDecoder
;
import
java.security.KeyStore
;
import
java.util.*
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
com.google.gson.Gson
;
import
com.google.gson.Gson
;
import
com.google.gson.GsonBuilder
;
import
com.google.gson.GsonBuilder
;
import
com.google.protobuf.ByteString
;
import
com.google.protobuf.ByteString
;
import
com.sun.net.httpserver.HttpExchange
;
import
com.sun.net.httpserver.HttpExchange
;
import
com.sun.net.httpserver.Http
Handl
er
;
import
com.sun.net.httpserver.Http
Serv
er
;
import
com.sun.net.httpserver.HttpsConfigurator
;
import
com.sun.net.httpserver.HttpsConfigurator
;
import
com.sun.net.httpserver.HttpsServer
;
import
com.sun.net.httpserver.HttpsServer
;
...
@@ -31,29 +16,31 @@ import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegio
...
@@ -31,29 +16,31 @@ import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegio
import
emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp
;
import
emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp
;
import
emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo
;
import
emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo
;
import
emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo
;
import
emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson
;
import
emu.grasscutter.server.dispatch.json.*
;
import
emu.grasscutter.server.dispatch.json.ComboTokenResJson
;
import
emu.grasscutter.server.dispatch.json.LoginAccountRequestJson
;
import
emu.grasscutter.server.dispatch.json.LoginResultJson
;
import
emu.grasscutter.server.dispatch.json.LoginTokenRequestJson
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
import
com.sun.net.httpserver.HttpServer
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
java.io.*
;
import
java.net.InetSocketAddress
;
import
java.net.URI
;
import
java.net.URLDecoder
;
import
java.security.KeyStore
;
import
java.util.*
;
public
final
class
DispatchServer
{
public
final
class
DispatchServer
{
public
static
String
query_region_list
=
""
;
public
static
String
query_cur_region
=
""
;
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
private
final
Gson
gson
;
private
final
Gson
gson
;
private
final
String
defaultServerName
=
"os_usa"
;
private
final
String
defaultServerName
=
"os_usa"
;
//private QueryCurrRegionHttpRsp currRegion;
public
String
regionListBase64
;
public
String
regionListBase64
;
public
HashMap
<
String
,
RegionData
>
regions
;
public
HashMap
<
String
,
RegionData
>
regions
;
public
static
String
query_region_list
=
""
;
public
static
String
query_cur_region
=
""
;
public
DispatchServer
()
{
public
DispatchServer
()
{
this
.
regions
=
new
HashMap
<
String
,
RegionData
>();
this
.
regions
=
new
HashMap
<
String
,
RegionData
>();
this
.
address
=
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
,
Grasscutter
.
getConfig
().
getDispatchOptions
().
Port
);
this
.
address
=
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
,
Grasscutter
.
getConfig
().
getDispatchOptions
().
Port
);
...
@@ -77,7 +64,7 @@ public final class DispatchServer {
...
@@ -77,7 +64,7 @@ public final class DispatchServer {
return
regions
.
get
(
defaultServerName
).
parsedRegionQuery
;
return
regions
.
get
(
defaultServerName
).
parsedRegionQuery
;
}
}
Grasscutter
.
getLogger
().
error
(
"Ignore the error below
"
);
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] Unsupported run mode for getCurrRegion()
"
);
return
null
;
return
null
;
}
}
...
@@ -88,14 +75,14 @@ public final class DispatchServer {
...
@@ -88,14 +75,14 @@ public final class DispatchServer {
if
(
file
.
exists
())
{
if
(
file
.
exists
())
{
query_region_list
=
new
String
(
FileUtils
.
read
(
file
));
query_region_list
=
new
String
(
FileUtils
.
read
(
file
));
}
else
{
}
else
{
Grasscutter
.
getLogger
().
warn
(
"query_region_list not found! Using default region list."
);
Grasscutter
.
getLogger
().
warn
(
"
[Dispatch]
query_region_list not found! Using default region list."
);
}
}
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_cur_region.txt"
);
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_cur_region.txt"
);
if
(
file
.
exists
())
{
if
(
file
.
exists
())
{
query_cur_region
=
new
String
(
FileUtils
.
read
(
file
));
query_cur_region
=
new
String
(
FileUtils
.
read
(
file
));
}
else
{
}
else
{
Grasscutter
.
getLogger
().
warn
(
"query_cur_region not found! Using default current region."
);
Grasscutter
.
getLogger
().
warn
(
"
[Dispatch]
query_cur_region not found! Using default current region."
);
}
}
}
}
...
@@ -130,7 +117,7 @@ public final class DispatchServer {
...
@@ -130,7 +117,7 @@ public final class DispatchServer {
}
else
{
}
else
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
getGameServers
().
length
==
0
)
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
getGameServers
().
length
==
0
)
{
Grasscutter
.
getLogger
().
error
(
"Dispatch
server has
no game servers available. Exiting due to unplayable state."
);
Grasscutter
.
getLogger
().
error
(
"
[
Dispatch
] There are
no game servers available. Exiting due to unplayable state."
);
System
.
exit
(
1
);
System
.
exit
(
1
);
}
}
}
}
...
@@ -174,7 +161,7 @@ public final class DispatchServer {
...
@@ -174,7 +161,7 @@ public final class DispatchServer {
public
void
start
()
throws
Exception
{
public
void
start
()
throws
Exception
{
HttpServer
server
;
HttpServer
server
;
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
UseSSL
)
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
UseSSL
)
{
HttpsServer
httpsServer
;
HttpsServer
httpsServer
;
httpsServer
=
HttpsServer
.
create
(
getAddress
(),
0
);
httpsServer
=
HttpsServer
.
create
(
getAddress
(),
0
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
...
@@ -190,58 +177,36 @@ public final class DispatchServer {
...
@@ -190,58 +177,36 @@ public final class DispatchServer {
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
server
=
httpsServer
;
server
=
httpsServer
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"No SSL cert found!"
);
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] No SSL cert found! Falling back to HTTP server."
);
return
;
Grasscutter
.
getConfig
().
getDispatchOptions
().
UseSSL
=
false
;
server
=
HttpServer
.
create
(
getAddress
(),
0
);
}
}
}
else
{
}
else
{
server
=
HttpServer
.
create
(
getAddress
(),
0
);
server
=
HttpServer
.
create
(
getAddress
(),
0
);
}
}
server
.
createContext
(
"/"
,
t
->
{
server
.
createContext
(
"/"
,
t
->
responseHTML
(
t
,
"Hello"
));
//Create a response form the request query parameters
String
response
=
"Hello"
;
//Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
//Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
// Dispatch
// Dispatch
server
.
createContext
(
"/query_region_list"
,
t
->
{
server
.
createContext
(
"/query_region_list"
,
t
->
{
// Log
// Log
Grasscutter
.
getLogger
().
info
(
"Client request: query_region_list"
);
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s request: query_region_list"
,
t
.
getRemoteAddress
()));
// Create a response form the request query parameters
String
response
=
regionListBase64
;
responseHTML
(
t
,
regionListBase64
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
for
(
String
regionName
:
regions
.
keySet
())
{
for
(
String
regionName
:
regions
.
keySet
())
{
server
.
createContext
(
"/query_cur_region_"
+
regionName
,
t
->
{
server
.
createContext
(
"/query_cur_region_"
+
regionName
,
t
->
{
String
regionCurrentBase64
=
regions
.
get
(
regionName
).
Base64
;
String
regionCurrentBase64
=
regions
.
get
(
regionName
).
Base64
;
// Log
// Log
Grasscutter
.
getLogger
().
info
(
"Client request: query_cur_region_
"
+
regionName
);
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"Client
%s
request: query_cur_region_
%s"
,
t
.
getRemoteAddress
(),
regionName
)
)
;
// Create a response form the request query parameters
// Create a response form the request query parameters
URI
uri
=
t
.
getRequestURI
();
URI
uri
=
t
.
getRequestURI
();
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
if
(
uri
.
getQuery
()
!=
null
&&
uri
.
getQuery
().
length
()
>
0
)
{
if
(
uri
.
getQuery
()
!=
null
&&
uri
.
getQuery
().
length
()
>
0
)
{
response
=
regionCurrentBase64
;
response
=
regionCurrentBase64
;
}
}
// Set the response header status and length
responseHTML
(
t
,
response
);
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
}
}
...
@@ -252,14 +217,15 @@ public final class DispatchServer {
...
@@ -252,14 +217,15 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
ignored
)
{
}
}
// Create response json
// Create response json
if
(
requestData
==
null
)
{
if
(
requestData
==
null
)
{
return
;
return
;
}
}
LoginResultJson
responseData
=
new
LoginResultJson
();
LoginResultJson
responseData
=
new
LoginResultJson
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in"
,
t
.
getRemoteAddress
()));
// Login
// Login
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
...
@@ -270,14 +236,25 @@ public final class DispatchServer {
...
@@ -270,14 +236,25 @@ public final class DispatchServer {
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
AutomaticallyCreateAccounts
)
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
AutomaticallyCreateAccounts
)
{
// This account has been created AUTOMATICALLY. There will be no permissions added.
// This account has been created AUTOMATICALLY. There will be no permissions added.
account
=
DatabaseHelper
.
createAccountWithId
(
requestData
.
account
,
0
);
account
=
DatabaseHelper
.
createAccountWithId
(
requestData
.
account
,
0
);
responseData
.
message
=
"OK"
;
if
(
account
!=
null
)
{
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account %s created"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
else
{
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found, create failed."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account create failed"
,
t
.
getRemoteAddress
()));
}
}
else
{
}
else
{
responseData
.
retcode
=
-
201
;
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found."
;
responseData
.
message
=
"Username not found."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account no found"
,
t
.
getRemoteAddress
()));
}
}
}
else
{
}
else
{
// Account was found, log the player in
// Account was found, log the player in
...
@@ -285,17 +262,11 @@ public final class DispatchServer {
...
@@ -285,17 +262,11 @@ public final class DispatchServer {
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
}
// Create a response
responseJSON
(
t
,
responseData
);
String
response
=
getGsonFactory
().
toJson
(
responseData
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
// Login via token
// Login via token
server
.
createContext
(
"/hk4e_global/mdk/shield/api/verify"
,
t
->
{
server
.
createContext
(
"/hk4e_global/mdk/shield/api/verify"
,
t
->
{
...
@@ -304,14 +275,14 @@ public final class DispatchServer {
...
@@ -304,14 +275,14 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
ignored
)
{
}
}
// Create response json
// Create response json
if
(
requestData
==
null
)
{
if
(
requestData
==
null
)
{
return
;
return
;
}
}
LoginResultJson
responseData
=
new
LoginResultJson
();
LoginResultJson
responseData
=
new
LoginResultJson
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in via token"
,
t
.
getRemoteAddress
()));
// Login
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
...
@@ -320,22 +291,18 @@ public final class DispatchServer {
...
@@ -320,22 +291,18 @@ public final class DispatchServer {
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
responseData
.
retcode
=
-
111
;
responseData
.
retcode
=
-
111
;
responseData
.
message
=
"Game account cache information error"
;
responseData
.
message
=
"Game account cache information error"
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in via token"
,
t
.
getRemoteAddress
()));
}
else
{
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in via token as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
}
// Create a response
responseJSON
(
t
,
responseData
);
String
response
=
getGsonFactory
().
toJson
(
responseData
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
// Exchange for combo token
// Exchange for combo token
server
.
createContext
(
"/hk4e_global/combo/granter/login/v2/login"
,
t
->
{
server
.
createContext
(
"/hk4e_global/combo/granter/login/v2/login"
,
t
->
{
...
@@ -344,9 +311,8 @@ public final class DispatchServer {
...
@@ -344,9 +311,8 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
ignored
)
{
}
}
// Create response json
// Create response json
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
return
;
return
;
...
@@ -361,22 +327,18 @@ public final class DispatchServer {
...
@@ -361,22 +327,18 @@ public final class DispatchServer {
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
responseData
.
retcode
=
-
201
;
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Wrong session key."
;
responseData
.
message
=
"Wrong session key."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to exchange combo token"
,
t
.
getRemoteAddress
()));
}
else
{
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
message
=
"OK"
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s succeed to exchange combo token"
,
t
.
getRemoteAddress
()));
}
}
// Create a response
responseJSON
(
t
,
responseData
);
String
response
=
getGsonFactory
().
toJson
(
responseData
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
// Agreement and Protocol
// Agreement and Protocol
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
...
@@ -444,64 +406,74 @@ public final class DispatchServer {
...
@@ -444,64 +406,74 @@ public final class DispatchServer {
"/perf/config/verify"
,
"/perf/config/verify"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
// Start server
server
.
start
();
Grasscutter
.
getLogger
().
info
(
"Dispatch server started on port "
+
getAddress
().
getPort
());
// Logging servers
// Logging servers
HttpServer
overseaLogServer
=
HttpServer
.
create
(
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
,
Grasscutter
.
getConfig
().
getDispatchOptions
().
OverseaLogPort
),
0
);
server
.
createContext
(
// overseauspider.yuanshen.com
overseaLogServer
.
createContext
(
// overseauspider.yuanshen.com
"/log"
,
"/log"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
overseaLogServer
.
start
();
Grasscutter
.
getLogger
().
info
(
"Log server (overseauspider) started on port "
+
8888
);
server
.
createContext
(
// log-upload-os.mihoyo.com
"/crash/dataUpload"
,
HttpServer
uploadLogServer
=
HttpServer
.
create
(
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
,
Grasscutter
.
getConfig
().
getDispatchOptions
().
UploadLogPort
),
0
);
uploadLogServer
.
createContext
(
// log-upload-os.mihoyo.com
"/crash/dataUpload"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
uploadLogServer
.
createContext
(
"/gacha"
,
t
->
{
server
.
createContext
(
"/gacha"
,
t
->
responseHTML
(
t
,
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
));
//Create a response form the request query parameters
String
response
=
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
;
// Start server
//Set the response header status and length
server
.
start
();
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
Grasscutter
.
getLogger
().
info
(
"[Dispatch] Dispatch server started on port "
+
getAddress
().
getPort
());
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
}
//Write the response string
OutputStream
os
=
t
.
getResponseBody
();
private
void
responseJSON
(
HttpExchange
t
,
Object
data
)
throws
IOException
{
os
.
write
(
response
.
getBytes
());
// Create a response
os
.
close
();
String
response
=
getGsonFactory
().
toJson
(
data
);
});
// Set the response header status and length
uploadLogServer
.
start
();
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
Grasscutter
.
getLogger
().
info
(
"Log server (log-upload-os) started on port "
+
Grasscutter
.
getConfig
().
getDispatchOptions
().
UploadLogPort
);
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
}
private
void
responseHTML
(
HttpExchange
t
,
String
response
)
throws
IOException
{
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
//Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
}
}
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
Map
<
String
,
String
>
result
=
new
HashMap
<>();
Map
<
String
,
String
>
result
=
new
HashMap
<>();
if
(
qs
==
null
)
if
(
qs
==
null
)
{
return
result
;
return
result
;
}
int
last
=
0
,
next
,
l
=
qs
.
length
();
while
(
last
<
l
)
{
int
last
=
0
,
next
,
l
=
qs
.
length
();
next
=
qs
.
indexOf
(
'&'
,
last
);
while
(
last
<
l
)
{
if
(
next
==
-
1
)
next
=
qs
.
indexOf
(
'&'
,
last
);
next
=
l
;
if
(
next
==
-
1
)
{
next
=
l
;
if
(
next
>
last
)
{
}
int
eqPos
=
qs
.
indexOf
(
'='
,
last
);
try
{
if
(
next
>
last
)
{
if
(
eqPos
<
0
||
eqPos
>
next
)
int
eqPos
=
qs
.
indexOf
(
'='
,
last
);
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
next
),
"utf-8"
),
""
);
try
{
else
if
(
eqPos
<
0
||
eqPos
>
next
)
{
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
eqPos
),
"utf-8"
),
URLDecoder
.
decode
(
qs
.
substring
(
eqPos
+
1
,
next
),
"utf-8"
));
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
next
),
"utf-8"
),
""
);
}
catch
(
UnsupportedEncodingException
e
)
{
}
else
{
throw
new
RuntimeException
(
e
);
// will never happen, utf-8 support is mandatory for java
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
eqPos
),
"utf-8"
),
URLDecoder
.
decode
(
qs
.
substring
(
eqPos
+
1
,
next
),
"utf-8"
));
}
}
}
}
catch
(
UnsupportedEncodingException
e
)
{
last
=
next
+
1
;
throw
new
RuntimeException
(
e
);
// will never happen, utf-8 support is mandatory for java
}
}
return
result
;
}
last
=
next
+
1
;
}
return
result
;
}
}
public
static
class
RegionData
{
public
static
class
RegionData
{
...
...
src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java
View file @
9eca5123
...
@@ -7,7 +7,7 @@ public class ComboTokenReqJson {
...
@@ -7,7 +7,7 @@ public class ComboTokenReqJson {
public
String
device
;
public
String
device
;
public
String
sign
;
public
String
sign
;
public
class
LoginTokenData
{
public
static
class
LoginTokenData
{
public
String
uid
;
public
String
uid
;
public
String
token
;
public
String
token
;
public
boolean
guest
;
public
boolean
guest
;
...
...
src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java
View file @
9eca5123
...
@@ -5,7 +5,7 @@ public class ComboTokenResJson {
...
@@ -5,7 +5,7 @@ public class ComboTokenResJson {
public
int
retcode
;
public
int
retcode
;
public
LoginData
data
=
new
LoginData
();
public
LoginData
data
=
new
LoginData
();
public
class
LoginData
{
public
static
class
LoginData
{
public
int
account_type
=
1
;
public
int
account_type
=
1
;
public
boolean
heartbeat
;
public
boolean
heartbeat
;
public
String
combo_id
;
public
String
combo_id
;
...
...
src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java
View file @
9eca5123
...
@@ -5,7 +5,7 @@ public class LoginResultJson {
...
@@ -5,7 +5,7 @@ public class LoginResultJson {
public
int
retcode
;
public
int
retcode
;
public
VerifyData
data
=
new
VerifyData
();
public
VerifyData
data
=
new
VerifyData
();
public
class
VerifyData
{
public
static
class
VerifyData
{
public
VerifyAccountData
account
=
new
VerifyAccountData
();
public
VerifyAccountData
account
=
new
VerifyAccountData
();
public
boolean
device_grant_required
=
false
;
public
boolean
device_grant_required
=
false
;
public
String
realname_operation
=
"NONE"
;
public
String
realname_operation
=
"NONE"
;
...
@@ -13,7 +13,7 @@ public class LoginResultJson {
...
@@ -13,7 +13,7 @@ public class LoginResultJson {
public
boolean
safe_mobile_required
=
false
;
public
boolean
safe_mobile_required
=
false
;
}
}
public
class
VerifyAccountData
{
public
static
class
VerifyAccountData
{
public
String
uid
;
public
String
uid
;
public
String
name
=
""
;
public
String
name
=
""
;
public
String
email
;
public
String
email
;
...
...
src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java
View file @
9eca5123
...
@@ -12,7 +12,7 @@ public class PacketSceneUnlockInfoNotify extends GenshinPacket {
...
@@ -12,7 +12,7 @@ public class PacketSceneUnlockInfoNotify extends GenshinPacket {
SceneUnlockInfoNotify
proto
=
SceneUnlockInfoNotify
.
newBuilder
()
SceneUnlockInfoNotify
proto
=
SceneUnlockInfoNotify
.
newBuilder
()
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
1
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
1
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
3
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
3
)
.
addSceneTagIdList
(
102
).
addSceneTagIdList
(
113
).
addSceneTagIdList
(
117
)
)
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
4
).
addSceneTagIdList
(
106
).
addSceneTagIdList
(
109
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
4
).
addSceneTagIdList
(
106
).
addSceneTagIdList
(
109
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
5
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
5
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
6
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
6
))
...
...
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