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
01b190bc
Commit
01b190bc
authored
May 07, 2022
by
Magix
Committed by
GitHub
May 07, 2022
Browse files
UPGRADE TO 1.1.0 POG
Merge `development` into `stable`
parents
6b81b888
1beddf16
Changes
497
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/server/event/player/PlayerQuitEvent.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.event.player
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.types.GameEvent
;
import
emu.grasscutter.server.event.types.PlayerEvent
;
public
final
class
PlayerQuitEvent
extends
PlayerEvent
{
public
PlayerQuitEvent
(
Player
player
)
{
super
(
player
);
}
}
src/main/java/emu/grasscutter/server/event/player/PlayerReceiveMailEvent.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.event.player
;
import
emu.grasscutter.game.mail.Mail
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.Cancellable
;
import
emu.grasscutter.server.event.types.PlayerEvent
;
public
final
class
PlayerReceiveMailEvent
extends
PlayerEvent
implements
Cancellable
{
private
Mail
message
;
public
PlayerReceiveMailEvent
(
Player
player
,
Mail
message
)
{
super
(
player
);
this
.
message
=
message
;
}
public
void
setMessage
(
Mail
message
)
{
this
.
message
=
message
;
}
public
Mail
getMessage
()
{
return
this
.
message
;
}
}
src/main/java/emu/grasscutter/server/event/types/GameEvent.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.event.types
;
import
emu.grasscutter.server.event.Event
;
/**
* An event that is related to the game.
*/
public
abstract
class
GameEvent
extends
Event
{
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/event/types/PlayerEvent.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.event.types
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.Event
;
/**
* An event that is related to player interactions.
*/
public
abstract
class
PlayerEvent
extends
Event
{
protected
final
Player
player
;
public
PlayerEvent
(
Player
player
)
{
this
.
player
=
player
;
}
public
Player
getPlayer
()
{
return
this
.
player
;
}
}
src/main/java/emu/grasscutter/server/event/types/ServerEvent.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.event.types
;
import
emu.grasscutter.server.event.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
Type
getServerType
()
{
return
this
.
type
;
}
public
enum
Type
{
DISPATCH
,
GAME
}
}
src/main/java/emu/grasscutter/server/game/GameServer.java
View file @
01b190bc
package
emu.grasscutter.server.game
;
package
emu.grasscutter.server.game
;
import
java.net.InetSocketAddress
;
import
emu.grasscutter.GameConstants
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
emu.grasscutter.GenshinConstants
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.combine.CombineManger
;
import
emu.grasscutter.game.drop.DropManager
;
import
emu.grasscutter.game.dungeons.DungeonManager
;
import
emu.grasscutter.game.dungeons.DungeonManager
;
import
emu.grasscutter.game.expedition.ExpeditionManager
;
import
emu.grasscutter.game.gacha.GachaManager
;
import
emu.grasscutter.game.gacha.GachaManager
;
import
emu.grasscutter.game.managers.ChatManager
;
import
emu.grasscutter.game.managers.ChatManager
;
import
emu.grasscutter.game.managers.InventoryManager
;
import
emu.grasscutter.game.managers.InventoryManager
;
import
emu.grasscutter.game.managers.MultiplayerManager
;
import
emu.grasscutter.game.managers.MultiplayerManager
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.shop.ShopManager
;
import
emu.grasscutter.game.shop.ShopManager
;
import
emu.grasscutter.game.world.World
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail
;
import
emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail
;
import
emu.grasscutter.netty.MihoyoKcpServer
;
import
emu.grasscutter.netty.KcpServer
;
import
org.greenrobot.eventbus.EventBus
;
import
emu.grasscutter.server.event.types.ServerEvent
;
import
emu.grasscutter.server.event.game.ServerTickEvent
;
import
emu.grasscutter.server.event.internal.ServerStartEvent
;
import
emu.grasscutter.server.event.internal.ServerStopEvent
;
import
emu.grasscutter.task.TaskMap
;
import
java.net.InetSocketAddress
;
import
java.time.OffsetDateTime
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ScheduledExecutorService
;
import
java.util.concurrent.TimeUnit
;
public
final
class
GameServer
extends
MihoyoKcpServer
{
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
public
final
class
GameServer
extends
KcpServer
{
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
private
final
GameServerPacketHandler
packetHandler
;
private
final
GameServerPacketHandler
packetHandler
;
private
final
Map
<
Integer
,
GenshinPlayer
>
players
;
private
final
Map
<
Integer
,
Player
>
players
;
private
final
Set
<
World
>
worlds
;
private
final
ChatManager
chatManager
;
private
final
ChatManager
chatManager
;
private
final
InventoryManager
inventoryManager
;
private
final
InventoryManager
inventoryManager
;
...
@@ -33,23 +48,28 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -33,23 +48,28 @@ public final class GameServer extends MihoyoKcpServer {
private
final
ShopManager
shopManager
;
private
final
ShopManager
shopManager
;
private
final
MultiplayerManager
multiplayerManager
;
private
final
MultiplayerManager
multiplayerManager
;
private
final
DungeonManager
dungeonManager
;
private
final
DungeonManager
dungeonManager
;
private
final
ExpeditionManager
expeditionManager
;
private
final
CommandMap
commandMap
;
private
final
CommandMap
commandMap
;
private
final
TaskMap
taskMap
;
private
final
DropManager
dropManager
;
private
final
CombineManger
combineManger
;
public
EventBus
OnGameServerStartFinish
;
public
GameServer
()
{
public
EventBus
OnGameServerTick
;
this
(
new
InetSocketAddress
(
public
EventBus
OnGameServerStop
;
Grasscutter
.
getConfig
().
getGameServerOptions
().
Ip
,
Grasscutter
.
getConfig
().
getGameServerOptions
().
Port
));
}
public
GameServer
(
InetSocketAddress
address
)
{
public
GameServer
(
InetSocketAddress
address
)
{
super
(
address
);
super
(
address
);
OnGameServerStartFinish
=
EventBus
.
builder
().
throwSubscriberException
(
true
).
logNoSubscriberMessages
(
false
).
build
();
OnGameServerTick
=
EventBus
.
builder
().
throwSubscriberException
(
true
).
logNoSubscriberMessages
(
false
).
build
();
OnGameServerStop
=
EventBus
.
builder
().
throwSubscriberException
(
true
).
logNoSubscriberMessages
(
false
).
build
();
this
.
setServerInitializer
(
new
GameServerInitializer
(
this
));
this
.
setServerInitializer
(
new
GameServerInitializer
(
this
));
this
.
address
=
address
;
this
.
address
=
address
;
this
.
packetHandler
=
new
GameServerPacketHandler
(
PacketHandler
.
class
);
this
.
packetHandler
=
new
GameServerPacketHandler
(
PacketHandler
.
class
);
this
.
players
=
new
ConcurrentHashMap
<>();
this
.
players
=
new
ConcurrentHashMap
<>();
this
.
worlds
=
Collections
.
synchronizedSet
(
new
HashSet
<>());
this
.
chatManager
=
new
ChatManager
(
this
);
this
.
chatManager
=
new
ChatManager
(
this
);
this
.
inventoryManager
=
new
InventoryManager
(
this
);
this
.
inventoryManager
=
new
InventoryManager
(
this
);
...
@@ -58,19 +78,10 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -58,19 +78,10 @@ public final class GameServer extends MihoyoKcpServer {
this
.
multiplayerManager
=
new
MultiplayerManager
(
this
);
this
.
multiplayerManager
=
new
MultiplayerManager
(
this
);
this
.
dungeonManager
=
new
DungeonManager
(
this
);
this
.
dungeonManager
=
new
DungeonManager
(
this
);
this
.
commandMap
=
new
CommandMap
(
true
);
this
.
commandMap
=
new
CommandMap
(
true
);
this
.
taskMap
=
new
TaskMap
(
true
);
// Schedule game loop.
this
.
dropManager
=
new
DropManager
(
this
);
Timer
gameLoop
=
new
Timer
();
this
.
expeditionManager
=
new
ExpeditionManager
(
this
);
gameLoop
.
scheduleAtFixedRate
(
new
TimerTask
()
{
this
.
combineManger
=
new
CombineManger
(
this
);
@Override
public
void
run
()
{
try
{
onTick
();
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"An error occurred during game update."
,
e
);
}
}
},
new
Date
(),
1000L
);
// Hook into shutdown event.
// Hook into shutdown event.
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(
this
::
onServerShutdown
));
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(
this
::
onServerShutdown
));
...
@@ -80,10 +91,14 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -80,10 +91,14 @@ public final class GameServer extends MihoyoKcpServer {
return
packetHandler
;
return
packetHandler
;
}
}
public
Map
<
Integer
,
Genshin
Player
>
getPlayers
()
{
public
Map
<
Integer
,
Player
>
getPlayers
()
{
return
players
;
return
players
;
}
}
public
Set
<
World
>
getWorlds
()
{
return
worlds
;
}
public
ChatManager
getChatManager
()
{
public
ChatManager
getChatManager
()
{
return
chatManager
;
return
chatManager
;
}
}
...
@@ -103,31 +118,47 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -103,31 +118,47 @@ public final class GameServer extends MihoyoKcpServer {
public
MultiplayerManager
getMultiplayerManager
()
{
public
MultiplayerManager
getMultiplayerManager
()
{
return
multiplayerManager
;
return
multiplayerManager
;
}
}
public
DropManager
getDropManager
()
{
return
dropManager
;
}
public
DungeonManager
getDungeonManager
()
{
public
DungeonManager
getDungeonManager
()
{
return
dungeonManager
;
return
dungeonManager
;
}
}
public
ExpeditionManager
getExpeditionManager
()
{
return
expeditionManager
;
}
public
CommandMap
getCommandMap
()
{
public
CommandMap
getCommandMap
()
{
return
this
.
commandMap
;
return
this
.
commandMap
;
}
}
public
CombineManger
getCombineManger
(){
return
this
.
combineManger
;
}
public
TaskMap
getTaskMap
()
{
return
this
.
taskMap
;
}
public
void
registerPlayer
(
Genshin
Player
player
)
{
public
void
registerPlayer
(
Player
player
)
{
getPlayers
().
put
(
player
.
getUid
(),
player
);
getPlayers
().
put
(
player
.
getUid
(),
player
);
}
}
public
Genshin
Player
getPlayerByUid
(
int
id
)
{
public
Player
getPlayerByUid
(
int
id
)
{
return
this
.
getPlayerByUid
(
id
,
false
);
return
this
.
getPlayerByUid
(
id
,
false
);
}
}
public
Genshin
Player
getPlayerByUid
(
int
id
,
boolean
allowOfflinePlayers
)
{
public
Player
getPlayerByUid
(
int
id
,
boolean
allowOfflinePlayers
)
{
// Console check
// Console check
if
(
id
==
G
enshin
Constants
.
SERVER_CONSOLE_UID
)
{
if
(
id
==
G
ame
Constants
.
SERVER_CONSOLE_UID
)
{
return
null
;
return
null
;
}
}
// Get from online players
// Get from online players
Genshin
Player
player
=
this
.
getPlayers
().
get
(
id
);
Player
player
=
this
.
getPlayers
().
get
(
id
);
if
(!
allowOfflinePlayers
)
{
if
(!
allowOfflinePlayers
)
{
return
player
;
return
player
;
...
@@ -143,7 +174,7 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -143,7 +174,7 @@ public final class GameServer extends MihoyoKcpServer {
public
SocialDetail
.
Builder
getSocialDetailByUid
(
int
id
)
{
public
SocialDetail
.
Builder
getSocialDetailByUid
(
int
id
)
{
// Get from online players
// Get from online players
Genshin
Player
player
=
this
.
getPlayerByUid
(
id
,
true
);
Player
player
=
this
.
getPlayerByUid
(
id
,
true
);
if
(
player
==
null
)
{
if
(
player
==
null
)
{
return
null
;
return
null
;
...
@@ -153,7 +184,7 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -153,7 +184,7 @@ public final class GameServer extends MihoyoKcpServer {
}
}
public
Account
getAccountByName
(
String
username
)
{
public
Account
getAccountByName
(
String
username
)
{
Optional
<
Genshin
Player
>
playerOpt
=
getPlayers
().
values
().
stream
().
filter
(
player
->
player
.
getAccount
().
getUsername
().
equals
(
username
)).
findFirst
();
Optional
<
Player
>
playerOpt
=
getPlayers
().
values
().
stream
().
filter
(
player
->
player
.
getAccount
().
getUsername
().
equals
(
username
)).
findFirst
();
if
(
playerOpt
.
isPresent
())
{
if
(
playerOpt
.
isPresent
())
{
return
playerOpt
.
get
().
getAccount
();
return
playerOpt
.
get
().
getAccount
();
}
}
...
@@ -161,28 +192,66 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -161,28 +192,66 @@ public final class GameServer extends MihoyoKcpServer {
}
}
public
void
onTick
()
throws
Exception
{
public
void
onTick
()
throws
Exception
{
for
(
GenshinPlayer
player
:
this
.
getPlayers
().
values
())
{
Iterator
<
World
>
it
=
this
.
getWorlds
().
iterator
();
while
(
it
.
hasNext
())
{
World
world
=
it
.
next
();
if
(
world
.
getPlayerCount
()
==
0
)
{
it
.
remove
();
}
world
.
onTick
();
}
for
(
Player
player
:
this
.
getPlayers
().
values
())
{
player
.
onTick
();
player
.
onTick
();
}
}
ServerTickEvent
event
=
new
ServerTickEvent
();
event
.
call
();
}
public
void
registerWorld
(
World
world
)
{
this
.
getWorlds
().
add
(
world
);
}
public
void
deregisterWorld
(
World
world
)
{
// TODO Auto-generated method stub
}
OnGameServerTick
.
post
(
new
GameServerTickEvent
());
@Override
public
synchronized
void
start
()
{
// Schedule game loop.
Timer
gameLoop
=
new
Timer
();
gameLoop
.
scheduleAtFixedRate
(
new
TimerTask
()
{
@Override
public
void
run
()
{
try
{
onTick
();
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
translate
(
"messages.game.game_update_error"
),
e
);
}
}
},
new
Date
(),
1000L
);
super
.
start
();
}
}
@Override
@Override
public
void
onStartFinish
()
{
public
void
onStartFinish
()
{
Grasscutter
.
getLogger
().
info
(
"Game Server started on port "
+
address
.
getPort
(
));
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.status.free_software"
));
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.game.port_bind"
,
Integer
.
toString
(
address
.
getPort
())));
OnGame
ServerStart
Finish
.
post
(
new
GameServerStartFinishEvent
()
);
ServerStart
Event
event
=
new
ServerStartEvent
(
ServerEvent
.
Type
.
GAME
,
OffsetDateTime
.
now
());
event
.
call
(
);
}
}
public
void
onServerShutdown
()
{
public
void
onServerShutdown
()
{
OnGame
ServerStop
.
post
(
new
GameServerStopEvent
()
);
ServerStop
Event
event
=
new
ServerStopEvent
(
ServerEvent
.
Type
.
GAME
,
OffsetDateTime
.
now
());
event
.
call
(
);
// Kick and save all players
// Kick and save all players
List
<
Genshin
Player
>
list
=
new
ArrayList
<>(
this
.
getPlayers
().
size
());
List
<
Player
>
list
=
new
ArrayList
<>(
this
.
getPlayers
().
size
());
list
.
addAll
(
this
.
getPlayers
().
values
());
list
.
addAll
(
this
.
getPlayers
().
values
());
for
(
Genshin
Player
player
:
list
)
{
for
(
Player
player
:
list
)
{
player
.
getSession
().
close
();
player
.
getSession
().
close
();
}
}
}
}
...
...
src/main/java/emu/grasscutter/server/game/GameServerInitializer.java
View file @
01b190bc
package
emu.grasscutter.server.game
;
package
emu.grasscutter.server.game
;
import
emu.grasscutter.netty.
Mihoyo
KcpServerInitializer
;
import
emu.grasscutter.netty.KcpServerInitializer
;
import
io.jpower.kcp.netty.UkcpChannel
;
import
io.jpower.kcp.netty.UkcpChannel
;
import
io.netty.channel.ChannelPipeline
;
import
io.netty.channel.ChannelPipeline
;
public
class
GameServerInitializer
extends
Mihoyo
KcpServerInitializer
{
public
class
GameServerInitializer
extends
KcpServerInitializer
{
private
GameServer
server
;
private
GameServer
server
;
public
GameServerInitializer
(
GameServer
server
)
{
public
GameServerInitializer
(
GameServer
server
)
{
...
...
src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java
View file @
01b190bc
...
@@ -2,9 +2,11 @@ package emu.grasscutter.server.game;
...
@@ -2,9 +2,11 @@ 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
;
import
emu.grasscutter.Grasscutter.ServerDebugMode
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
...
@@ -12,6 +14,7 @@ import emu.grasscutter.server.game.GameSession.SessionState;
...
@@ -12,6 +14,7 @@ import emu.grasscutter.server.game.GameSession.SessionState;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
@SuppressWarnings
(
"unchecked"
)
public
class
GameServerPacketHandler
{
public
class
GameServerPacketHandler
{
private
final
Int2ObjectMap
<
PacketHandler
>
handlers
;
private
final
Int2ObjectMap
<
PacketHandler
>
handlers
;
...
@@ -20,27 +23,29 @@ public class GameServerPacketHandler {
...
@@ -20,27 +23,29 @@ public class GameServerPacketHandler {
this
.
registerHandlers
(
handlerClass
);
this
.
registerHandlers
(
handlerClass
);
}
}
public
void
registerPacketHandler
(
Class
<?
extends
PacketHandler
>
handlerClass
)
{
try
{
Opcodes
opcode
=
handlerClass
.
getAnnotation
(
Opcodes
.
class
);
if
(
opcode
==
null
||
opcode
.
disabled
()
||
opcode
.
value
()
<=
0
)
{
return
;
}
PacketHandler
packetHandler
=
(
PacketHandler
)
handlerClass
.
newInstance
();
this
.
handlers
.
put
(
opcode
.
value
(),
packetHandler
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
public
void
registerHandlers
(
Class
<?
extends
PacketHandler
>
handlerClass
)
{
public
void
registerHandlers
(
Class
<?
extends
PacketHandler
>
handlerClass
)
{
Reflections
reflections
=
new
Reflections
(
"emu.grasscutter.server.packet"
);
Reflections
reflections
=
new
Reflections
(
"emu.grasscutter.server.packet"
);
Set
<?>
handlerClasses
=
reflections
.
getSubTypesOf
(
handlerClass
);
Set
<?>
handlerClasses
=
reflections
.
getSubTypesOf
(
handlerClass
);
for
(
Object
obj
:
handlerClasses
)
{
for
(
Object
obj
:
handlerClasses
)
{
Class
<?>
c
=
(
Class
<?>)
obj
;
this
.
registerPacketHandler
((
Class
<?
extends
PacketHandler
>)
obj
);
try
{
Opcodes
opcode
=
c
.
getAnnotation
(
Opcodes
.
class
);
if
(
opcode
==
null
||
opcode
.
disabled
()
||
opcode
.
value
()
<=
0
)
{
continue
;
}
PacketHandler
packetHandler
=
(
PacketHandler
)
c
.
newInstance
();
this
.
handlers
.
put
(
opcode
.
value
(),
packetHandler
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
// Debug
// Debug
...
@@ -48,9 +53,7 @@ public class GameServerPacketHandler {
...
@@ -48,9 +53,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 +80,10 @@ public class GameServerPacketHandler {
...
@@ -77,8 +80,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
();
...
@@ -87,8 +92,8 @@ public class GameServerPacketHandler {
...
@@ -87,8 +92,8 @@ public class GameServerPacketHandler {
}
}
// Log unhandled packets
// Log unhandled packets
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
if
(
Grasscutter
.
getConfig
().
DebugMode
==
ServerDebugMode
.
MISSING
)
{
//
Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + PacketOpcodesUtil.getOpcodeName(opcode));
Grasscutter
.
getLogger
().
info
(
"Unhandled packet ("
+
opcode
+
"): "
+
emu
.
grasscutter
.
net
.
packet
.
PacketOpcodesUtil
.
getOpcodeName
(
opcode
));
}
}
}
}
}
}
src/main/java/emu/grasscutter/server/game/GameSession.java
View file @
01b190bc
...
@@ -3,13 +3,18 @@ package emu.grasscutter.server.game;
...
@@ -3,13 +3,18 @@ package emu.grasscutter.server.game;
import
java.io.File
;
import
java.io.File
;
import
java.net.InetSocketAddress
;
import
java.net.InetSocketAddress
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.HashSet
;
import
java.util.Set
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter.ServerDebugMode
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.packet.BasePacket
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodesUtil
;
import
emu.grasscutter.net.packet.PacketOpcodesUtil
;
import
emu.grasscutter.netty.MihoyoKcpChannel
;
import
emu.grasscutter.netty.KcpChannel
;
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
;
...
@@ -17,11 +22,13 @@ import io.netty.buffer.ByteBuf;
...
@@ -17,11 +22,13 @@ import io.netty.buffer.ByteBuf;
import
io.netty.buffer.Unpooled
;
import
io.netty.buffer.Unpooled
;
import
io.netty.channel.ChannelHandlerContext
;
import
io.netty.channel.ChannelHandlerContext
;
public
class
GameSession
extends
MihoyoKcpChannel
{
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
public
class
GameSession
extends
KcpChannel
{
private
GameServer
server
;
private
GameServer
server
;
private
Account
account
;
private
Account
account
;
private
Genshin
Player
player
;
private
Player
player
;
private
boolean
useSecretKey
;
private
boolean
useSecretKey
;
private
SessionState
state
;
private
SessionState
state
;
...
@@ -63,11 +70,11 @@ public class GameSession extends MihoyoKcpChannel {
...
@@ -63,11 +70,11 @@ public class GameSession extends MihoyoKcpChannel {
return
this
.
getAccount
().
getId
();
return
this
.
getAccount
().
getId
();
}
}
public
Genshin
Player
getPlayer
()
{
public
Player
getPlayer
()
{
return
player
;
return
player
;
}
}
public
synchronized
void
setPlayer
(
Genshin
Player
player
)
{
public
synchronized
void
setPlayer
(
Player
player
)
{
this
.
player
=
player
;
this
.
player
=
player
;
this
.
player
.
setSession
(
this
);
this
.
player
.
setSession
(
this
);
this
.
player
.
setAccount
(
this
.
getAccount
());
this
.
player
.
setAccount
(
this
.
getAccount
());
...
@@ -108,21 +115,21 @@ public class GameSession extends MihoyoKcpChannel {
...
@@ -108,21 +115,21 @@ public class GameSession extends MihoyoKcpChannel {
@Override
@Override
protected
void
onConnect
()
{
protected
void
onConnect
()
{
Grasscutter
.
getLogger
().
info
(
"Client connected from "
+
getAddress
().
getHostString
().
toLowerCase
());
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.game.connect"
,
this
.
getAddress
().
getHostString
().
toLowerCase
())
)
;
}
}
@Override
@Override
protected
synchronized
void
onDisconnect
()
{
// Synchronize so we dont add character at the same time
protected
synchronized
void
onDisconnect
()
{
// Synchronize so we don
'
t add character at the same time
.
Grasscutter
.
getLogger
().
info
(
"Client disconnected from "
+
getAddress
().
getHostString
().
toLowerCase
());
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.game.disconnect"
,
this
.
getAddress
().
getHostString
().
toLowerCase
())
)
;
// Set state so no more packets can be handled
// Set state so no more packets can be handled
this
.
setState
(
SessionState
.
INACTIVE
);
this
.
setState
(
SessionState
.
INACTIVE
);
// Save after disconnecting
// Save after disconnecting
if
(
this
.
isLoggedIn
())
{
if
(
this
.
isLoggedIn
())
{
//
Save
//
Call logout event.
getPlayer
().
onLogout
();
getPlayer
().
onLogout
();
// Remove from
game
server
// Remove from server
.
getServer
().
getPlayers
().
remove
(
getPlayer
().
getUid
());
getServer
().
getPlayers
().
remove
(
getPlayer
().
getUid
());
}
}
}
}
...
@@ -140,47 +147,54 @@ public class GameSession extends MihoyoKcpChannel {
...
@@ -140,47 +147,54 @@ public class GameSession extends MihoyoKcpChannel {
byte
[]
packet
=
FileUtils
.
read
(
p
);
byte
[]
packet
=
FileUtils
.
read
(
p
);
GenshinPacket
genshinPacket
=
new
GenshinPacket
(
opcode
);
BasePacket
basePacket
=
new
BasePacket
(
opcode
);
genshinPacket
.
setData
(
packet
);
basePacket
.
setData
(
packet
);
// Log
logPacket
(
genshinPacket
.
getOpcode
());
send
(
genshin
Packet
);
send
(
base
Packet
);
}
}
public
void
send
(
GenshinPacket
genshinP
acket
)
{
public
void
send
(
BasePacket
p
acket
)
{
// Test
// Test
if
(
genshinP
acket
.
getOpcode
()
<=
0
)
{
if
(
p
acket
.
getOpcode
()
<=
0
)
{
Grasscutter
.
getLogger
().
warn
(
"Tried to send packet with missing cmd id!"
);
Grasscutter
.
getLogger
().
warn
(
"Tried to send packet with missing cmd id!"
);
return
;
return
;
}
}
// DO NOT REMOVE (unless we find a way to validate code before sending to client which I don't think we can)
// Stop WindSeedClientNotify from being sent for security purposes.
if
(
PacketOpcodes
.
BANNED_PACKETS
.
contains
(
packet
.
getOpcode
()))
{
return
;
}
// Header
// Header
if
(
genshinP
acket
.
shouldBuildHeader
())
{
if
(
p
acket
.
shouldBuildHeader
())
{
genshinP
acket
.
buildHeader
(
this
.
getNextClientSequence
());
p
acket
.
buildHeader
(
this
.
getNextClientSequence
());
}
}
// Build packet
byte
[]
data
=
genshinPacket
.
build
();
// Log
// Log
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
if
(
Grasscutter
.
getConfig
().
DebugMode
==
ServerDebugMode
.
ALL
)
{
logPacket
(
genshinP
acket
);
logPacket
(
p
acket
);
}
}
// Send
// Invoke event.
send
(
data
);
SendPacketEvent
event
=
new
SendPacketEvent
(
this
,
packet
);
event
.
call
();
}
if
(!
event
.
isCanceled
())
// If event is not cancelled, continue.
this
.
send
(
event
.
getPacket
().
build
());
private
void
logPacket
(
int
opcode
)
{
//Grasscutter.getLogger().info("SEND: " + PacketOpcodesUtil.getOpcodeName(opcode));
//System.out.println(Utils.bytesToHex(genshinPacket.getData()));
}
}
private
void
logPacket
(
GenshinPacket
genshinPacket
)
{
private
static
final
Set
<
Integer
>
loopPacket
=
Set
.
of
(
Grasscutter
.
getLogger
().
info
(
"SEND: "
+
PacketOpcodesUtil
.
getOpcodeName
(
genshinPacket
.
getOpcode
())
+
" ("
+
genshinPacket
.
getOpcode
()
+
")"
);
PacketOpcodes
.
PingReq
,
System
.
out
.
println
(
Utils
.
bytesToHex
(
genshinPacket
.
getData
()));
PacketOpcodes
.
PingRsp
,
PacketOpcodes
.
WorldPlayerRTTNotify
,
PacketOpcodes
.
UnionCmdNotify
,
PacketOpcodes
.
QueryPathReq
);
private
void
logPacket
(
BasePacket
packet
)
{
if
(!
loopPacket
.
contains
(
packet
.
getOpcode
()))
{
Grasscutter
.
getLogger
().
info
(
"SEND: "
+
PacketOpcodesUtil
.
getOpcodeName
(
packet
.
getOpcode
())
+
" ("
+
packet
.
getOpcode
()
+
")"
);
System
.
out
.
println
(
Utils
.
bytesToHex
(
packet
.
getData
()));
}
}
}
@Override
@Override
...
@@ -225,9 +239,11 @@ public class GameSession extends MihoyoKcpChannel {
...
@@ -225,9 +239,11 @@ public class GameSession extends MihoyoKcpChannel {
}
}
// Log packet
// Log packet
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
if
(
Grasscutter
.
getConfig
().
DebugMode
==
ServerDebugMode
.
ALL
)
{
Grasscutter
.
getLogger
().
info
(
"RECV: "
+
PacketOpcodesUtil
.
getOpcodeName
(
opcode
)
+
" ("
+
opcode
+
")"
);
if
(!
loopPacket
.
contains
(
opcode
))
{
System
.
out
.
println
(
Utils
.
bytesToHex
(
payload
));
Grasscutter
.
getLogger
().
info
(
"RECV: "
+
PacketOpcodesUtil
.
getOpcodeName
(
opcode
)
+
" ("
+
opcode
+
")"
);
System
.
out
.
println
(
Utils
.
bytesToHex
(
payload
));
}
}
}
// Handle
// Handle
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionAllDataReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketAvatarExpeditionAllDataRsp
;
@Opcodes
(
PacketOpcodes
.
AvatarExpeditionAllDataReq
)
public
class
HandlerAvatarExpeditionAllDataReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
session
.
send
(
new
PacketAvatarExpeditionAllDataRsp
(
session
.
getPlayer
()));
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionCallBackReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.AvatarExpeditionCallBackReqOuterClass.AvatarExpeditionCallBackReq
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketAvatarExpeditionCallBackRsp
;
import
emu.grasscutter.server.packet.send.PacketAvatarExpeditionStartRsp
;
import
emu.grasscutter.utils.Utils
;
@Opcodes
(
PacketOpcodes
.
AvatarExpeditionCallBackReq
)
public
class
HandlerAvatarExpeditionCallBackReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
AvatarExpeditionCallBackReq
req
=
AvatarExpeditionCallBackReq
.
parseFrom
(
payload
);
for
(
int
i
=
0
;
i
<
req
.
getAvatarGuidCount
();
i
++)
{
session
.
getPlayer
().
removeExpeditionInfo
(
req
.
getAvatarGuid
(
i
));
}
session
.
getPlayer
().
save
();
session
.
send
(
new
PacketAvatarExpeditionCallBackRsp
(
session
.
getPlayer
()));
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionGetRewardReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.game.drop.DropData
;
import
emu.grasscutter.game.expedition.ExpeditionInfo
;
import
emu.grasscutter.game.expedition.ExpeditionRewardData
;
import
emu.grasscutter.game.expedition.ExpeditionRewardDataList
;
import
emu.grasscutter.game.inventory.GameItem
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.AvatarExpeditionGetRewardReqOuterClass.AvatarExpeditionGetRewardReq
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketAvatarExpeditionCallBackRsp
;
import
emu.grasscutter.server.packet.send.PacketAvatarExpeditionGetRewardRsp
;
import
emu.grasscutter.server.packet.send.PacketGadgetInteractRsp
;
import
emu.grasscutter.server.packet.send.PacketItemAddHintNotify
;
import
emu.grasscutter.utils.Utils
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.LinkedList
;
import
java.util.List
;
@Opcodes
(
PacketOpcodes
.
AvatarExpeditionGetRewardReq
)
public
class
HandlerAvatarExpeditionGetRewardReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
AvatarExpeditionGetRewardReq
req
=
AvatarExpeditionGetRewardReq
.
parseFrom
(
payload
);
ExpeditionInfo
expInfo
=
session
.
getPlayer
().
getExpeditionInfo
(
req
.
getAvatarGuid
());
List
<
GameItem
>
items
=
new
LinkedList
<>();
if
(
session
.
getServer
().
getExpeditionManager
().
getExpeditionRewardDataList
().
containsKey
(
expInfo
.
getExpId
()))
{
for
(
ExpeditionRewardDataList
RewardDataList
:
session
.
getServer
().
getExpeditionManager
().
getExpeditionRewardDataList
().
get
(
expInfo
.
getExpId
()))
{
if
(
RewardDataList
.
getHourTime
()
==
expInfo
.
getHourTime
()){
if
(!
RewardDataList
.
getExpeditionRewardData
().
isEmpty
()){
for
(
ExpeditionRewardData
RewardData
:
RewardDataList
.
getExpeditionRewardData
())
{
int
num
=
RewardData
.
getMinCount
();
if
(
RewardData
.
getMinCount
()
!=
RewardData
.
getMaxCount
()){
num
=
Utils
.
randomRange
(
RewardData
.
getMinCount
(),
RewardData
.
getMaxCount
());
}
items
.
add
(
new
GameItem
(
RewardData
.
getItemId
(),
num
));
}
}
}
}
}
session
.
getPlayer
().
getInventory
().
addItems
(
items
);
session
.
getPlayer
().
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
ExpeditionReward
));
session
.
getPlayer
().
removeExpeditionInfo
(
req
.
getAvatarGuid
());
session
.
getPlayer
().
save
();
session
.
send
(
new
PacketAvatarExpeditionGetRewardRsp
(
session
.
getPlayer
(),
items
));
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarExpeditionStartReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.AvatarExpeditionStartReqOuterClass.AvatarExpeditionStartReq
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketAvatarExpeditionStartRsp
;
import
emu.grasscutter.utils.Utils
;
@Opcodes
(
PacketOpcodes
.
AvatarExpeditionStartReq
)
public
class
HandlerAvatarExpeditionStartReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
AvatarExpeditionStartReq
req
=
AvatarExpeditionStartReq
.
parseFrom
(
payload
);
int
startTime
=
Utils
.
getCurrentSeconds
();
session
.
getPlayer
().
addExpeditionInfo
(
req
.
getAvatarGuid
(),
req
.
getExpId
(),
req
.
getHourTime
(),
startTime
);
session
.
getPlayer
().
save
();
session
.
send
(
new
PacketAvatarExpeditionStartRsp
(
session
.
getPlayer
()));
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarFetterLevelRewardReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.def.RewardData
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.inventory.GameItem
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.AvatarFetterLevelRewardReqOuterClass.AvatarFetterLevelRewardReq
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketAvatarDataNotify
;
import
emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify
;
import
emu.grasscutter.server.packet.send.PacketAvatarFetterLevelRewardRsp
;
import
emu.grasscutter.server.packet.send.PacketItemAddHintNotify
;
import
emu.grasscutter.server.packet.send.PacketUnlockNameCardNotify
;
import
emu.grasscutter.net.packet.PacketHandler
;
@Opcodes
(
PacketOpcodes
.
AvatarFetterLevelRewardReq
)
public
class
HandlerAvatarFetterLevelRewardReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
AvatarFetterLevelRewardReq
req
=
AvatarFetterLevelRewardReq
.
parseFrom
(
payload
);
if
(
req
.
getFetterLevel
()
<
10
)
{
// You don't have a full level of fetter level, why do you want to get a divorce certificate?
session
.
send
(
new
PacketAvatarFetterLevelRewardRsp
(
req
.
getAvatarGuid
(),
req
.
getFetterLevel
()));
}
else
{
long
avatarGuid
=
req
.
getAvatarGuid
();
Avatar
avatar
=
session
.
getPlayer
()
.
getAvatars
()
.
getAvatarByGuid
(
avatarGuid
);
int
rewardId
=
avatar
.
getNameCardRewardId
();
RewardData
card
=
GameData
.
getRewardDataMap
().
get
(
rewardId
);
int
cardId
=
card
.
getRewardItemList
().
get
(
0
).
getItemId
();
if
(
session
.
getPlayer
().
getNameCardList
().
contains
(
cardId
))
{
// Already got divorce certificate.
session
.
getPlayer
().
sendPacket
(
new
PacketAvatarFetterLevelRewardRsp
(
req
.
getAvatarGuid
(),
req
.
getFetterLevel
(),
rewardId
));
return
;
}
GameItem
item
=
new
GameItem
(
cardId
);
session
.
getPlayer
().
getInventory
().
addItem
(
item
,
ActionReason
.
FetterLevelReward
);
session
.
getPlayer
().
sendPacket
(
new
PacketUnlockNameCardNotify
(
cardId
));
session
.
send
(
new
PacketAvatarFetterDataNotify
(
avatar
));
session
.
send
(
new
PacketAvatarDataNotify
(
avatar
.
getPlayer
()));
session
.
send
(
new
PacketAvatarFetterLevelRewardRsp
(
avatarGuid
,
req
.
getFetterLevel
(),
rewardId
));
}
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerBuyGoodsReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.common.ItemParamData
;
import
emu.grasscutter.game.inventory.GameItem
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.shop.ShopInfo
;
import
emu.grasscutter.game.shop.ShopLimit
;
import
emu.grasscutter.game.shop.ShopManager
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.BuyGoodsReqOuterClass
;
import
emu.grasscutter.net.proto.ItemParamOuterClass
;
import
emu.grasscutter.net.proto.ShopGoodsOuterClass
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketBuyGoodsRsp
;
import
emu.grasscutter.server.packet.send.PacketStoreItemChangeNotify
;
import
emu.grasscutter.utils.Utils
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Optional
;
@Opcodes
(
PacketOpcodes
.
BuyGoodsReq
)
public
class
HandlerBuyGoodsReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
BuyGoodsReqOuterClass
.
BuyGoodsReq
buyGoodsReq
=
BuyGoodsReqOuterClass
.
BuyGoodsReq
.
parseFrom
(
payload
);
List
<
ShopInfo
>
configShop
=
session
.
getServer
().
getShopManager
().
getShopData
().
get
(
buyGoodsReq
.
getShopType
());
if
(
configShop
==
null
)
return
;
// Don't trust your users' input
List
<
Integer
>
targetShopGoodsId
=
buyGoodsReq
.
getGoodsListList
().
stream
().
map
(
ShopGoodsOuterClass
.
ShopGoods
::
getGoodsId
).
toList
();
for
(
int
goodsId
:
targetShopGoodsId
)
{
Optional
<
ShopInfo
>
sg2
=
configShop
.
stream
().
filter
(
x
->
x
.
getGoodsId
()
==
goodsId
).
findFirst
();
if
(
sg2
.
isEmpty
())
continue
;
ShopInfo
sg
=
sg2
.
get
();
int
currentTs
=
Utils
.
getCurrentSeconds
();
ShopLimit
shopLimit
=
session
.
getPlayer
().
getGoodsLimit
(
sg
.
getGoodsId
());
int
bought
=
0
;
if
(
shopLimit
!=
null
)
{
if
(
currentTs
>
shopLimit
.
getNextRefreshTime
())
{
shopLimit
.
setNextRefreshTime
(
ShopManager
.
getShopNextRefreshTime
(
sg
));
}
else
{
bought
=
shopLimit
.
getHasBoughtInPeriod
();
}
session
.
getPlayer
().
save
();
}
if
((
bought
+
buyGoodsReq
.
getBoughtNum
()
>
sg
.
getBuyLimit
())
&&
sg
.
getBuyLimit
()
!=
0
)
{
return
;
}
if
(
sg
.
getScoin
()
>
0
&&
session
.
getPlayer
().
getMora
()
<
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getScoin
())
{
return
;
}
if
(
sg
.
getHcoin
()
>
0
&&
session
.
getPlayer
().
getPrimogems
()
<
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getHcoin
())
{
return
;
}
if
(
sg
.
getMcoin
()
>
0
&&
session
.
getPlayer
().
getCrystals
()
<
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getMcoin
())
{
return
;
}
HashMap
<
GameItem
,
Integer
>
itemsCache
=
new
HashMap
<>();
if
(
sg
.
getCostItemList
()
!=
null
)
{
for
(
ItemParamData
p
:
sg
.
getCostItemList
())
{
Optional
<
GameItem
>
invItem
=
session
.
getPlayer
().
getInventory
().
getItems
().
values
().
stream
().
filter
(
x
->
x
.
getItemId
()
==
p
.
getId
()).
findFirst
();
if
(
invItem
.
isEmpty
()
||
invItem
.
get
().
getCount
()
<
p
.
getCount
())
return
;
itemsCache
.
put
(
invItem
.
get
(),
p
.
getCount
()
*
buyGoodsReq
.
getBoughtNum
());
}
}
session
.
getPlayer
().
setMora
(
session
.
getPlayer
().
getMora
()
-
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getScoin
());
session
.
getPlayer
().
setPrimogems
(
session
.
getPlayer
().
getPrimogems
()
-
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getHcoin
());
session
.
getPlayer
().
setCrystals
(
session
.
getPlayer
().
getCrystals
()
-
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getMcoin
());
if
(!
itemsCache
.
isEmpty
())
{
for
(
GameItem
gi
:
itemsCache
.
keySet
())
{
session
.
getPlayer
().
getInventory
().
removeItem
(
gi
,
itemsCache
.
get
(
gi
));
}
itemsCache
.
clear
();
}
session
.
getPlayer
().
addShopLimit
(
sg
.
getGoodsId
(),
buyGoodsReq
.
getBoughtNum
(),
ShopManager
.
getShopNextRefreshTime
(
sg
));
GameItem
item
=
new
GameItem
(
GameData
.
getItemDataMap
().
get
(
sg
.
getGoodsItem
().
getId
()));
item
.
setCount
(
buyGoodsReq
.
getBoughtNum
()
*
sg
.
getGoodsItem
().
getCount
());
session
.
getPlayer
().
getInventory
().
addItem
(
item
,
ActionReason
.
Shop
,
true
);
// fix: not notify when got virtual item from shop
session
.
send
(
new
PacketBuyGoodsRsp
(
buyGoodsReq
.
getShopType
(),
session
.
getPlayer
().
getGoodsLimit
(
sg
.
getGoodsId
()).
getHasBoughtInPeriod
(),
buyGoodsReq
.
getGoodsListList
().
stream
().
filter
(
x
->
x
.
getGoodsId
()
==
goodsId
).
findFirst
().
get
()));
}
session
.
getPlayer
().
save
();
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeMailStarNotify.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.game.mail.Mail
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.ChangeMailStarNotifyOuterClass
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketMailChangeNotify
;
import
java.util.ArrayList
;
import
java.util.List
;
@Opcodes
(
PacketOpcodes
.
ChangeMailStarNotify
)
public
class
HandlerChangeMailStarNotify
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
ChangeMailStarNotifyOuterClass
.
ChangeMailStarNotify
req
=
ChangeMailStarNotifyOuterClass
.
ChangeMailStarNotify
.
parseFrom
(
payload
);
List
<
Mail
>
updatedMail
=
new
ArrayList
<>();
for
(
int
mailId
:
req
.
getMailIdListList
())
{
Mail
message
=
session
.
getPlayer
().
getMail
(
mailId
);
message
.
importance
=
req
.
getIsStar
()
==
true
?
1
:
0
;
session
.
getPlayer
().
replaceMailByIndex
(
mailId
,
message
);
updatedMail
.
add
(
message
);
}
session
.
send
(
new
PacketMailChangeNotify
(
session
.
getPlayer
(),
updatedMail
));
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.game.entity.G
enshin
Entity
;
import
emu.grasscutter.game.entity.G
ame
Entity
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify
;
import
emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify
;
...
@@ -12,40 +12,40 @@ import emu.grasscutter.server.game.GameSession;
...
@@ -12,40 +12,40 @@ import emu.grasscutter.server.game.GameSession;
@Opcodes
(
PacketOpcodes
.
CombatInvocationsNotify
)
@Opcodes
(
PacketOpcodes
.
CombatInvocationsNotify
)
public
class
HandlerCombatInvocationsNotify
extends
PacketHandler
{
public
class
HandlerCombatInvocationsNotify
extends
PacketHandler
{
@Override
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
CombatInvocationsNotify
notif
=
CombatInvocationsNotify
.
parseFrom
(
payload
);
CombatInvocationsNotify
notif
=
CombatInvocationsNotify
.
parseFrom
(
payload
);
for
(
CombatInvokeEntry
entry
:
notif
.
getInvokeListList
())
{
for
(
CombatInvokeEntry
entry
:
notif
.
getInvokeListList
())
{
switch
(
entry
.
getArgumentType
())
{
switch
(
entry
.
getArgumentType
())
{
case
C
ombatEvtBeingHit
:
case
C
OMBAT_EVT_BEING_HIT
:
// Handle damage
// Handle damage
EvtBeingHitInfo
hitInfo
=
EvtBeingHitInfo
.
parseFrom
(
entry
.
getCombatData
());
EvtBeingHitInfo
hitInfo
=
EvtBeingHitInfo
.
parseFrom
(
entry
.
getCombatData
());
session
.
getPlayer
().
get
Scene
().
handleAttack
(
hitInfo
.
getAttackResult
());
session
.
getPlayer
().
get
AttackResults
().
add
(
hitInfo
.
getAttackResult
());
break
;
break
;
case
E
ntityMove
:
case
E
NTITY_MOVE
:
// Handle movement
// Handle movement
EntityMoveInfo
moveInfo
=
EntityMoveInfo
.
parseFrom
(
entry
.
getCombatData
());
EntityMoveInfo
moveInfo
=
EntityMoveInfo
.
parseFrom
(
entry
.
getCombatData
());
G
enshin
Entity
entity
=
session
.
getPlayer
().
getScene
().
getEntityById
(
moveInfo
.
getEntityId
());
G
ame
Entity
entity
=
session
.
getPlayer
().
getScene
().
getEntityById
(
moveInfo
.
getEntityId
());
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
entity
.
getPosition
().
set
(
moveInfo
.
getMotionInfo
().
getPos
());
session
.
getPlayer
().
getMovementManager
().
handle
(
session
,
moveInfo
,
entity
);
entity
.
getRotation
().
set
(
moveInfo
.
getMotionInfo
().
getRot
());
entity
.
setLastMoveSceneTimeMs
(
moveInfo
.
getSceneTime
());
entity
.
setLastMoveReliableSeq
(
moveInfo
.
getReliableSeq
());
entity
.
setMotionState
(
moveInfo
.
getMotionInfo
().
getState
());
}
}
break
;
break
;
default
:
default
:
break
;
break
;
}
}
session
.
getPlayer
().
getCombatInvokeHandler
().
addEntry
(
entry
.
getForwardType
(),
entry
);
session
.
getPlayer
().
getCombatInvokeHandler
().
addEntry
(
entry
.
getForwardType
(),
entry
);
}
}
if
(
notif
.
getInvokeListList
().
size
()
>
0
)
{
if
(
notif
.
getInvokeListList
().
size
()
>
0
)
{
session
.
getPlayer
().
getCombatInvokeHandler
().
update
(
session
.
getPlayer
());
session
.
getPlayer
().
getCombatInvokeHandler
().
update
(
session
.
getPlayer
());
}
}
// Handle attack results last
while
(!
session
.
getPlayer
().
getAttackResults
().
isEmpty
())
{
session
.
getPlayer
().
getScene
().
handleAttack
(
session
.
getPlayer
().
getAttackResults
().
poll
());
}
}
}
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.data.def.CombineData
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.CombineReqOuterClass
;
import
emu.grasscutter.net.proto.ItemParamOuterClass
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketCombineRsp
;
import
java.util.List
;
import
java.util.stream.Collectors
;
@Opcodes
(
PacketOpcodes
.
CombineReq
)
public
class
HandlerCombineReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
CombineReqOuterClass
.
CombineReq
req
=
CombineReqOuterClass
.
CombineReq
.
parseFrom
(
payload
);
var
result
=
session
.
getServer
().
getCombineManger
()
.
combineItem
(
session
.
getPlayer
(),
req
.
getCombineId
(),
req
.
getCombineCount
());
if
(
result
==
null
){
return
;
}
session
.
send
(
new
PacketCombineRsp
(
req
,
toItemParamList
(
result
.
getMaterial
()),
toItemParamList
(
result
.
getResult
()),
toItemParamList
(
result
.
getExtra
()),
toItemParamList
(
result
.
getBack
()),
toItemParamList
(
result
.
getBack
())));
}
private
List
<
ItemParamOuterClass
.
ItemParam
>
toItemParamList
(
List
<
CombineData
.
CombineItemPair
>
list
){
return
list
.
stream
()
.
map
(
item
->
ItemParamOuterClass
.
ItemParam
.
newBuilder
()
.
setItemId
(
item
.
getId
())
.
setCount
(
item
.
getCount
())
.
build
())
.
collect
(
Collectors
.
toList
());
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerDelMailReq.java
0 → 100644
View file @
01b190bc
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.DelMailReqOuterClass
;
import
emu.grasscutter.net.proto.DeleteFriendReqOuterClass
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketDelMailRsp
;
@Opcodes
(
PacketOpcodes
.
DelMailReq
)
public
class
HandlerDelMailReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
DelMailReqOuterClass
.
DelMailReq
req
=
DelMailReqOuterClass
.
DelMailReq
.
parseFrom
(
payload
);
session
.
getPlayer
().
getMailHandler
().
deleteMail
(
req
.
getMailIdListList
());
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerDungeonEntryInfoReq.java
View file @
01b190bc
...
@@ -2,6 +2,7 @@ package emu.grasscutter.server.packet.recv;
...
@@ -2,6 +2,7 @@ package emu.grasscutter.server.packet.recv;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.DungeonEntryInfoReqOuterClass.DungeonEntryInfoReq
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.game.GameSession
;
...
@@ -10,7 +11,9 @@ public class HandlerDungeonEntryInfoReq extends PacketHandler {
...
@@ -10,7 +11,9 @@ public class HandlerDungeonEntryInfoReq extends PacketHandler {
@Override
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
DungeonEntryInfoReq
req
=
DungeonEntryInfoReq
.
parseFrom
(
payload
);
session
.
getServer
().
getDungeonManager
().
getEntryInfo
(
session
.
getPlayer
(),
req
.
getPointId
());
}
}
}
}
Prev
1
…
9
10
11
12
13
14
15
16
17
…
25
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment