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
a505b041
Commit
a505b041
authored
Apr 25, 2022
by
Magix
Committed by
GitHub
Apr 25, 2022
Browse files
Merge pull request #135 from Grasscutters/plugin-system
Implement a plugin system
parents
b6fedcf2
dce13cf6
Changes
20
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/Config.java
View file @
a505b041
package
emu.grasscutter
;
package
emu.grasscutter
;
import
java.util.ArrayList
;
public
final
class
Config
{
public
final
class
Config
{
public
String
DatabaseUrl
=
"mongodb://localhost:27017"
;
public
String
DatabaseUrl
=
"mongodb://localhost:27017"
;
...
@@ -12,6 +10,7 @@ public final class Config {
...
@@ -12,6 +10,7 @@ public final class Config {
public
String
PACKETS_FOLDER
=
"./packets/"
;
public
String
PACKETS_FOLDER
=
"./packets/"
;
public
String
DUMPS_FOLDER
=
"./dumps/"
;
public
String
DUMPS_FOLDER
=
"./dumps/"
;
public
String
KEY_FOLDER
=
"./keys/"
;
public
String
KEY_FOLDER
=
"./keys/"
;
public
String
PLUGINS_FOLDER
=
"./plugins/"
;
public
String
RunMode
=
"HYBRID"
;
// HYBRID, DISPATCH_ONLY, GAME_ONLY
public
String
RunMode
=
"HYBRID"
;
// HYBRID, DISPATCH_ONLY, GAME_ONLY
public
GameServerOptions
GameServer
=
new
GameServerOptions
();
public
GameServerOptions
GameServer
=
new
GameServerOptions
();
...
...
src/main/java/emu/grasscutter/Grasscutter.java
View file @
a505b041
...
@@ -8,6 +8,7 @@ import java.io.InputStreamReader;
...
@@ -8,6 +8,7 @@ import java.io.InputStreamReader;
import
java.net.InetSocketAddress
;
import
java.net.InetSocketAddress
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.plugin.PluginManager
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
import
org.reflections.Reflections
;
import
org.reflections.Reflections
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
...
@@ -33,8 +34,9 @@ public final class Grasscutter {
...
@@ -33,8 +34,9 @@ public final class Grasscutter {
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
;
private
static
PluginManager
pluginManager
;
public
static
final
Reflections
reflector
=
new
Reflections
(
"emu.grasscutter"
);
public
static
final
Reflections
reflector
=
new
Reflections
();
static
{
static
{
// Declare logback configuration.
// Declare logback configuration.
...
@@ -52,15 +54,11 @@ public final class Grasscutter {
...
@@ -52,15 +54,11 @@ public final class Grasscutter {
for
(
String
arg
:
args
)
{
for
(
String
arg
:
args
)
{
switch
(
arg
.
toLowerCase
())
{
switch
(
arg
.
toLowerCase
())
{
case
"-auth"
:
case
"-auth"
->
MODE
=
RunMode
.
AUTH
;
MODE
=
RunMode
.
AUTH
;
case
"-game"
->
MODE
=
RunMode
.
GAME
;
break
;
case
"-handbook"
->
{
case
"-game"
:
Tools
.
createGmHandbook
();
return
;
MODE
=
RunMode
.
GAME
;
}
break
;
case
"-handbook"
:
Tools
.
createGmHandbook
();
return
;
}
}
}
}
...
@@ -71,19 +69,21 @@ public final class Grasscutter {
...
@@ -71,19 +69,21 @@ public final class Grasscutter {
ResourceLoader
.
loadAll
();
ResourceLoader
.
loadAll
();
// Database
// Database
DatabaseManager
.
initialize
();
DatabaseManager
.
initialize
();
// Create server instances.
dispatchServer
=
new
DispatchServer
();
gameServer
=
new
GameServer
(
new
InetSocketAddress
(
getConfig
().
getGameServerOptions
().
Ip
,
getConfig
().
getGameServerOptions
().
Port
));
// Create plugin manager instance.
pluginManager
=
new
PluginManager
();
// Start servers.
// Start servers.
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
dispatchServer
=
new
DispatchServer
();
dispatchServer
.
start
();
dispatchServer
.
start
();
gameServer
=
new
GameServer
(
new
InetSocketAddress
(
getConfig
().
getGameServerOptions
().
Ip
,
getConfig
().
getGameServerOptions
().
Port
));
gameServer
.
start
();
gameServer
.
start
();
}
else
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"DISPATCH_ONLY"
))
{
}
else
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"DISPATCH_ONLY"
))
{
dispatchServer
=
new
DispatchServer
();
dispatchServer
.
start
();
dispatchServer
.
start
();
}
else
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"GAME_ONLY"
))
{
}
else
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"GAME_ONLY"
))
{
gameServer
=
new
GameServer
(
new
InetSocketAddress
(
getConfig
().
getGameServerOptions
().
Ip
,
getConfig
().
getGameServerOptions
().
Port
));
gameServer
.
start
();
gameServer
.
start
();
}
else
{
}
else
{
getLogger
().
error
(
"Invalid server run mode. "
+
getConfig
().
RunMode
);
getLogger
().
error
(
"Invalid server run mode. "
+
getConfig
().
RunMode
);
...
@@ -91,12 +91,23 @@ public final class Grasscutter {
...
@@ -91,12 +91,23 @@ public final class Grasscutter {
getLogger
().
error
(
"Shutting down..."
);
getLogger
().
error
(
"Shutting down..."
);
System
.
exit
(
1
);
System
.
exit
(
1
);
}
}
// Enable all plugins.
pluginManager
.
enablePlugins
();
// Open console.
// Open console.
startConsole
();
startConsole
();
// Hook into shutdown event.
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(
Grasscutter:
:
onShutdown
));
}
}
/**
* Server shutdown event.
*/
private
static
void
onShutdown
()
{
// Disable all plugins.
pluginManager
.
disablePlugins
();
}
public
static
void
loadConfig
()
{
public
static
void
loadConfig
()
{
try
(
FileReader
file
=
new
FileReader
(
configFile
))
{
try
(
FileReader
file
=
new
FileReader
(
configFile
))
{
...
@@ -112,7 +123,7 @@ public final class Grasscutter {
...
@@ -112,7 +123,7 @@ public final class Grasscutter {
try
(
FileWriter
file
=
new
FileWriter
(
configFile
))
{
try
(
FileWriter
file
=
new
FileWriter
(
configFile
))
{
file
.
write
(
gson
.
toJson
(
config
));
file
.
write
(
gson
.
toJson
(
config
));
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"
Config save error
"
);
Grasscutter
.
getLogger
().
error
(
"
Unable to save config file.
"
);
}
}
}
}
...
@@ -123,13 +134,13 @@ public final class Grasscutter {
...
@@ -123,13 +134,13 @@ public final class Grasscutter {
while
((
input
=
br
.
readLine
())
!=
null
)
{
while
((
input
=
br
.
readLine
())
!=
null
)
{
try
{
try
{
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"DISPATCH_ONLY"
))
{
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"DISPATCH_ONLY"
))
{
getLogger
().
error
(
"Commands are not supported in dispatch only mode"
);
getLogger
().
error
(
"Commands are not supported in dispatch only mode
.
"
);
return
;
return
;
}
}
CommandMap
.
getInstance
().
invoke
(
null
,
input
);
CommandMap
.
getInstance
().
invoke
(
null
,
input
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Command error: "
);
Grasscutter
.
getLogger
().
error
(
"Command error:"
,
e
);
e
.
printStackTrace
();
}
}
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
...
@@ -162,4 +173,8 @@ public final class Grasscutter {
...
@@ -162,4 +173,8 @@ public final class Grasscutter {
public
static
GameServer
getGameServer
()
{
public
static
GameServer
getGameServer
()
{
return
gameServer
;
return
gameServer
;
}
}
public
static
PluginManager
getPluginManager
()
{
return
pluginManager
;
}
}
}
src/main/java/emu/grasscutter/plugin/Plugin.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.plugin
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.server.game.GameServer
;
/**
* The base class for all plugins to extend.
*/
public
abstract
class
Plugin
{
private
PluginIdentifier
identifier
;
/**
* This method is reflected into.
*
* Set plugin variables.
* @param identifier The plugin's identifier.
*/
private
void
initializePlugin
(
PluginIdentifier
identifier
)
{
if
(
this
.
identifier
==
null
)
this
.
identifier
=
identifier
;
else
Grasscutter
.
getLogger
().
warn
(
this
.
identifier
.
name
+
" had a reinitialization attempt."
);
}
/**
* The plugin's identifier instance.
* @return An instance of {@link PluginIdentifier}.
*/
public
final
PluginIdentifier
getIdentifier
(){
return
this
.
identifier
;
}
/**
* Get the plugin's name.
*/
public
final
String
getName
()
{
return
this
.
identifier
.
name
;
}
/**
* Get the plugin's description.
*/
public
final
String
getDescription
()
{
return
this
.
identifier
.
description
;
}
/**
* Get the plugin's version.
*/
public
final
String
getVersion
()
{
return
this
.
identifier
.
version
;
}
/**
* Returns the server that initialized the plugin.
* @return A server instance.
*/
public
final
GameServer
getServer
()
{
return
Grasscutter
.
getGameServer
();
}
/* Called when the plugin is first loaded. */
public
void
onLoad
()
{
}
/* Called after (most of) the server enables. */
public
void
onEnable
()
{
}
/* Called before the server disables. */
public
void
onDisable
()
{
}
}
src/main/java/emu/grasscutter/plugin/PluginConfig.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.plugin
;
/**
* The data contained in the plugin's `plugin.json` file.
*/
public
final
class
PluginConfig
{
public
String
name
,
description
,
version
;
public
String
mainClass
;
public
String
[]
authors
;
/**
* Attempts to validate this config instance.
* @return True if the config is valid, false otherwise.
*/
public
boolean
validate
()
{
return
name
!=
null
&&
description
!=
null
&&
mainClass
!=
null
;
}
}
src/main/java/emu/grasscutter/plugin/PluginIdentifier.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.plugin
;
// TODO: Potentially replace with Lombok?
public
final
class
PluginIdentifier
{
public
final
String
name
,
description
,
version
;
public
final
String
[]
authors
;
public
PluginIdentifier
(
String
name
,
String
description
,
String
version
,
String
[]
authors
)
{
this
.
name
=
name
;
this
.
description
=
description
;
this
.
version
=
version
;
this
.
authors
=
authors
;
}
/**
* Converts a {@link PluginConfig} into a {@link PluginIdentifier}.
*/
public
static
PluginIdentifier
fromPluginConfig
(
PluginConfig
config
)
{
if
(!
config
.
validate
())
throw
new
IllegalArgumentException
(
"A valid plugin config is required to convert into a plugin identifier."
);
return
new
PluginIdentifier
(
config
.
name
,
config
.
description
,
config
.
version
,
config
.
authors
);
}
}
src/main/java/emu/grasscutter/plugin/PluginManager.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.plugin
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.server.event.Event
;
import
emu.grasscutter.server.event.EventHandler
;
import
emu.grasscutter.server.event.Listener
;
import
emu.grasscutter.utils.Utils
;
import
org.reflections.Reflections
;
import
java.io.File
;
import
java.io.InputStreamReader
;
import
java.lang.reflect.Method
;
import
java.net.URL
;
import
java.net.URLClassLoader
;
import
java.util.*
;
/**
* Manages the server's plugins & the event system.
*/
public
final
class
PluginManager
{
private
final
Map
<
String
,
Plugin
>
plugins
=
new
HashMap
<>();
private
final
Map
<
Plugin
,
List
<
Listener
>>
listeners
=
new
HashMap
<>();
public
PluginManager
()
{
this
.
loadPlugins
();
// Load all plugins from the plugins directory.
}
/**
* Loads plugins from the config-specified directory.
*/
private
void
loadPlugins
()
{
String
directory
=
Grasscutter
.
getConfig
().
PLUGINS_FOLDER
;
File
pluginsDir
=
new
File
(
Utils
.
toFilePath
(
directory
));
if
(!
pluginsDir
.
exists
()
&&
!
pluginsDir
.
mkdirs
())
{
Grasscutter
.
getLogger
().
error
(
"Failed to create plugins directory: "
+
pluginsDir
.
getAbsolutePath
());
return
;
}
File
[]
files
=
pluginsDir
.
listFiles
();
if
(
files
==
null
)
{
// The directory is empty, there aren't any plugins to load.
return
;
}
List
<
File
>
plugins
=
Arrays
.
stream
(
files
)
.
filter
(
file
->
file
.
getName
().
endsWith
(
".jar"
))
.
toList
();
plugins
.
forEach
(
plugin
->
{
try
{
URL
url
=
plugin
.
toURI
().
toURL
();
try
(
URLClassLoader
loader
=
new
URLClassLoader
(
new
URL
[]{
url
}))
{
URL
configFile
=
loader
.
findResource
(
"plugin.json"
);
InputStreamReader
fileReader
=
new
InputStreamReader
(
configFile
.
openStream
());
PluginConfig
pluginConfig
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
PluginConfig
.
class
);
if
(!
pluginConfig
.
validate
())
{
Utils
.
logObject
(
pluginConfig
);
Grasscutter
.
getLogger
().
warn
(
"Plugin "
+
plugin
.
getName
()
+
" has an invalid config file."
);
return
;
}
Class
<?>
pluginClass
=
loader
.
loadClass
(
pluginConfig
.
mainClass
);
Plugin
pluginInstance
=
(
Plugin
)
pluginClass
.
getDeclaredConstructor
().
newInstance
();
this
.
loadPlugin
(
pluginInstance
,
PluginIdentifier
.
fromPluginConfig
(
pluginConfig
));
fileReader
.
close
();
// Close the file reader.
}
catch
(
ClassNotFoundException
ignored
)
{
Grasscutter
.
getLogger
().
warn
(
"Plugin "
+
plugin
.
getName
()
+
" has an invalid main class."
);
}
}
catch
(
Exception
exception
)
{
Grasscutter
.
getLogger
().
error
(
"Failed to load plugin: "
+
plugin
.
getName
(),
exception
);
}
});
}
/**
* Load the specified plugin.
* @param plugin The plugin instance.
*/
private
void
loadPlugin
(
Plugin
plugin
,
PluginIdentifier
identifier
)
{
Grasscutter
.
getLogger
().
info
(
"Loading plugin: "
+
identifier
.
name
);
// Add the plugin's identifier.
try
{
Class
<
Plugin
>
pluginClass
=
Plugin
.
class
;
Method
method
=
pluginClass
.
getDeclaredMethod
(
"initializePlugin"
,
PluginIdentifier
.
class
);
method
.
setAccessible
(
true
);
method
.
invoke
(
plugin
,
identifier
);
method
.
setAccessible
(
false
);
}
catch
(
Exception
ignored
)
{
Grasscutter
.
getLogger
().
warn
(
"Failed to add plugin identifier: "
+
identifier
.
name
);
}
// Add the plugin to the list of loaded plugins.
this
.
plugins
.
put
(
identifier
.
name
,
plugin
);
// Call the plugin's onLoad method.
plugin
.
onLoad
();
}
/**
* Enables all registered plugins.
*/
public
void
enablePlugins
()
{
this
.
plugins
.
forEach
((
name
,
plugin
)
->
{
Grasscutter
.
getLogger
().
info
(
"Enabling plugin: "
+
name
);
plugin
.
onEnable
();
});
}
/**
* Disables all registered plugins.
*/
public
void
disablePlugins
()
{
this
.
plugins
.
forEach
((
name
,
plugin
)
->
{
Grasscutter
.
getLogger
().
info
(
"Disabling plugin: "
+
name
);
plugin
.
onDisable
();
});
}
/**
* Registers a plugin's event listener.
* @param plugin The plugin instance.
* @param listener The event listener.
*/
public
void
registerListener
(
Plugin
plugin
,
Listener
listener
)
{
this
.
listeners
.
computeIfAbsent
(
plugin
,
k
->
new
ArrayList
<>()).
add
(
listener
);
}
/**
* Invoke the provided event on all registered event listeners.
* @param event The event to invoke.
*/
public
void
invokeEvent
(
Event
event
)
{
this
.
listeners
.
values
().
stream
()
.
flatMap
(
Collection:
:
stream
)
.
forEach
(
listener
->
this
.
invokeOnListener
(
listener
,
event
));
}
/**
* Attempts to invoke the event on the provided listener.
*/
private
void
invokeOnListener
(
Listener
listener
,
Event
event
)
{
try
{
Class
<?>
listenerClass
=
listener
.
getClass
();
Method
[]
methods
=
listenerClass
.
getMethods
();
for
(
Method
method
:
methods
)
{
if
(!
method
.
isAnnotationPresent
(
EventHandler
.
class
))
return
;
if
(!
method
.
getParameterTypes
()[
0
].
isAssignableFrom
(
event
.
getClass
()))
return
;
method
.
invoke
(
listener
,
event
);
}
}
catch
(
Exception
ignored
)
{
}
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
a505b041
...
@@ -18,6 +18,8 @@ import emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo;
...
@@ -18,6 +18,8 @@ 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.*
;
import
emu.grasscutter.server.dispatch.json.*
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData
;
import
emu.grasscutter.server.event.dispatch.QueryAllRegionsEvent
;
import
emu.grasscutter.server.event.dispatch.QueryCurrentRegionEvent
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
...
@@ -277,7 +279,11 @@ public final class DispatchServer {
...
@@ -277,7 +279,11 @@ public final class DispatchServer {
if
(
uri
.
getQuery
()
!=
null
&&
uri
.
getQuery
().
length
()
>
0
)
{
if
(
uri
.
getQuery
()
!=
null
&&
uri
.
getQuery
().
length
()
>
0
)
{
response
=
regionCurrentBase64
;
response
=
regionCurrentBase64
;
}
}
responseHTML
(
t
,
response
);
// Invoke event.
QueryCurrentRegionEvent
event
=
new
QueryCurrentRegionEvent
(
response
);
event
.
call
();
// Respond with event result.
responseHTML
(
t
,
event
.
getRegionInfo
());
});
});
}
}
...
...
src/main/java/emu/grasscutter/server/event/Cancellable.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event
;
/**
* Implementing this interface marks an event as cancellable.
*/
public
interface
Cancellable
{
void
cancel
();
}
src/main/java/emu/grasscutter/server/event/Event.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event
;
import
emu.grasscutter.Grasscutter
;
/**
* A generic server event.
*/
public
abstract
class
Event
{
private
boolean
cancelled
=
false
;
/**
* Return the cancelled state of the event.
*/
public
boolean
isCanceled
()
{
return
this
.
cancelled
;
}
/**
* Cancels the event if possible.
*/
public
void
cancel
()
{
if
(
this
instanceof
Cancellable
)
this
.
cancelled
=
true
;
}
/**
* Pushes this event to all listeners.
*/
public
void
call
()
{
Grasscutter
.
getPluginManager
().
invokeEvent
(
this
);
}
}
src/main/java/emu/grasscutter/server/event/EventHandler.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
/**
* Declares a class as an event listener/handler.
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
EventHandler
{
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/event/Listener.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event
;
/**
* Implementing this interface declares a class as an event listener.
*/
public
interface
Listener
{
}
src/main/java/emu/grasscutter/server/event/ServerEvent.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event
;
/**
* An event that is related to the internals of the server.
*/
public
abstract
class
ServerEvent
extends
Event
{
protected
final
Type
type
;
public
ServerEvent
(
Type
type
)
{
this
.
type
=
type
;
}
public
enum
Type
{
DISPATCH
,
GAME
}
}
src/main/java/emu/grasscutter/server/event/dispatch/QueryAllRegionsEvent.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event.dispatch
;
import
emu.grasscutter.server.event.ServerEvent
;
public
final
class
QueryAllRegionsEvent
extends
ServerEvent
{
private
String
regionList
;
public
QueryAllRegionsEvent
(
String
regionList
)
{
super
(
Type
.
DISPATCH
);
this
.
regionList
=
regionList
;
}
public
void
setRegionList
(
String
regionList
)
{
this
.
regionList
=
regionList
;
}
public
String
getRegionList
()
{
return
this
.
regionList
;
}
}
src/main/java/emu/grasscutter/server/event/dispatch/QueryCurrentRegionEvent.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event.dispatch
;
import
emu.grasscutter.server.event.ServerEvent
;
public
final
class
QueryCurrentRegionEvent
extends
ServerEvent
{
private
String
regionInfo
;
public
QueryCurrentRegionEvent
(
String
regionInfo
)
{
super
(
Type
.
DISPATCH
);
this
.
regionInfo
=
regionInfo
;
}
public
void
setRegionInfo
(
String
regionInfo
)
{
this
.
regionInfo
=
regionInfo
;
}
public
String
getRegionInfo
()
{
return
this
.
regionInfo
;
}
}
src/main/java/emu/grasscutter/server/event/game/ReceivePacketEvent.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event.game
;
import
emu.grasscutter.server.event.Cancellable
;
import
emu.grasscutter.server.event.ServerEvent
;
import
emu.grasscutter.server.game.GameSession
;
public
final
class
ReceivePacketEvent
extends
ServerEvent
implements
Cancellable
{
private
final
GameSession
gameSession
;
private
final
int
packetId
;
private
byte
[]
packetData
;
public
ReceivePacketEvent
(
GameSession
gameSession
,
int
packetId
,
byte
[]
packetData
)
{
super
(
Type
.
GAME
);
this
.
gameSession
=
gameSession
;
this
.
packetId
=
packetId
;
this
.
packetData
=
packetData
;
}
public
GameSession
getGameSession
()
{
return
this
.
gameSession
;
}
public
int
getPacketId
()
{
return
this
.
packetId
;
}
public
void
setPacketData
(
byte
[]
packetData
)
{
this
.
packetData
=
packetData
;
}
public
byte
[]
getPacketData
()
{
return
this
.
packetData
;
}
}
src/main/java/emu/grasscutter/server/event/game/SendPacketEvent.java
0 → 100644
View file @
a505b041
package
emu.grasscutter.server.event.game
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.server.event.Cancellable
;
import
emu.grasscutter.server.event.ServerEvent
;
import
emu.grasscutter.server.game.GameSession
;
public
final
class
SendPacketEvent
extends
ServerEvent
implements
Cancellable
{
private
final
GameSession
gameSession
;
private
GenshinPacket
packet
;
public
SendPacketEvent
(
GameSession
gameSession
,
GenshinPacket
packet
)
{
super
(
Type
.
GAME
);
this
.
gameSession
=
gameSession
;
this
.
packet
=
packet
;
}
public
GameSession
getGameSession
()
{
return
this
.
gameSession
;
}
public
void
setPacket
(
GenshinPacket
packet
)
{
this
.
packet
=
packet
;
}
public
GenshinPacket
getPacket
()
{
return
this
.
packet
;
}
}
src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java
View file @
a505b041
...
@@ -2,6 +2,7 @@ package emu.grasscutter.server.game;
...
@@ -2,6 +2,7 @@ package emu.grasscutter.server.game;
import
java.util.Set
;
import
java.util.Set
;
import
emu.grasscutter.server.event.game.ReceivePacketEvent
;
import
org.reflections.Reflections
;
import
org.reflections.Reflections
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
...
@@ -48,9 +49,7 @@ public class GameServerPacketHandler {
...
@@ -48,9 +49,7 @@ public class GameServerPacketHandler {
}
}
public
void
handle
(
GameSession
session
,
int
opcode
,
byte
[]
header
,
byte
[]
payload
)
{
public
void
handle
(
GameSession
session
,
int
opcode
,
byte
[]
header
,
byte
[]
payload
)
{
PacketHandler
handler
=
null
;
PacketHandler
handler
=
this
.
handlers
.
get
(
opcode
);
handler
=
this
.
handlers
.
get
(
opcode
);
if
(
handler
!=
null
)
{
if
(
handler
!=
null
)
{
try
{
try
{
...
@@ -77,8 +76,10 @@ public class GameServerPacketHandler {
...
@@ -77,8 +76,10 @@ public class GameServerPacketHandler {
}
}
}
}
// Handle
// Invoke event.
handler
.
handle
(
session
,
header
,
payload
);
ReceivePacketEvent
event
=
new
ReceivePacketEvent
(
session
,
opcode
,
payload
);
event
.
call
();
if
(!
event
.
isCanceled
())
// If event is not canceled, continue.
handler
.
handle
(
session
,
header
,
event
.
getPacketData
());
}
catch
(
Exception
ex
)
{
}
catch
(
Exception
ex
)
{
// TODO Remove this when no more needed
// TODO Remove this when no more needed
ex
.
printStackTrace
();
ex
.
printStackTrace
();
...
...
src/main/java/emu/grasscutter/server/game/GameSession.java
View file @
a505b041
...
@@ -10,6 +10,7 @@ import emu.grasscutter.game.GenshinPlayer;
...
@@ -10,6 +10,7 @@ import emu.grasscutter.game.GenshinPlayer;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.packet.PacketOpcodesUtil
;
import
emu.grasscutter.net.packet.PacketOpcodesUtil
;
import
emu.grasscutter.netty.MihoyoKcpChannel
;
import
emu.grasscutter.netty.MihoyoKcpChannel
;
import
emu.grasscutter.server.event.game.SendPacketEvent
;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
...
@@ -161,16 +162,15 @@ public class GameSession extends MihoyoKcpChannel {
...
@@ -161,16 +162,15 @@ public class GameSession extends MihoyoKcpChannel {
genshinPacket
.
buildHeader
(
this
.
getNextClientSequence
());
genshinPacket
.
buildHeader
(
this
.
getNextClientSequence
());
}
}
// Build packet
byte
[]
data
=
genshinPacket
.
build
();
// Log
// Log
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
logPacket
(
genshinPacket
);
logPacket
(
genshinPacket
);
}
}
// Send
// Invoke event.
send
(
data
);
SendPacketEvent
event
=
new
SendPacketEvent
(
this
,
genshinPacket
);
event
.
call
();
if
(!
event
.
isCanceled
())
// If event is not cancelled, continue.
this
.
send
(
event
.
getPacket
().
build
());
}
}
private
void
logPacket
(
int
opcode
)
{
private
void
logPacket
(
int
opcode
)
{
...
...
src/main/java/emu/grasscutter/utils/Utils.java
View file @
a505b041
...
@@ -137,6 +137,15 @@ public final class Utils {
...
@@ -137,6 +137,15 @@ public final class Utils {
return
nonNull
!=
null
?
nonNull
:
fallback
;
return
nonNull
!=
null
?
nonNull
:
fallback
;
}
}
/**
* Logs an object to the console.
* @param object The object to log.
*/
public
static
void
logObject
(
Object
object
)
{
String
asJson
=
Grasscutter
.
getGsonFactory
().
toJson
(
object
);
Grasscutter
.
getLogger
().
info
(
asJson
);
}
/**
/**
* Checks for required files and folders before startup.
* Checks for required files and folders before startup.
*/
*/
...
...
src/main/
java
/META-INF/MANIFEST.MF
→
src/main/
resources
/META-INF/MANIFEST.MF
View file @
a505b041
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