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
358a888b
Commit
358a888b
authored
Apr 17, 2022
by
Melledy
Committed by
GitHub
Apr 17, 2022
Browse files
Merge pull request #1 from Melledy/refactor
Refactor existing code
parents
7925d1cd
8b5f7dd0
Changes
15
Hide whitespace changes
Inline
Side-by-side
src/main/java/META-INF/MANIFEST.MF
0 → 100644
View file @
358a888b
Manifest-Version: 1.0
Main-Class: emu.grasscutter.Grasscutter
src/main/java/emu/grasscutter/Config.java
View file @
358a888b
package
emu.grasscutter
;
package
emu.grasscutter
;
public
class
Config
{
public
final
class
Config
{
public
String
DispatchServerIp
=
"127.0.0.1"
;
public
String
DispatchServerIp
=
"127.0.0.1"
;
public
int
DispatchServerPort
=
443
;
public
int
DispatchServerPort
=
443
;
public
String
DispatchServerKeystorePath
=
"./keystore.p12"
;
public
String
DispatchServerKeystorePath
=
"./keystore.p12"
;
...
@@ -31,14 +31,14 @@ public class Config {
...
@@ -31,14 +31,14 @@ public class Config {
return
ServerOptions
;
return
ServerOptions
;
}
}
public
class
GameRates
{
public
static
class
GameRates
{
public
float
ADVENTURE_EXP_RATE
=
1.0f
;
public
float
ADVENTURE_EXP_RATE
=
1.0f
;
public
float
MORA_RATE
=
1.0f
;
public
float
MORA_RATE
=
1.0f
;
public
float
DOMAIN_DROP_RATE
=
1.0f
;
public
float
DOMAIN_DROP_RATE
=
1.0f
;
}
}
public
class
ServerOptions
{
public
static
class
ServerOptions
{
public
int
MaxEntityLimit
=
1000
;
// Max entity limit per world. TODO
Une
nforce
d for now
public
int
MaxEntityLimit
=
1000
;
// Max entity limit per world.
//
TODO
: E
nforce
later.
public
int
[]
WelcomeEmotes
=
{
2007
,
1002
,
4010
};
public
int
[]
WelcomeEmotes
=
{
2007
,
1002
,
4010
};
public
String
WelcomeMotd
=
"Welcome to Grasscutter emu"
;
public
String
WelcomeMotd
=
"Welcome to Grasscutter emu"
;
}
}
...
...
src/main/java/emu/grasscutter/GenshinConstants.java
View file @
358a888b
...
@@ -2,11 +2,10 @@ package emu.grasscutter;
...
@@ -2,11 +2,10 @@ package emu.grasscutter;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
emu.grasscutter.game.props.OpenState
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
public
class
GenshinConstants
{
public
final
class
GenshinConstants
{
public
static
String
VERSION
=
"2.6.0"
;
public
static
String
VERSION
=
"2.6.0"
;
public
static
final
int
MAX_TEAMS
=
4
;
public
static
final
int
MAX_TEAMS
=
4
;
...
@@ -25,9 +24,9 @@ public class GenshinConstants {
...
@@ -25,9 +24,9 @@ public class GenshinConstants {
public
static
final
int
MAX_FRIENDS
=
45
;
public
static
final
int
MAX_FRIENDS
=
45
;
public
static
final
int
MAX_FRIEND_REQUESTS
=
50
;
public
static
final
int
MAX_FRIEND_REQUESTS
=
50
;
public
static
final
int
SERVER_CONSOLE_UID
=
99
;
//
uid
of the
fake player used for commands
public
static
final
int
SERVER_CONSOLE_UID
=
99
;
//
The UID
of the
server console's "player".
// Default entity ability hashes
// Default entity ability hashes
.
public
static
final
String
[]
DEFAULT_ABILITY_STRINGS
=
{
public
static
final
String
[]
DEFAULT_ABILITY_STRINGS
=
{
"Avatar_DefaultAbility_VisionReplaceDieInvincible"
,
"Avatar_DefaultAbility_AvartarInShaderChange"
,
"Avatar_SprintBS_Invincible"
,
"Avatar_DefaultAbility_VisionReplaceDieInvincible"
,
"Avatar_DefaultAbility_AvartarInShaderChange"
,
"Avatar_SprintBS_Invincible"
,
"Avatar_Freeze_Duration_Reducer"
,
"Avatar_Attack_ReviveEnergy"
,
"Avatar_Component_Initializer"
,
"Avatar_FallAnthem_Achievement_Listener"
"Avatar_Freeze_Duration_Reducer"
,
"Avatar_Attack_ReviveEnergy"
,
"Avatar_Component_Initializer"
,
"Avatar_FallAnthem_Achievement_Listener"
...
...
src/main/java/emu/grasscutter/Grasscutter.java
View file @
358a888b
...
@@ -6,8 +6,8 @@ import java.io.FileReader;
...
@@ -6,8 +6,8 @@ import java.io.FileReader;
import
java.io.FileWriter
;
import
java.io.FileWriter
;
import
java.io.InputStreamReader
;
import
java.io.InputStreamReader
;
import
java.net.InetSocketAddress
;
import
java.net.InetSocketAddress
;
import
java.util.Arrays
;
import
emu.grasscutter.utils.Utils
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
com.google.gson.Gson
;
import
com.google.gson.Gson
;
...
@@ -22,19 +22,25 @@ import emu.grasscutter.server.game.GameServer;
...
@@ -22,19 +22,25 @@ import emu.grasscutter.server.game.GameServer;
import
emu.grasscutter.tools.Tools
;
import
emu.grasscutter.tools.Tools
;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.Crypto
;
public
class
Grasscutter
{
public
final
class
Grasscutter
{
private
static
Logger
log
=
(
Logger
)
LoggerFactory
.
getLogger
(
Grasscutter
.
class
);
private
static
final
Logger
log
=
(
Logger
)
LoggerFactory
.
getLogger
(
Grasscutter
.
class
);
private
static
Config
config
;
private
static
Config
config
;
private
static
Gson
gson
=
new
GsonBuilder
().
setPrettyPrinting
().
create
();
private
static
final
Gson
gson
=
new
GsonBuilder
().
setPrettyPrinting
().
create
();
private
static
File
configFile
=
new
File
(
"./config.json"
);
private
static
final
File
configFile
=
new
File
(
"./config.json"
);
public
static
RunMode
MODE
=
RunMode
.
BOTH
;
public
static
RunMode
MODE
=
RunMode
.
BOTH
;
private
static
DispatchServer
dispatchServer
;
private
static
DispatchServer
dispatchServer
;
private
static
GameServer
gameServer
;
private
static
GameServer
gameServer
;
static
{
// Load configuration.
Grasscutter
.
loadConfig
();
// Check server structure.
Utils
.
startupCheck
();
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Grasscutter
.
loadConfig
();
Crypto
.
loadKeys
();
Crypto
.
loadKeys
();
for
(
String
arg
:
args
)
{
for
(
String
arg
:
args
)
{
...
@@ -48,56 +54,34 @@ public class Grasscutter {
...
@@ -48,56 +54,34 @@ public class Grasscutter {
case
"-handbook"
:
case
"-handbook"
:
Tools
.
createGmHandbook
();
Tools
.
createGmHandbook
();
return
;
return
;
}
}
}
}
//
Startup
//
Initialize server.
Grasscutter
.
getLogger
().
info
(
"Grasscutter
Emu
"
);
Grasscutter
.
getLogger
().
info
(
"
Starting
Grasscutter
...
"
);
// Load resource
file
s
// Load
all
resources
.
ResourceLoader
.
loadAll
();
ResourceLoader
.
loadAll
();
// Database
// Database
DatabaseManager
.
initialize
();
DatabaseManager
.
initialize
();
//
Run
servers
//
Start
servers
.
dispatchServer
=
new
DispatchServer
();
dispatchServer
=
new
DispatchServer
();
dispatchServer
.
start
();
dispatchServer
.
start
();
gameServer
=
new
GameServer
(
new
InetSocketAddress
(
getConfig
().
GameServerIp
,
getConfig
().
GameServerPort
));
gameServer
=
new
GameServer
(
new
InetSocketAddress
(
getConfig
().
GameServerIp
,
getConfig
().
GameServerPort
));
gameServer
.
start
();
gameServer
.
start
();
// Open console.
startConsole
();
startConsole
();
}
}
public
static
Config
getConfig
()
{
return
config
;
}
public
static
Logger
getLogger
()
{
return
log
;
}
public
static
Gson
getGsonFactory
()
{
return
gson
;
}
public
static
DispatchServer
getDispatchServer
()
{
return
dispatchServer
;
}
public
static
GameServer
getGameServer
()
{
return
gameServer
;
}
public
static
void
loadConfig
()
{
public
static
void
loadConfig
()
{
try
(
FileReader
file
=
new
FileReader
(
configFile
))
{
try
(
FileReader
file
=
new
FileReader
(
configFile
))
{
config
=
gson
.
fromJson
(
file
,
Config
.
class
);
config
=
gson
.
fromJson
(
file
,
Config
.
class
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
config
=
new
Config
();
Grasscutter
.
config
=
new
Config
();
saveConfig
();
}
}
saveConfig
();
}
}
public
static
void
saveConfig
()
{
public
static
void
saveConfig
()
{
...
@@ -115,7 +99,7 @@ public class Grasscutter {
...
@@ -115,7 +99,7 @@ public class Grasscutter {
ServerCommands
.
handle
(
input
);
ServerCommands
.
handle
(
input
);
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"
Console error:
"
,
e
);
Grasscutter
.
getLogger
().
error
(
"
An error occurred.
"
,
e
);
}
}
}
}
...
@@ -124,4 +108,24 @@ public class Grasscutter {
...
@@ -124,4 +108,24 @@ public class Grasscutter {
AUTH
,
AUTH
,
GAME
GAME
}
}
public
static
Config
getConfig
()
{
return
config
;
}
public
static
Logger
getLogger
()
{
return
log
;
}
public
static
Gson
getGsonFactory
()
{
return
gson
;
}
public
static
DispatchServer
getDispatchServer
()
{
return
dispatchServer
;
}
public
static
GameServer
getGameServer
()
{
return
gameServer
;
}
}
}
src/main/java/emu/grasscutter/commands/Command.java
View file @
358a888b
...
@@ -5,9 +5,9 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -5,9 +5,9 @@ import java.lang.annotation.RetentionPolicy;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Command
{
public
@interface
Command
{
public
String
[]
aliases
()
default
""
;
String
[]
aliases
()
default
""
;
public
int
gmLevel
()
default
1
;
int
gmLevel
()
default
1
;
public
String
helpText
()
default
""
;
String
helpText
()
default
""
;
}
}
src/main/java/emu/grasscutter/database/DatabaseManager.java
View file @
358a888b
package
emu.grasscutter.database
;
package
emu.grasscutter.database
;
import
java.sql.Connection
;
import
java.sql.SQLException
;
import
com.mongodb.MongoClient
;
import
com.mongodb.MongoClient
;
import
com.mongodb.MongoClientURI
;
import
com.mongodb.MongoClientURI
;
import
com.mongodb.MongoCommandException
;
import
com.mongodb.MongoCommandException
;
...
@@ -18,12 +15,11 @@ import emu.grasscutter.game.avatar.GenshinAvatar;
...
@@ -18,12 +15,11 @@ import emu.grasscutter.game.avatar.GenshinAvatar;
import
emu.grasscutter.game.friends.Friendship
;
import
emu.grasscutter.game.friends.Friendship
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.inventory.GenshinItem
;
public
class
DatabaseManager
{
public
final
class
DatabaseManager
{
private
static
MongoClient
mongoClient
;
private
static
MongoClient
mongoClient
;
private
static
Morphia
morphia
;
private
static
Datastore
datastore
;
private
static
Datastore
datastore
;
private
static
Class
<?>[]
mappedClasses
=
new
Class
<?>[]
{
private
static
final
Class
<?>[]
mappedClasses
=
new
Class
<?>[]
{
DatabaseCounter
.
class
,
Account
.
class
,
GenshinPlayer
.
class
,
GenshinAvatar
.
class
,
GenshinItem
.
class
,
Friendship
.
class
DatabaseCounter
.
class
,
Account
.
class
,
GenshinPlayer
.
class
,
GenshinAvatar
.
class
,
GenshinItem
.
class
,
Friendship
.
class
};
};
...
@@ -38,15 +34,11 @@ public class DatabaseManager {
...
@@ -38,15 +34,11 @@ public class DatabaseManager {
public
static
MongoDatabase
getDatabase
()
{
public
static
MongoDatabase
getDatabase
()
{
return
getDatastore
().
getDatabase
();
return
getDatastore
().
getDatabase
();
}
}
public
static
Connection
getConnection
()
throws
SQLException
{
return
null
;
}
public
static
void
initialize
()
{
public
static
void
initialize
()
{
// Initialize
// Initialize
mongoClient
=
new
MongoClient
(
new
MongoClientURI
(
Grasscutter
.
getConfig
().
DatabaseUrl
));
mongoClient
=
new
MongoClient
(
new
MongoClientURI
(
Grasscutter
.
getConfig
().
DatabaseUrl
));
morphia
=
new
Morphia
();
Morphia
morphia
=
new
Morphia
();
// TODO Update when migrating to Morphia 2.0
// TODO Update when migrating to Morphia 2.0
morphia
.
getMapper
().
getOptions
().
setStoreEmpties
(
true
);
morphia
.
getMapper
().
getOptions
().
setStoreEmpties
(
true
);
...
...
src/main/java/emu/grasscutter/server/dispatch/DispatchHttpJsonHandler.java
View file @
358a888b
...
@@ -7,7 +7,7 @@ import java.util.Collections;
...
@@ -7,7 +7,7 @@ import java.util.Collections;
import
com.sun.net.httpserver.HttpExchange
;
import
com.sun.net.httpserver.HttpExchange
;
import
com.sun.net.httpserver.HttpHandler
;
import
com.sun.net.httpserver.HttpHandler
;
public
class
DispatchHttpJsonHandler
implements
HttpHandler
{
public
final
class
DispatchHttpJsonHandler
implements
HttpHandler
{
private
final
String
response
;
private
final
String
response
;
public
DispatchHttpJsonHandler
(
String
response
)
{
public
DispatchHttpJsonHandler
(
String
response
)
{
...
@@ -24,5 +24,4 @@ public class DispatchHttpJsonHandler implements HttpHandler {
...
@@ -24,5 +24,4 @@ public class DispatchHttpJsonHandler implements HttpHandler {
os
.
write
(
response
.
getBytes
());
os
.
write
(
response
.
getBytes
());
os
.
close
();
os
.
close
();
}
}
}
}
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
358a888b
...
@@ -43,8 +43,7 @@ import emu.grasscutter.utils.Utils;
...
@@ -43,8 +43,7 @@ import emu.grasscutter.utils.Utils;
import
com.sun.net.httpserver.HttpServer
;
import
com.sun.net.httpserver.HttpServer
;
public
class
DispatchServer
{
public
final
class
DispatchServer
{
private
HttpsServer
server
;
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
private
final
Gson
gson
;
private
final
Gson
gson
;
private
QueryCurrRegionHttpRsp
currRegion
;
private
QueryCurrRegionHttpRsp
currRegion
;
...
@@ -135,12 +134,12 @@ public class DispatchServer {
...
@@ -135,12 +134,12 @@ public class DispatchServer {
this
.
regionCurrentBase64
=
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
());
this
.
regionCurrentBase64
=
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
());
this
.
currRegion
=
parsedRegionQuery
;
this
.
currRegion
=
parsedRegionQuery
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
);
Grasscutter
.
getLogger
().
error
(
"Error while initializing region info!"
,
e
);
}
}
}
}
public
void
start
()
throws
Exception
{
public
void
start
()
throws
Exception
{
server
=
HttpsServer
.
create
(
getAddress
(),
0
);
HttpsServer
server
=
HttpsServer
.
create
(
getAddress
(),
0
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
DispatchServerKeystorePath
))
{
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
DispatchServerKeystorePath
))
{
...
@@ -158,187 +157,169 @@ public class DispatchServer {
...
@@ -158,187 +157,169 @@ public class DispatchServer {
return
;
return
;
}
}
server
.
createContext
(
"/"
,
new
HttpHandler
()
{
server
.
createContext
(
"/"
,
t
->
{
@Override
//Create a response form the request query parameters
public
void
handle
(
HttpExchange
t
)
throws
IOException
{
String
response
=
"Hello"
;
//Create a response form the request query parameters
//Set the response header status and length
String
response
=
"Hello"
;
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
//Set the response header status and length
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
//Write the response string
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
OutputStream
os
=
t
.
getResponseBody
();
//Write the response string
os
.
write
(
response
.
getBytes
());
OutputStream
os
=
t
.
getResponseBody
();
os
.
close
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
}
});
});
// Dispatch
// Dispatch
server
.
createContext
(
"/query_region_list"
,
new
HttpHandler
()
{
server
.
createContext
(
"/query_region_list"
,
t
->
{
@Override
// Log
public
void
handle
(
HttpExchange
t
)
throws
IOException
{
Grasscutter
.
getLogger
().
info
(
"Client request: query_region_list"
);
// Log
// Create a response form the request query parameters
Grasscutter
.
getLogger
().
info
(
"Client request: query_region_list"
);
String
response
=
regionListBase64
;
// Create a response form the request query parameters
// Set the response header status and length
String
response
=
regionListBase64
;
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
// Set the response header status and length
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
// Write the response string
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
OutputStream
os
=
t
.
getResponseBody
();
// Write the response string
os
.
write
(
response
.
getBytes
());
OutputStream
os
=
t
.
getResponseBody
();
os
.
close
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
}
});
});
server
.
createContext
(
"/query_cur_region"
,
new
HttpHandler
()
{
server
.
createContext
(
"/query_cur_region"
,
t
->
{
@Override
// Log
public
void
handle
(
HttpExchange
t
)
throws
IOException
{
Grasscutter
.
getLogger
().
info
(
"Client request: query_cur_region"
);
// Log
// Create a response form the request query parameters
Grasscutter
.
getLogger
().
info
(
"Client request: query_cur_region"
);
URI
uri
=
t
.
getRequestURI
();
// Create a response form the request query parameters
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
URI
uri
=
t
.
getRequestURI
();
if
(
uri
.
getQuery
()
!=
null
&&
uri
.
getQuery
().
length
()
>
0
)
{
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
response
=
regionCurrentBase64
;
if
(
uri
.
getQuery
()
!=
null
&&
uri
.
getQuery
().
length
()
>
0
)
{
response
=
regionCurrentBase64
;
}
// 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
();
}
}
// 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
();
});
});
// Login via account
// Login via account
server
.
createContext
(
"/hk4e_global/mdk/shield/api/login"
,
new
HttpHandler
()
{
server
.
createContext
(
"/hk4e_global/mdk/shield/api/login"
,
t
->
{
@Override
// Get post data
public
void
handle
(
HttpExchange
t
)
throws
IOException
{
LoginAccountRequestJson
requestData
=
null
;
// Get post data
try
{
LoginAccountRequestJson
requestData
=
null
;
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
try
{
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
}
catch
(
Exception
e
)
{
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
}
catch
(
Exception
e
)
{
}
// Create response json
if
(
requestData
==
null
)
{
return
;
}
LoginResultJson
responseData
=
new
LoginResultJson
();
// Login
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
// Test
if
(
account
==
null
)
{
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found."
;
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
}
// Create a response
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
();
}
}
// Create response json
if
(
requestData
==
null
)
{
return
;
}
LoginResultJson
responseData
=
new
LoginResultJson
();
// Login
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
// Test
if
(
account
==
null
)
{
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found."
;
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
}
// Create a response
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"
,
new
HttpHandler
()
{
server
.
createContext
(
"/hk4e_global/mdk/shield/api/verify"
,
t
->
{
@Override
// Get post data
public
void
handle
(
HttpExchange
t
)
throws
IOException
{
LoginTokenRequestJson
requestData
=
null
;
// Get post data
try
{
LoginTokenRequestJson
requestData
=
null
;
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
try
{
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
}
catch
(
Exception
e
)
{
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
}
catch
(
Exception
e
)
{
}
// Create response json
if
(
requestData
==
null
)
{
return
;
}
LoginResultJson
responseData
=
new
LoginResultJson
();
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
// Test
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
responseData
.
retcode
=
-
111
;
responseData
.
message
=
"Game account cache information error"
;
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
}
// Create a response
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
();
}
}
// Create response json
if
(
requestData
==
null
)
{
return
;
}
LoginResultJson
responseData
=
new
LoginResultJson
();
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
// Test
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
responseData
.
retcode
=
-
111
;
responseData
.
message
=
"Game account cache information error"
;
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
}
// Create a response
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"
,
new
HttpHandler
()
{
server
.
createContext
(
"/hk4e_global/combo/granter/login/v2/login"
,
t
->
{
@Override
// Get post data
public
void
handle
(
HttpExchange
t
)
throws
IOException
{
ComboTokenReqJson
requestData
=
null
;
// Get post data
try
{
ComboTokenReqJson
requestData
=
null
;
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
try
{
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
}
catch
(
Exception
e
)
{
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
}
catch
(
Exception
e
)
{
}
// Create response json
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
return
;
}
LoginTokenData
loginData
=
getGsonFactory
().
fromJson
(
requestData
.
data
,
LoginTokenData
.
class
);
// Get login data
ComboTokenResJson
responseData
=
new
ComboTokenResJson
();
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
loginData
.
uid
);
// Test
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Wrong session key."
;
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
}
// Create a response
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
();
}
}
// Create response json
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
return
;
}
LoginTokenData
loginData
=
getGsonFactory
().
fromJson
(
requestData
.
data
,
LoginTokenData
.
class
);
// Get login data
ComboTokenResJson
responseData
=
new
ComboTokenResJson
();
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
loginData
.
uid
);
// Test
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Wrong session key."
;
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
}
// Create a response
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
...
@@ -420,19 +401,16 @@ public class DispatchServer {
...
@@ -420,19 +401,16 @@ public class DispatchServer {
"/crash/dataUpload"
,
"/crash/dataUpload"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
uploadLogServer
.
createContext
(
"/gacha"
,
new
HttpHandler
()
{
uploadLogServer
.
createContext
(
"/gacha"
,
t
->
{
@Override
//Create a response form the request query parameters
public
void
handle
(
HttpExchange
t
)
throws
IOException
{
String
response
=
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
;
//Create a response form the request query parameters
//Set the response header status and length
String
response
=
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
;
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
//Set the response header status and length
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
//Write the response string
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
OutputStream
os
=
t
.
getResponseBody
();
//Write the response string
os
.
write
(
response
.
getBytes
());
OutputStream
os
=
t
.
getResponseBody
();
os
.
close
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
}
});
});
uploadLogServer
.
start
();
uploadLogServer
.
start
();
Grasscutter
.
getLogger
().
info
(
"Log server (log-upload-os) started on port "
+
80
);
Grasscutter
.
getLogger
().
info
(
"Log server (log-upload-os) started on port "
+
80
);
...
...
src/main/java/emu/grasscutter/tools/Dumpers.java
View file @
358a888b
...
@@ -8,10 +8,8 @@ import emu.grasscutter.game.props.OpenState;
...
@@ -8,10 +8,8 @@ import emu.grasscutter.game.props.OpenState;
import
emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp
;
import
emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp
;
import
emu.grasscutter.net.proto.GetShopRspOuterClass.GetShopRsp
;
import
emu.grasscutter.net.proto.GetShopRspOuterClass.GetShopRsp
;
import
emu.grasscutter.net.proto.OpenStateUpdateNotifyOuterClass.OpenStateUpdateNotify
;
import
emu.grasscutter.net.proto.OpenStateUpdateNotifyOuterClass.OpenStateUpdateNotify
;
import
emu.grasscutter.utils.FileUtils
;
public
class
Dumpers
{
public
final
class
Dumpers
{
public
static
void
extractBanner
(
byte
[]
data
)
throws
Exception
{
public
static
void
extractBanner
(
byte
[]
data
)
throws
Exception
{
GetGachaInfoRsp
proto
=
GetGachaInfoRsp
.
parseFrom
(
data
);
GetGachaInfoRsp
proto
=
GetGachaInfoRsp
.
parseFrom
(
data
);
System
.
out
.
println
(
proto
);
System
.
out
.
println
(
proto
);
...
...
src/main/java/emu/grasscutter/tools/Tools.java
View file @
358a888b
...
@@ -5,6 +5,7 @@ import java.io.FileWriter;
...
@@ -5,6 +5,7 @@ import java.io.FileWriter;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.time.format.DateTimeFormatter
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -20,7 +21,7 @@ import emu.grasscutter.data.def.AvatarData;
...
@@ -20,7 +21,7 @@ import emu.grasscutter.data.def.AvatarData;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.data.def.MonsterData
;
public
class
Tools
{
public
final
class
Tools
{
@SuppressWarnings
(
"deprecation"
)
@SuppressWarnings
(
"deprecation"
)
public
static
void
createGmHandbook
()
throws
Exception
{
public
static
void
createGmHandbook
()
throws
Exception
{
...
@@ -40,7 +41,7 @@ public class Tools {
...
@@ -40,7 +41,7 @@ public class Tools {
writer
.
println
(
"// Genshin Impact "
+
GenshinConstants
.
VERSION
+
" GM Handbook"
);
writer
.
println
(
"// Genshin Impact "
+
GenshinConstants
.
VERSION
+
" GM Handbook"
);
writer
.
println
(
"// Created "
+
dtf
.
format
(
now
)
+
System
.
lineSeparator
()
+
System
.
lineSeparator
());
writer
.
println
(
"// Created "
+
dtf
.
format
(
now
)
+
System
.
lineSeparator
()
+
System
.
lineSeparator
());
list
=
GenshinData
.
getAvatarDataMap
().
keySet
()
.
stream
().
collect
(
Collectors
.
toList
()
);
list
=
new
ArrayList
<>(
GenshinData
.
getAvatarDataMap
().
keySet
());
Collections
.
sort
(
list
);
Collections
.
sort
(
list
);
writer
.
println
(
"// Avatars"
);
writer
.
println
(
"// Avatars"
);
...
@@ -51,7 +52,7 @@ public class Tools {
...
@@ -51,7 +52,7 @@ public class Tools {
writer
.
println
();
writer
.
println
();
list
=
GenshinData
.
getItemDataMap
().
keySet
()
.
stream
().
collect
(
Collectors
.
toList
()
);
list
=
new
ArrayList
<>(
GenshinData
.
getItemDataMap
().
keySet
());
Collections
.
sort
(
list
);
Collections
.
sort
(
list
);
writer
.
println
(
"// Items"
);
writer
.
println
(
"// Items"
);
...
@@ -63,7 +64,7 @@ public class Tools {
...
@@ -63,7 +64,7 @@ public class Tools {
writer
.
println
();
writer
.
println
();
writer
.
println
(
"// Monsters"
);
writer
.
println
(
"// Monsters"
);
list
=
GenshinData
.
getMonsterDataMap
().
keySet
()
.
stream
().
collect
(
Collectors
.
toList
()
);
list
=
new
ArrayList
<>(
GenshinData
.
getMonsterDataMap
().
keySet
());
Collections
.
sort
(
list
);
Collections
.
sort
(
list
);
for
(
Integer
id
:
list
)
{
for
(
Integer
id
:
list
)
{
...
...
src/main/java/emu/grasscutter/utils/Crypto.java
View file @
358a888b
...
@@ -7,8 +7,8 @@ import emu.grasscutter.Grasscutter;
...
@@ -7,8 +7,8 @@ import emu.grasscutter.Grasscutter;
import
emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp
;
import
emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp
;
import
emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp
;
import
emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp
;
public
class
Crypto
{
public
final
class
Crypto
{
private
static
SecureRandom
secureRandom
=
new
SecureRandom
();
private
static
final
SecureRandom
secureRandom
=
new
SecureRandom
();
public
static
final
long
ENCRYPT_SEED
=
Long
.
parseUnsignedLong
(
"11468049314633205968"
);
public
static
final
long
ENCRYPT_SEED
=
Long
.
parseUnsignedLong
(
"11468049314633205968"
);
public
static
byte
[]
ENCRYPT_SEED_BUFFER
=
new
byte
[
0
];
public
static
byte
[]
ENCRYPT_SEED_BUFFER
=
new
byte
[
0
];
...
@@ -37,8 +37,7 @@ public class Crypto {
...
@@ -37,8 +37,7 @@ public class Crypto {
FileUtils
.
write
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"secretKeyBuffer.bin"
,
p
.
getSecretKeyBuffer
().
toByteArray
());
FileUtils
.
write
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"secretKeyBuffer.bin"
,
p
.
getSecretKeyBuffer
().
toByteArray
());
Grasscutter
.
getLogger
().
info
(
"Secret Key: "
+
p
.
getSecretKey
());
Grasscutter
.
getLogger
().
info
(
"Secret Key: "
+
p
.
getSecretKey
());
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
// TODO Auto-generated catch block
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
e
.
printStackTrace
();
}
}
}
}
...
@@ -47,7 +46,7 @@ public class Crypto {
...
@@ -47,7 +46,7 @@ public class Crypto {
QueryCurrRegionHttpRsp
p
=
QueryCurrRegionHttpRsp
.
parseFrom
(
Base64
.
getDecoder
().
decode
(
data
));
QueryCurrRegionHttpRsp
p
=
QueryCurrRegionHttpRsp
.
parseFrom
(
Base64
.
getDecoder
().
decode
(
data
));
FileUtils
.
write
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
,
p
.
getRegionInfo
().
getSecretKey
().
toByteArray
());
FileUtils
.
write
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
,
p
.
getRegionInfo
().
getSecretKey
().
toByteArray
());
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
);
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
}
}
}
}
...
...
src/main/java/emu/grasscutter/utils/FileUtils.java
View file @
358a888b
package
emu.grasscutter.utils
;
package
emu.grasscutter.utils
;
import
emu.grasscutter.Grasscutter
;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.nio.file.Paths
;
public
class
FileUtils
{
public
final
class
FileUtils
{
public
static
void
write
(
String
dest
,
byte
[]
bytes
)
{
public
static
void
write
(
String
dest
,
byte
[]
bytes
)
{
Path
path
=
Paths
.
get
(
dest
);
Path
path
=
Paths
.
get
(
dest
);
try
{
try
{
Files
.
write
(
path
,
bytes
);
Files
.
write
(
path
,
bytes
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
// TODO Auto-generated catch block
Grasscutter
.
getLogger
().
warn
(
"Failed to write file: "
+
dest
);
e
.
printStackTrace
();
}
}
}
}
...
@@ -27,8 +27,7 @@ public class FileUtils {
...
@@ -27,8 +27,7 @@ public class FileUtils {
try
{
try
{
return
Files
.
readAllBytes
(
path
);
return
Files
.
readAllBytes
(
path
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
// TODO Auto-generated catch block
Grasscutter
.
getLogger
().
warn
(
"Failed to read file: "
+
path
);
e
.
printStackTrace
();
}
}
return
new
byte
[
0
];
return
new
byte
[
0
];
...
...
src/main/java/emu/grasscutter/utils/ProtoHelper.java
View file @
358a888b
...
@@ -3,7 +3,7 @@ package emu.grasscutter.utils;
...
@@ -3,7 +3,7 @@ package emu.grasscutter.utils;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.net.proto.PropValueOuterClass.PropValue
;
import
emu.grasscutter.net.proto.PropValueOuterClass.PropValue
;
public
class
ProtoHelper
{
public
final
class
ProtoHelper
{
public
static
PropValue
newPropValue
(
PlayerProperty
key
,
int
value
)
{
public
static
PropValue
newPropValue
(
PlayerProperty
key
,
int
value
)
{
return
PropValue
.
newBuilder
().
setType
(
key
.
getId
()).
setIval
(
value
).
setVal
(
value
).
build
();
return
PropValue
.
newBuilder
().
setType
(
key
.
getId
()).
setIval
(
value
).
setVal
(
value
).
build
();
}
}
...
...
src/main/java/emu/grasscutter/utils/Utils.java
View file @
358a888b
package
emu.grasscutter.utils
;
package
emu.grasscutter.utils
;
import
java.io.BufferedInputStream
;
import
java.io.*
;
import
java.io.ByteArrayOutputStream
;
import
java.nio.file.Files
;
import
java.io.IOException
;
import
java.nio.file.StandardCopyOption
;
import
java.io.InputStream
;
import
java.util.Random
;
import
java.util.Random
;
import
emu.grasscutter.Config
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
io.netty.buffer.ByteBuf
;
import
io.netty.buffer.ByteBuf
;
import
io.netty.buffer.ByteBufUtil
;
import
io.netty.buffer.ByteBufUtil
;
import
io.netty.buffer.Unpooled
;
import
io.netty.buffer.Unpooled
;
import
org.slf4j.Logger
;
public
class
Utils
{
@SuppressWarnings
({
"UnusedReturnValue"
,
"BooleanMethodIsAlwaysInverted"
})
public
final
class
Utils
{
public
static
final
Random
random
=
new
Random
();
public
static
final
Random
random
=
new
Random
();
public
static
int
randomRange
(
int
min
,
int
max
)
{
public
static
int
randomRange
(
int
min
,
int
max
)
{
...
@@ -76,4 +78,77 @@ public class Utils {
...
@@ -76,4 +78,77 @@ public class Utils {
}
}
return
v7
;
return
v7
;
}
}
/**
* Checks if a file exists on the file system.
* @param path The path to the file.
* @return True if the file exists, false otherwise.
*/
public
static
boolean
fileExists
(
String
path
)
{
return
new
File
(
path
).
exists
();
}
/**
* Creates a folder on the file system.
* @param path The path to the folder.
* @return True if the folder was created, false otherwise.
*/
public
static
boolean
createFolder
(
String
path
)
{
return
new
File
(
path
).
mkdirs
();
}
/**
* Copies a file from the archive's resources to the file system.
* @param resource The path to the resource.
* @param destination The path to copy the resource to.
* @return True if the file was copied, false otherwise.
*/
public
static
boolean
copyFromResources
(
String
resource
,
String
destination
)
{
try
(
InputStream
stream
=
Grasscutter
.
class
.
getResourceAsStream
(
resource
))
{
if
(
stream
==
null
)
{
Grasscutter
.
getLogger
().
warn
(
"Could not find resource: "
+
resource
);
return
false
;
}
Files
.
copy
(
stream
,
new
File
(
destination
).
toPath
(),
StandardCopyOption
.
REPLACE_EXISTING
);
return
true
;
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
warn
(
"Unable to copy resource "
+
resource
+
" to "
+
destination
,
e
);
return
false
;
}
}
/**
* Checks for required files and folders before startup.
*/
public
static
void
startupCheck
()
{
Config
config
=
Grasscutter
.
getConfig
();
Logger
logger
=
Grasscutter
.
getLogger
();
boolean
exit
=
false
;
String
resourcesFolder
=
config
.
RESOURCE_FOLDER
;
String
dataFolder
=
config
.
DATA_FOLDER
;
// Check for resources folder.
if
(!
fileExists
(
resourcesFolder
))
{
logger
.
info
(
"Creating resources folder..."
);
logger
.
info
(
"Place a copy of 'GenshinData' in the resources folder."
);
createFolder
(
resourcesFolder
);
exit
=
true
;
}
// Check for GenshinData.
if
(!
fileExists
(
resourcesFolder
+
"BinOutput"
)
||
!
fileExists
(
resourcesFolder
+
"ExcelBinOutput"
))
{
logger
.
info
(
"Place a copy of 'GenshinData' in the resources folder."
);
exit
=
true
;
}
// Check for game data.
if
(!
fileExists
(
dataFolder
))
createFolder
(
dataFolder
);
if
(!
fileExists
(
dataFolder
+
"AbilityEmbryos.json"
))
copyFromResources
(
"data/AbilityEmbryos.json"
,
dataFolder
);
if
(
exit
)
System
.
exit
(
1
);
}
}
}
src/main/
java
/logback.xml
→
src/main/
resources
/logback.xml
View file @
358a888b
File moved
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