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
6e81dc39
Commit
6e81dc39
authored
Apr 21, 2022
by
Magix
Committed by
GitHub
Apr 21, 2022
Browse files
Update Grasscutter to v1.0.0
Merge development into stable (and all the support hell that comes with it).
parents
1456cd99
4e1ea6ab
Changes
103
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/game/friends/PlayerProfile.java
View file @
6e81dc39
...
@@ -7,7 +7,7 @@ import emu.grasscutter.utils.Utils;
...
@@ -7,7 +7,7 @@ import emu.grasscutter.utils.Utils;
public
class
PlayerProfile
{
public
class
PlayerProfile
{
@Transient
private
GenshinPlayer
player
;
@Transient
private
GenshinPlayer
player
;
private
int
id
;
@AlsoLoad
(
"id"
)
private
int
u
id
;
private
int
nameCard
;
private
int
nameCard
;
private
int
avatarId
;
private
int
avatarId
;
private
String
name
;
private
String
name
;
...
@@ -22,12 +22,12 @@ public class PlayerProfile {
...
@@ -22,12 +22,12 @@ public class PlayerProfile {
public
PlayerProfile
()
{
}
public
PlayerProfile
()
{
}
public
PlayerProfile
(
GenshinPlayer
player
)
{
public
PlayerProfile
(
GenshinPlayer
player
)
{
this
.
id
=
player
.
getUid
();
this
.
u
id
=
player
.
getUid
();
this
.
syncWithCharacter
(
player
);
this
.
syncWithCharacter
(
player
);
}
}
public
int
get
I
d
()
{
public
int
get
Ui
d
()
{
return
id
;
return
u
id
;
}
}
public
GenshinPlayer
getPlayer
()
{
public
GenshinPlayer
getPlayer
()
{
...
@@ -87,6 +87,7 @@ public class PlayerProfile {
...
@@ -87,6 +87,7 @@ public class PlayerProfile {
return
;
return
;
}
}
this
.
uid
=
player
.
getUid
();
this
.
name
=
player
.
getNickname
();
this
.
name
=
player
.
getNickname
();
this
.
avatarId
=
player
.
getHeadImage
();
this
.
avatarId
=
player
.
getHeadImage
();
this
.
signature
=
player
.
getSignature
();
this
.
signature
=
player
.
getSignature
();
...
...
src/main/java/emu/grasscutter/game/gacha/GachaBanner.java
View file @
6e81dc39
...
@@ -92,7 +92,7 @@ public class GachaBanner {
...
@@ -92,7 +92,7 @@ public class GachaBanner {
}
}
public
GachaInfo
toProto
()
{
public
GachaInfo
toProto
()
{
String
record
=
"http://"
+
(
Grasscutter
.
getConfig
().
Dispatch
Server
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
Dispatch
Server
Ip
:
Grasscutter
.
getConfig
().
Dispatch
Server
PublicIp
)
+
"/gacha"
;
String
record
=
"http://"
+
(
Grasscutter
.
getConfig
().
get
Dispatch
Options
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
get
Dispatch
Options
().
Ip
:
Grasscutter
.
getConfig
().
get
Dispatch
Options
().
PublicIp
)
+
"/gacha"
;
GachaInfo
.
Builder
info
=
GachaInfo
.
newBuilder
()
GachaInfo
.
Builder
info
=
GachaInfo
.
newBuilder
()
.
setGachaType
(
this
.
getGachaType
())
.
setGachaType
(
this
.
getGachaType
())
...
...
src/main/java/emu/grasscutter/game/gacha/GachaManager.java
View file @
6e81dc39
package
emu.grasscutter.game.gacha
;
package
emu.grasscutter.game.gacha
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.FileReader
;
import
java.nio.file.*
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.List
;
...
@@ -8,6 +10,7 @@ import java.util.concurrent.ThreadLocalRandom;
...
@@ -8,6 +10,7 @@ import java.util.concurrent.ThreadLocalRandom;
import
com.google.gson.reflect.TypeToken
;
import
com.google.gson.reflect.TypeToken
;
import
com.sun.nio.file.SensitivityWatchEventModifier
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.ItemData
;
...
@@ -21,17 +24,20 @@ import emu.grasscutter.net.proto.GachaTransferItemOuterClass.GachaTransferItem;
...
@@ -21,17 +24,20 @@ import emu.grasscutter.net.proto.GachaTransferItemOuterClass.GachaTransferItem;
import
emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp
;
import
emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp
;
import
emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam
;
import
emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam
;
import
emu.grasscutter.server.game.GameServer
;
import
emu.grasscutter.server.game.GameServer
;
import
emu.grasscutter.server.game.GameServerTickEvent
;
import
emu.grasscutter.server.packet.send.PacketDoGachaRsp
;
import
emu.grasscutter.server.packet.send.PacketDoGachaRsp
;
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
;
import
it.unimi.dsi.fastutil.ints.IntArrayList
;
import
it.unimi.dsi.fastutil.ints.IntArrayList
;
import
it.unimi.dsi.fastutil.ints.IntList
;
import
it.unimi.dsi.fastutil.ints.IntList
;
import
org.greenrobot.eventbus.Subscribe
;
public
class
GachaManager
{
public
class
GachaManager
{
private
final
GameServer
server
;
private
final
GameServer
server
;
private
final
Int2ObjectMap
<
GachaBanner
>
gachaBanners
;
private
final
Int2ObjectMap
<
GachaBanner
>
gachaBanners
;
private
GetGachaInfoRsp
cachedProto
;
private
GetGachaInfoRsp
cachedProto
;
WatchService
watchService
;
private
int
[]
yellowAvatars
=
new
int
[]
{
1003
,
1016
,
1042
,
1035
,
1041
};
private
int
[]
yellowAvatars
=
new
int
[]
{
1003
,
1016
,
1042
,
1035
,
1041
};
private
int
[]
yellowWeapons
=
new
int
[]
{
11501
,
11502
,
12501
,
12502
,
13502
,
13505
,
14501
,
14502
,
15501
,
15502
};
private
int
[]
yellowWeapons
=
new
int
[]
{
11501
,
11502
,
12501
,
12502
,
13502
,
13505
,
14501
,
14502
,
15501
,
15502
};
private
int
[]
purpleAvatars
=
new
int
[]
{
1006
,
1014
,
1015
,
1020
,
1021
,
1023
,
1024
,
1025
,
1027
,
1031
,
1032
,
1034
,
1036
,
1039
,
1043
,
1044
,
1045
,
1048
,
1053
,
1055
,
1056
,
1064
};
private
int
[]
purpleAvatars
=
new
int
[]
{
1006
,
1014
,
1015
,
1020
,
1021
,
1023
,
1024
,
1025
,
1027
,
1031
,
1032
,
1034
,
1036
,
1039
,
1043
,
1044
,
1045
,
1048
,
1053
,
1055
,
1056
,
1064
};
...
@@ -40,11 +46,12 @@ public class GachaManager {
...
@@ -40,11 +46,12 @@ public class GachaManager {
private
static
int
starglitterId
=
221
;
private
static
int
starglitterId
=
221
;
private
static
int
stardustId
=
222
;
private
static
int
stardustId
=
222
;
public
GachaManager
(
GameServer
server
)
{
public
GachaManager
(
GameServer
server
)
{
this
.
server
=
server
;
this
.
server
=
server
;
this
.
gachaBanners
=
new
Int2ObjectOpenHashMap
<>();
this
.
gachaBanners
=
new
Int2ObjectOpenHashMap
<>();
this
.
load
();
this
.
load
();
this
.
startWatcher
(
server
);
}
}
public
GameServer
getServer
()
{
public
GameServer
getServer
()
{
...
@@ -65,9 +72,16 @@ public class GachaManager {
...
@@ -65,9 +72,16 @@ public class GachaManager {
public
synchronized
void
load
()
{
public
synchronized
void
load
()
{
try
(
FileReader
fileReader
=
new
FileReader
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"Banners.json"
))
{
try
(
FileReader
fileReader
=
new
FileReader
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"Banners.json"
))
{
getGachaBanners
().
clear
();
List
<
GachaBanner
>
banners
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
GachaBanner
.
class
).
getType
());
List
<
GachaBanner
>
banners
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
GachaBanner
.
class
).
getType
());
for
(
GachaBanner
banner
:
banners
)
{
if
(
banners
.
size
()
>
0
)
{
getGachaBanners
().
put
(
banner
.
getGachaType
(),
banner
);
for
(
GachaBanner
banner
:
banners
)
{
getGachaBanners
().
put
(
banner
.
getGachaType
(),
banner
);
}
Grasscutter
.
getLogger
().
info
(
"Banners successfully loaded."
);
this
.
cachedProto
=
createProto
();
}
else
{
Grasscutter
.
getLogger
().
error
(
"Unable to load banners. Banners size is 0."
);
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
// TODO Auto-generated catch block
// TODO Auto-generated catch block
...
@@ -204,7 +218,6 @@ public class GachaManager {
...
@@ -204,7 +218,6 @@ public class GachaManager {
addStarglitter
=
2
;
addStarglitter
=
2
;
// Add 1 const
// Add 1 const
gachaItem
.
addTransferItems
(
GachaTransferItem
.
newBuilder
().
setItem
(
ItemParam
.
newBuilder
().
setItemId
(
constItemId
).
setCount
(
1
)).
setIsTransferItemNew
(
constItem
==
null
));
gachaItem
.
addTransferItems
(
GachaTransferItem
.
newBuilder
().
setItem
(
ItemParam
.
newBuilder
().
setItemId
(
constItemId
).
setCount
(
1
)).
setIsTransferItemNew
(
constItem
==
null
));
gachaItem
.
addTokenItemList
(
ItemParam
.
newBuilder
().
setItemId
(
constItemId
).
setCount
(
1
));
player
.
getInventory
().
addItem
(
constItemId
,
1
);
player
.
getInventory
().
addItem
(
constItemId
,
1
);
}
else
{
}
else
{
// Is max const
// Is max const
...
@@ -266,6 +279,48 @@ public class GachaManager {
...
@@ -266,6 +279,48 @@ public class GachaManager {
// Packets
// Packets
player
.
sendPacket
(
new
PacketDoGachaRsp
(
banner
,
list
));
player
.
sendPacket
(
new
PacketDoGachaRsp
(
banner
,
list
));
}
}
private
synchronized
void
startWatcher
(
GameServer
server
)
{
if
(
this
.
watchService
==
null
)
{
try
{
this
.
watchService
=
FileSystems
.
getDefault
().
newWatchService
();
Path
path
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
).
toPath
();
path
.
register
(
watchService
,
new
WatchEvent
.
Kind
[]{
StandardWatchEventKinds
.
ENTRY_MODIFY
},
SensitivityWatchEventModifier
.
HIGH
);
server
.
OnGameServerTick
.
register
(
this
);
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"
);
e
.
printStackTrace
();
}
}
else
{
Grasscutter
.
getLogger
().
error
(
"Cannot reinitialise watcher "
);
}
}
@Subscribe
public
synchronized
void
watchBannerJson
(
GameServerTickEvent
tickEvent
)
{
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
WatchGacha
)
{
try
{
WatchKey
watchKey
=
watchService
.
take
();
for
(
WatchEvent
<?>
event
:
watchKey
.
pollEvents
())
{
final
Path
changed
=
(
Path
)
event
.
context
();
if
(
changed
.
endsWith
(
"Banners.json"
))
{
Grasscutter
.
getLogger
().
info
(
"Change detected with banners.json. Reloading gacha config"
);
this
.
load
();
}
}
boolean
valid
=
watchKey
.
reset
();
if
(!
valid
)
{
Grasscutter
.
getLogger
().
error
(
"Unable to reset Gacha Manager Watch Key. Auto-reload of banners.json will no longer work."
);
return
;
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
private
synchronized
GetGachaInfoRsp
createProto
()
{
private
synchronized
GetGachaInfoRsp
createProto
()
{
GetGachaInfoRsp
.
Builder
proto
=
GetGachaInfoRsp
.
newBuilder
().
setGachaRandom
(
12345
);
GetGachaInfoRsp
.
Builder
proto
=
GetGachaInfoRsp
.
newBuilder
().
setGachaRandom
(
12345
);
...
...
src/main/java/emu/grasscutter/game/inventory/Inventory.java
View file @
6e81dc39
...
@@ -37,10 +37,10 @@ public class Inventory implements Iterable<GenshinItem> {
...
@@ -37,10 +37,10 @@ public class Inventory implements Iterable<GenshinItem> {
this
.
store
=
new
Long2ObjectOpenHashMap
<>();
this
.
store
=
new
Long2ObjectOpenHashMap
<>();
this
.
inventoryTypes
=
new
Int2ObjectOpenHashMap
<>();
this
.
inventoryTypes
=
new
Int2ObjectOpenHashMap
<>();
this
.
createInventoryTab
(
ItemType
.
ITEM_WEAPON
,
new
EquipInventoryTab
(
Grasscutter
.
getConfig
().
getServerOptions
().
InventoryLimitWeapon
));
this
.
createInventoryTab
(
ItemType
.
ITEM_WEAPON
,
new
EquipInventoryTab
(
Grasscutter
.
getConfig
().
get
Game
ServerOptions
().
InventoryLimitWeapon
));
this
.
createInventoryTab
(
ItemType
.
ITEM_RELIQUARY
,
new
EquipInventoryTab
(
Grasscutter
.
getConfig
().
getServerOptions
().
InventoryLimitRelic
));
this
.
createInventoryTab
(
ItemType
.
ITEM_RELIQUARY
,
new
EquipInventoryTab
(
Grasscutter
.
getConfig
().
get
Game
ServerOptions
().
InventoryLimitRelic
));
this
.
createInventoryTab
(
ItemType
.
ITEM_MATERIAL
,
new
MaterialInventoryTab
(
Grasscutter
.
getConfig
().
getServerOptions
().
InventoryLimitMaterial
));
this
.
createInventoryTab
(
ItemType
.
ITEM_MATERIAL
,
new
MaterialInventoryTab
(
Grasscutter
.
getConfig
().
get
Game
ServerOptions
().
InventoryLimitMaterial
));
this
.
createInventoryTab
(
ItemType
.
ITEM_FURNITURE
,
new
MaterialInventoryTab
(
Grasscutter
.
getConfig
().
getServerOptions
().
InventoryLimitFurniture
));
this
.
createInventoryTab
(
ItemType
.
ITEM_FURNITURE
,
new
MaterialInventoryTab
(
Grasscutter
.
getConfig
().
get
Game
ServerOptions
().
InventoryLimitFurniture
));
}
}
public
GenshinPlayer
getPlayer
()
{
public
GenshinPlayer
getPlayer
()
{
...
...
src/main/java/emu/grasscutter/game/managers/ChatManager.java
View file @
6e81dc39
package
emu.grasscutter.game.managers
;
package
emu.grasscutter.game.managers
;
import
emu.grasscutter.command
s
.CommandMap
;
import
emu.grasscutter.command.CommandMap
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.server.game.GameServer
;
import
emu.grasscutter.server.game.GameServer
;
...
...
src/main/java/emu/grasscutter/game/managers/InventoryManager.java
View file @
6e81dc39
...
@@ -589,7 +589,6 @@ public class InventoryManager {
...
@@ -589,7 +589,6 @@ public class InventoryManager {
// Update proud skills
// Update proud skills
AvatarSkillDepotData
skillDepot
=
GenshinData
.
getAvatarSkillDepotDataMap
().
get
(
avatar
.
getSkillDepotId
());
AvatarSkillDepotData
skillDepot
=
GenshinData
.
getAvatarSkillDepotDataMap
().
get
(
avatar
.
getSkillDepotId
());
boolean
hasAddedProudSkill
=
false
;
if
(
skillDepot
!=
null
&&
skillDepot
.
getInherentProudSkillOpens
()
!=
null
)
{
if
(
skillDepot
!=
null
&&
skillDepot
.
getInherentProudSkillOpens
()
!=
null
)
{
for
(
InherentProudSkillOpens
openData
:
skillDepot
.
getInherentProudSkillOpens
())
{
for
(
InherentProudSkillOpens
openData
:
skillDepot
.
getInherentProudSkillOpens
())
{
...
@@ -599,7 +598,6 @@ public class InventoryManager {
...
@@ -599,7 +598,6 @@ public class InventoryManager {
if
(
openData
.
getNeedAvatarPromoteLevel
()
==
avatar
.
getPromoteLevel
())
{
if
(
openData
.
getNeedAvatarPromoteLevel
()
==
avatar
.
getPromoteLevel
())
{
int
proudSkillId
=
(
openData
.
getProudSkillGroupId
()
*
100
)
+
1
;
int
proudSkillId
=
(
openData
.
getProudSkillGroupId
()
*
100
)
+
1
;
if
(
GenshinData
.
getProudSkillDataMap
().
containsKey
(
proudSkillId
))
{
if
(
GenshinData
.
getProudSkillDataMap
().
containsKey
(
proudSkillId
))
{
hasAddedProudSkill
=
true
;
avatar
.
getProudSkillList
().
add
(
proudSkillId
);
avatar
.
getProudSkillList
().
add
(
proudSkillId
);
player
.
sendPacket
(
new
PacketProudSkillChangeNotify
(
avatar
));
player
.
sendPacket
(
new
PacketProudSkillChangeNotify
(
avatar
));
}
}
...
@@ -607,20 +605,13 @@ public class InventoryManager {
...
@@ -607,20 +605,13 @@ public class InventoryManager {
}
}
}
}
// Racalc stats and save avatar
avatar
.
recalcStats
();
avatar
.
save
();
// Resend ability embryos if proud skill has been added
if
(
hasAddedProudSkill
&&
avatar
.
getAsEntity
()
!=
null
)
{
player
.
sendPacket
(
new
PacketAbilityChangeNotify
(
avatar
.
getAsEntity
()));
}
// TODO Send entity prop update packet to world
// Packets
// Packets
player
.
sendPacket
(
new
PacketAvatarPropNotify
(
avatar
));
player
.
sendPacket
(
new
PacketAvatarPropNotify
(
avatar
));
player
.
sendPacket
(
new
PacketAvatarPromoteRsp
(
avatar
));
player
.
sendPacket
(
new
PacketAvatarPromoteRsp
(
avatar
));
// TODO Send entity prop update packet to world
avatar
.
recalcStats
(
true
);
avatar
.
save
();
}
}
public
void
upgradeAvatar
(
GenshinPlayer
player
,
long
guid
,
int
itemId
,
int
count
)
{
public
void
upgradeAvatar
(
GenshinPlayer
player
,
long
guid
,
int
itemId
,
int
count
)
{
...
@@ -827,25 +818,20 @@ public class InventoryManager {
...
@@ -827,25 +818,20 @@ public class InventoryManager {
// Apply + recalc
// Apply + recalc
avatar
.
getTalentIdList
().
add
(
talentData
.
getId
());
avatar
.
getTalentIdList
().
add
(
talentData
.
getId
());
avatar
.
setCoreProudSkillLevel
(
currentTalentLevel
+
1
);
avatar
.
setCoreProudSkillLevel
(
currentTalentLevel
+
1
);
avatar
.
recalcStats
();
// Packet
// Packet
player
.
sendPacket
(
new
PacketAvatarUnlockTalentNotify
(
avatar
,
nextTalentId
));
player
.
sendPacket
(
new
PacketAvatarUnlockTalentNotify
(
avatar
,
nextTalentId
));
player
.
sendPacket
(
new
PacketUnlockAvatarTalentRsp
(
avatar
,
nextTalentId
));
player
.
sendPacket
(
new
PacketUnlockAvatarTalentRsp
(
avatar
,
nextTalentId
));
// Proud skill bonus map
// Proud skill bonus map
(Extra skills)
OpenConfigEntry
entry
=
GenshinData
.
getOpenConfigEntries
().
get
(
talentData
.
getOpenConfig
());
OpenConfigEntry
entry
=
GenshinData
.
getOpenConfigEntries
().
get
(
talentData
.
getOpenConfig
());
if
(
entry
!=
null
&&
entry
.
getExtraTalentIndex
()
>
0
)
{
if
(
entry
!=
null
&&
entry
.
getExtraTalentIndex
()
>
0
)
{
avatar
.
recalcProudSkillBonusMap
();
avatar
.
recalcProudSkillBonusMap
();
player
.
sendPacket
(
new
PacketProudSkillExtraLevelNotify
(
avatar
,
entry
.
getExtraTalentIndex
()));
player
.
sendPacket
(
new
PacketProudSkillExtraLevelNotify
(
avatar
,
entry
.
getExtraTalentIndex
()));
}
}
// Resend ability embryos
// Recalc + save avatar
if
(
avatar
.
getAsEntity
()
!=
null
)
{
avatar
.
recalcStats
(
true
);
player
.
sendPacket
(
new
PacketAbilityChangeNotify
(
avatar
.
getAsEntity
()));
}
// Save avatar
avatar
.
save
();
avatar
.
save
();
}
}
...
...
src/main/java/emu/grasscutter/game/props/FetterState.java
0 → 100644
View file @
6e81dc39
package
emu.grasscutter.game.props
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.stream.Stream
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
enum
FetterState
{
NONE
(
0
),
NOT_OPEN
(
1
),
OPEN
(
1
),
FINISH
(
3
);
private
final
int
value
;
private
static
final
Int2ObjectMap
<
FetterState
>
map
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Map
<
String
,
FetterState
>
stringMap
=
new
HashMap
<>();
static
{
Stream
.
of
(
values
()).
forEach
(
e
->
{
map
.
put
(
e
.
getValue
(),
e
);
stringMap
.
put
(
e
.
name
(),
e
);
});
}
private
FetterState
(
int
value
)
{
this
.
value
=
value
;
}
public
int
getValue
()
{
return
value
;
}
public
static
FetterState
getTypeByValue
(
int
value
)
{
return
map
.
getOrDefault
(
value
,
NONE
);
}
public
static
FetterState
getTypeByName
(
String
name
)
{
return
stringMap
.
getOrDefault
(
name
,
NONE
);
}
}
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
6e81dc39
package
emu.grasscutter.server.dispatch
;
package
emu.grasscutter.server.dispatch
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.io.UnsupportedEncodingException
;
import
java.net.InetSocketAddress
;
import
java.net.URI
;
import
java.net.URLDecoder
;
import
java.security.KeyStore
;
import
java.util.Base64
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
com.google.gson.Gson
;
import
com.google.gson.Gson
;
import
com.google.gson.GsonBuilder
;
import
com.google.gson.GsonBuilder
;
import
com.google.protobuf.ByteString
;
import
com.google.protobuf.ByteString
;
import
com.sun.net.httpserver.HttpExchange
;
import
com.sun.net.httpserver.HttpExchange
;
import
com.sun.net.httpserver.Http
Handl
er
;
import
com.sun.net.httpserver.Http
Serv
er
;
import
com.sun.net.httpserver.HttpsConfigurator
;
import
com.sun.net.httpserver.HttpsConfigurator
;
import
com.sun.net.httpserver.HttpsServer
;
import
com.sun.net.httpserver.HttpsServer
;
import
emu.grasscutter.Config
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.Account
;
...
@@ -32,30 +16,34 @@ import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegio
...
@@ -32,30 +16,34 @@ import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegio
import
emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp
;
import
emu.grasscutter.net.proto.QueryRegionListHttpRspOuterClass.QueryRegionListHttpRsp
;
import
emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo
;
import
emu.grasscutter.net.proto.RegionInfoOuterClass.RegionInfo
;
import
emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo
;
import
emu.grasscutter.net.proto.RegionSimpleInfoOuterClass.RegionSimpleInfo
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson
;
import
emu.grasscutter.server.dispatch.json.*
;
import
emu.grasscutter.server.dispatch.json.ComboTokenResJson
;
import
emu.grasscutter.server.dispatch.json.LoginAccountRequestJson
;
import
emu.grasscutter.server.dispatch.json.LoginResultJson
;
import
emu.grasscutter.server.dispatch.json.LoginTokenRequestJson
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData
;
import
emu.grasscutter.server.dispatch.json.ComboTokenReqJson.LoginTokenData
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.FileUtils
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
import
com.sun.net.httpserver.HttpServer
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
java.io.*
;
import
java.net.InetSocketAddress
;
import
java.net.URI
;
import
java.net.URLDecoder
;
import
java.security.KeyStore
;
import
java.util.*
;
public
final
class
DispatchServer
{
public
final
class
DispatchServer
{
public
static
String
query_region_list
=
""
;
public
static
String
query_cur_region
=
""
;
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
private
final
Gson
gson
;
private
final
Gson
gson
;
private
QueryCurrRegionHttpRsp
currRegion
;
private
final
String
defaultServerName
=
"os_usa"
;
public
String
regionListBase64
;
public
String
regionListBase64
;
public
String
regionCurrentBase64
;
public
HashMap
<
String
,
RegionData
>
regions
;
public
static
String
query_region_list
=
""
;
public
static
String
query_cur_region
=
""
;
public
DispatchServer
()
{
public
DispatchServer
()
{
this
.
address
=
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
DispatchServerIp
,
Grasscutter
.
getConfig
().
DispatchServerPort
);
this
.
regions
=
new
HashMap
<
String
,
RegionData
>();
this
.
address
=
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
,
Grasscutter
.
getConfig
().
getDispatchOptions
().
Port
);
this
.
gson
=
new
GsonBuilder
().
create
();
this
.
gson
=
new
GsonBuilder
().
create
();
this
.
loadQueries
();
this
.
loadQueries
();
...
@@ -71,7 +59,13 @@ public final class DispatchServer {
...
@@ -71,7 +59,13 @@ public final class DispatchServer {
}
}
public
QueryCurrRegionHttpRsp
getCurrRegion
()
{
public
QueryCurrRegionHttpRsp
getCurrRegion
()
{
return
currRegion
;
// Needs to be fixed by having the game servers connect to the dispatch server.
if
(
Grasscutter
.
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
return
regions
.
get
(
defaultServerName
).
parsedRegionQuery
;
}
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] Unsupported run mode for getCurrRegion()"
);
return
null
;
}
}
public
void
loadQueries
()
{
public
void
loadQueries
()
{
...
@@ -81,14 +75,14 @@ public final class DispatchServer {
...
@@ -81,14 +75,14 @@ public final class DispatchServer {
if
(
file
.
exists
())
{
if
(
file
.
exists
())
{
query_region_list
=
new
String
(
FileUtils
.
read
(
file
));
query_region_list
=
new
String
(
FileUtils
.
read
(
file
));
}
else
{
}
else
{
Grasscutter
.
getLogger
().
warn
(
"query_region_list not found! Using default region list."
);
Grasscutter
.
getLogger
().
warn
(
"
[Dispatch]
query_region_list not found! Using default region list."
);
}
}
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_cur_region.txt"
);
file
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"query_cur_region.txt"
);
if
(
file
.
exists
())
{
if
(
file
.
exists
())
{
query_cur_region
=
new
String
(
FileUtils
.
read
(
file
));
query_cur_region
=
new
String
(
FileUtils
.
read
(
file
));
}
else
{
}
else
{
Grasscutter
.
getLogger
().
warn
(
"query_cur_region not found! Using default current region."
);
Grasscutter
.
getLogger
().
warn
(
"
[Dispatch]
query_cur_region not found! Using default current region."
);
}
}
}
}
...
@@ -99,53 +93,80 @@ public final class DispatchServer {
...
@@ -99,53 +93,80 @@ public final class DispatchServer {
byte
[]
decoded2
=
Base64
.
getDecoder
().
decode
(
query_cur_region
);
byte
[]
decoded2
=
Base64
.
getDecoder
().
decode
(
query_cur_region
);
QueryCurrRegionHttpRsp
regionQuery
=
QueryCurrRegionHttpRsp
.
parseFrom
(
decoded2
);
QueryCurrRegionHttpRsp
regionQuery
=
QueryCurrRegionHttpRsp
.
parseFrom
(
decoded2
);
RegionSimpleInfo
server
=
RegionSimpleInfo
.
newBuilder
()
List
<
RegionSimpleInfo
>
servers
=
new
ArrayList
<
RegionSimpleInfo
>();
.
setName
(
"os_usa"
)
List
<
String
>
usedNames
=
new
ArrayList
<
String
>();
// List to check for potential naming conflicts
.
setTitle
(
Grasscutter
.
getConfig
().
GameServerName
)
if
(
Grasscutter
.
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
// Automatically add the game server if in hybrid mode
.
setType
(
"DEV_PUBLIC"
)
RegionSimpleInfo
server
=
RegionSimpleInfo
.
newBuilder
()
.
setDispatchUrl
(
"https://"
+
(
Grasscutter
.
getConfig
().
DispatchServerPublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
DispatchServerIp
:
Grasscutter
.
getConfig
().
DispatchServerPublicIp
)
+
":"
+
getAddress
().
getPort
()
+
"/query_cur_region"
)
.
setName
(
"os_usa"
)
.
build
();
.
setTitle
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
Name
)
.
setType
(
"DEV_PUBLIC"
)
RegionSimpleInfo
serverTest2
=
RegionSimpleInfo
.
newBuilder
()
.
setDispatchUrl
(
"https://"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
)
+
":"
+
getAddress
().
getPort
()
+
"/query_cur_region_"
+
defaultServerName
)
.
setName
(
"os_euro"
)
.
build
();
.
setTitle
(
"Grasscutter"
)
usedNames
.
add
(
defaultServerName
);
.
setType
(
"DEV_PUBLIC"
)
servers
.
add
(
server
);
.
setDispatchUrl
(
"https://"
+
(
Grasscutter
.
getConfig
().
DispatchServerPublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
DispatchServerIp
:
Grasscutter
.
getConfig
().
DispatchServerPublicIp
)
+
":"
+
getAddress
().
getPort
()
+
"/query_cur_region"
)
.
build
();
RegionInfo
serverRegion
=
regionQuery
.
getRegionInfo
().
toBuilder
()
.
setIp
((
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getGameServerOptions
().
Ip
:
Grasscutter
.
getConfig
().
getGameServerOptions
().
PublicIp
))
.
setPort
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
Port
)
.
setSecretKey
(
ByteString
.
copyFrom
(
FileUtils
.
read
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
)))
.
build
();
QueryCurrRegionHttpRsp
parsedRegionQuery
=
regionQuery
.
toBuilder
().
setRegionInfo
(
serverRegion
).
build
();
regions
.
put
(
defaultServerName
,
new
RegionData
(
parsedRegionQuery
,
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
())));
}
else
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
getGameServers
().
length
==
0
)
{
Grasscutter
.
getLogger
().
error
(
"[Dispatch] There are no game servers available. Exiting due to unplayable state."
);
System
.
exit
(
1
);
}
}
for
(
Config
.
DispatchServerOptions
.
RegionInfo
regionInfo
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
getGameServers
())
{
if
(
usedNames
.
contains
(
regionInfo
.
Name
))
{
Grasscutter
.
getLogger
().
error
(
"Region name already in use."
);
continue
;
}
RegionSimpleInfo
server
=
RegionSimpleInfo
.
newBuilder
()
.
setName
(
regionInfo
.
Name
)
.
setTitle
(
regionInfo
.
Title
)
.
setType
(
"DEV_PUBLIC"
)
.
setDispatchUrl
(
"https://"
+
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
getDispatchOptions
().
Ip
:
Grasscutter
.
getConfig
().
getDispatchOptions
().
PublicIp
)
+
":"
+
getAddress
().
getPort
()
+
"/query_cur_region_"
+
regionInfo
.
Name
)
.
build
();
usedNames
.
add
(
regionInfo
.
Name
);
servers
.
add
(
server
);
RegionInfo
serverRegion
=
regionQuery
.
getRegionInfo
().
toBuilder
()
.
setIp
(
regionInfo
.
Ip
)
.
setPort
(
regionInfo
.
Port
)
.
setSecretKey
(
ByteString
.
copyFrom
(
FileUtils
.
read
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
)))
.
build
();
QueryCurrRegionHttpRsp
parsedRegionQuery
=
regionQuery
.
toBuilder
().
setRegionInfo
(
serverRegion
).
build
();
regions
.
put
(
regionInfo
.
Name
,
new
RegionData
(
parsedRegionQuery
,
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
())));
}
QueryRegionListHttpRsp
regionList
=
QueryRegionListHttpRsp
.
newBuilder
()
QueryRegionListHttpRsp
regionList
=
QueryRegionListHttpRsp
.
newBuilder
()
.
addServers
(
server
)
.
addAllServers
(
servers
)
.
addServers
(
serverTest2
)
.
setClientSecretKey
(
rl
.
getClientSecretKey
())
.
setClientSecretKey
(
rl
.
getClientSecretKey
())
.
setClientCustomConfigEncrypted
(
rl
.
getClientCustomConfigEncrypted
())
.
setClientCustomConfigEncrypted
(
rl
.
getClientCustomConfigEncrypted
())
.
setEnableLoginPc
(
true
)
.
setEnableLoginPc
(
true
)
.
build
();
.
build
();
RegionInfo
currentRegion
=
regionQuery
.
getRegionInfo
().
toBuilder
()
.
setIp
((
Grasscutter
.
getConfig
().
GameServerPublicIp
.
isEmpty
()
?
Grasscutter
.
getConfig
().
GameServerIp
:
Grasscutter
.
getConfig
().
GameServerPublicIp
))
.
setPort
(
Grasscutter
.
getConfig
().
GameServerPort
)
.
setSecretKey
(
ByteString
.
copyFrom
(
FileUtils
.
read
(
Grasscutter
.
getConfig
().
KEY_FOLDER
+
"dispatchSeed.bin"
)))
.
build
();
QueryCurrRegionHttpRsp
parsedRegionQuery
=
regionQuery
.
toBuilder
().
setRegionInfo
(
currentRegion
).
build
();
this
.
regionListBase64
=
Base64
.
getEncoder
().
encodeToString
(
regionList
.
toByteString
().
toByteArray
());
this
.
regionListBase64
=
Base64
.
getEncoder
().
encodeToString
(
regionList
.
toByteString
().
toByteArray
());
this
.
regionCurrentBase64
=
Base64
.
getEncoder
().
encodeToString
(
parsedRegionQuery
.
toByteString
().
toByteArray
());
this
.
currRegion
=
parsedRegionQuery
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Error while initializing region info!"
,
e
);
Grasscutter
.
getLogger
().
error
(
"
[Dispatch]
Error while initializing region info!"
,
e
);
}
}
}
}
public
void
start
()
throws
Exception
{
public
void
start
()
throws
Exception
{
HttpServer
server
;
HttpServer
server
;
if
(
Grasscutter
.
getConfig
().
UseSSL
)
{
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
UseSSL
)
{
HttpsServer
httpsServer
;
HttpsServer
httpsServer
;
httpsServer
=
HttpsServer
.
create
(
getAddress
(),
0
);
httpsServer
=
HttpsServer
.
create
(
getAddress
(),
0
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
Dispatch
Server
KeystorePath
))
{
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
get
Dispatch
Options
().
KeystorePath
))
{
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
Dispatch
Server
KeystorePassword
.
toCharArray
();
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
get
Dispatch
Options
().
KeystorePassword
.
toCharArray
();
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
ks
.
load
(
fis
,
keystorePassword
);
ks
.
load
(
fis
,
keystorePassword
);
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"SunX509"
);
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"SunX509"
);
...
@@ -156,56 +177,39 @@ public final class DispatchServer {
...
@@ -156,56 +177,39 @@ public final class DispatchServer {
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
server
=
httpsServer
;
server
=
httpsServer
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"No SSL cert found!"
);
Grasscutter
.
getLogger
().
warn
(
"[Dispatch] No SSL cert found! Falling back to HTTP server."
);
return
;
Grasscutter
.
getConfig
().
getDispatchOptions
().
UseSSL
=
false
;
server
=
HttpServer
.
create
(
getAddress
(),
0
);
}
}
}
else
{
}
else
{
server
=
HttpServer
.
create
(
getAddress
(),
0
);
server
=
HttpServer
.
create
(
getAddress
(),
0
);
}
}
server
.
createContext
(
"/"
,
t
->
{
server
.
createContext
(
"/"
,
t
->
responseHTML
(
t
,
"Hello"
));
//Create a response form the request query parameters
String
response
=
"Hello"
;
//Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
//Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
// Dispatch
// Dispatch
server
.
createContext
(
"/query_region_list"
,
t
->
{
server
.
createContext
(
"/query_region_list"
,
t
->
{
// Log
// Log
Grasscutter
.
getLogger
().
info
(
"Client request: query_region_list"
);
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s request: query_region_list"
,
t
.
getRemoteAddress
()));
// Create a response form the request query parameters
String
response
=
regionListBase64
;
responseHTML
(
t
,
regionListBase64
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
server
.
createContext
(
"/query_cur_region"
,
t
->
{
// Log
Grasscutter
.
getLogger
().
info
(
"Client request: query_cur_region"
);
// Create a response form the request query parameters
URI
uri
=
t
.
getRequestURI
();
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
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
();
});
});
for
(
String
regionName
:
regions
.
keySet
())
{
server
.
createContext
(
"/query_cur_region_"
+
regionName
,
t
->
{
String
regionCurrentBase64
=
regions
.
get
(
regionName
).
Base64
;
// Log
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"Client %s request: query_cur_region_%s"
,
t
.
getRemoteAddress
(),
regionName
));
// Create a response form the request query parameters
URI
uri
=
t
.
getRequestURI
();
String
response
=
"CAESGE5vdCBGb3VuZCB2ZXJzaW9uIGNvbmZpZw=="
;
if
(
uri
.
getQuery
()
!=
null
&&
uri
.
getQuery
().
length
()
>
0
)
{
response
=
regionCurrentBase64
;
}
responseHTML
(
t
,
response
);
});
}
// Login via account
// Login via account
server
.
createContext
(
"/hk4e_global/mdk/shield/api/login"
,
t
->
{
server
.
createContext
(
"/hk4e_global/mdk/shield/api/login"
,
t
->
{
// Get post data
// Get post data
...
@@ -213,14 +217,15 @@ public final class DispatchServer {
...
@@ -213,14 +217,15 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginAccountRequestJson
.
class
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
ignored
)
{
}
}
// Create response json
// Create response json
if
(
requestData
==
null
)
{
if
(
requestData
==
null
)
{
return
;
return
;
}
}
LoginResultJson
responseData
=
new
LoginResultJson
();
LoginResultJson
responseData
=
new
LoginResultJson
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in"
,
t
.
getRemoteAddress
()));
// Login
// Login
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
Account
account
=
DatabaseHelper
.
getAccountByName
(
requestData
.
account
);
...
@@ -228,17 +233,28 @@ public final class DispatchServer {
...
@@ -228,17 +233,28 @@ public final class DispatchServer {
// Check if account exists, else create a new one.
// Check if account exists, else create a new one.
if
(
account
==
null
)
{
if
(
account
==
null
)
{
// Account doesnt exist, so we can either auto create it if the config value is set
// Account doesnt exist, so we can either auto create it if the config value is set
if
(
Grasscutter
.
getConfig
().
Server
Options
.
AutomaticallyCreateAccounts
)
{
if
(
Grasscutter
.
getConfig
().
getDispatch
Options
()
.
AutomaticallyCreateAccounts
)
{
// This account has been created AUTOMATICALLY. There will be no permissions added.
// This account has been created AUTOMATICALLY. There will be no permissions added.
account
=
DatabaseHelper
.
createAccountWithId
(
requestData
.
account
,
0
);
account
=
DatabaseHelper
.
createAccountWithId
(
requestData
.
account
,
0
);
responseData
.
message
=
"OK"
;
if
(
account
!=
null
)
{
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account %s created"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
else
{
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found, create failed."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account create failed"
,
t
.
getRemoteAddress
()));
}
}
else
{
}
else
{
responseData
.
retcode
=
-
201
;
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Username not found."
;
responseData
.
message
=
"Username not found."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in: Account no found"
,
t
.
getRemoteAddress
()));
}
}
}
else
{
}
else
{
// Account was found, log the player in
// Account was found, log the player in
...
@@ -246,17 +262,11 @@ public final class DispatchServer {
...
@@ -246,17 +262,11 @@ public final class DispatchServer {
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
uid
=
account
.
getId
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
token
=
account
.
generateSessionKey
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
}
// Create a response
responseJSON
(
t
,
responseData
);
String
response
=
getGsonFactory
().
toJson
(
responseData
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
// Login via token
// Login via token
server
.
createContext
(
"/hk4e_global/mdk/shield/api/verify"
,
t
->
{
server
.
createContext
(
"/hk4e_global/mdk/shield/api/verify"
,
t
->
{
...
@@ -265,14 +275,14 @@ public final class DispatchServer {
...
@@ -265,14 +275,14 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
LoginTokenRequestJson
.
class
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
ignored
)
{
}
}
// Create response json
// Create response json
if
(
requestData
==
null
)
{
if
(
requestData
==
null
)
{
return
;
return
;
}
}
LoginResultJson
responseData
=
new
LoginResultJson
();
LoginResultJson
responseData
=
new
LoginResultJson
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s is trying to log in via token"
,
t
.
getRemoteAddress
()));
// Login
// Login
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
Account
account
=
DatabaseHelper
.
getAccountById
(
requestData
.
uid
);
...
@@ -281,22 +291,18 @@ public final class DispatchServer {
...
@@ -281,22 +291,18 @@ public final class DispatchServer {
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
requestData
.
token
))
{
responseData
.
retcode
=
-
111
;
responseData
.
retcode
=
-
111
;
responseData
.
message
=
"Game account cache information error"
;
responseData
.
message
=
"Game account cache information error"
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to log in via token"
,
t
.
getRemoteAddress
()));
}
else
{
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
message
=
"OK"
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
uid
=
requestData
.
uid
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
token
=
requestData
.
token
;
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
responseData
.
data
.
account
.
email
=
account
.
getEmail
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s logged in via token as %s"
,
t
.
getRemoteAddress
(),
responseData
.
data
.
account
.
uid
));
}
}
// Create a response
responseJSON
(
t
,
responseData
);
String
response
=
getGsonFactory
().
toJson
(
responseData
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
// Exchange for combo token
// Exchange for combo token
server
.
createContext
(
"/hk4e_global/combo/granter/login/v2/login"
,
t
->
{
server
.
createContext
(
"/hk4e_global/combo/granter/login/v2/login"
,
t
->
{
...
@@ -305,9 +311,8 @@ public final class DispatchServer {
...
@@ -305,9 +311,8 @@ public final class DispatchServer {
try
{
try
{
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
String
body
=
Utils
.
toString
(
t
.
getRequestBody
());
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
requestData
=
getGsonFactory
().
fromJson
(
body
,
ComboTokenReqJson
.
class
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
ignored
)
{
}
}
// Create response json
// Create response json
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
if
(
requestData
==
null
||
requestData
.
data
==
null
)
{
return
;
return
;
...
@@ -322,22 +327,18 @@ public final class DispatchServer {
...
@@ -322,22 +327,18 @@ public final class DispatchServer {
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
if
(
account
==
null
||
!
account
.
getSessionKey
().
equals
(
loginData
.
token
))
{
responseData
.
retcode
=
-
201
;
responseData
.
retcode
=
-
201
;
responseData
.
message
=
"Wrong session key."
;
responseData
.
message
=
"Wrong session key."
;
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s failed to exchange combo token"
,
t
.
getRemoteAddress
()));
}
else
{
}
else
{
responseData
.
message
=
"OK"
;
responseData
.
message
=
"OK"
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
open_id
=
loginData
.
uid
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_id
=
"157795300"
;
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
responseData
.
data
.
combo_token
=
account
.
generateLoginToken
();
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"[Dispatch] Client %s succeed to exchange combo token"
,
t
.
getRemoteAddress
()));
}
}
// Create a response
responseJSON
(
t
,
responseData
);
String
response
=
getGsonFactory
().
toJson
(
responseData
);
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
});
});
// Agreement and Protocol
// Agreement and Protocol
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
server
.
createContext
(
// hk4e-sdk-os.hoyoverse.com
...
@@ -405,63 +406,84 @@ public final class DispatchServer {
...
@@ -405,63 +406,84 @@ public final class DispatchServer {
"/perf/config/verify"
,
"/perf/config/verify"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
// Start server
server
.
start
();
Grasscutter
.
getLogger
().
info
(
"Dispatch server started on port "
+
getAddress
().
getPort
());
// Logging servers
// Logging servers
HttpServer
overseaLogServer
=
HttpServer
.
create
(
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
DispatchServerIp
,
8888
),
0
);
server
.
createContext
(
// overseauspider.yuanshen.com
overseaLogServer
.
createContext
(
// overseauspider.yuanshen.com
"/log"
,
"/log"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
overseaLogServer
.
start
();
Grasscutter
.
getLogger
().
info
(
"Log server (overseauspider) started on port "
+
8888
);
server
.
createContext
(
// log-upload-os.mihoyo.com
"/crash/dataUpload"
,
HttpServer
uploadLogServer
=
HttpServer
.
create
(
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
DispatchServerIp
,
Grasscutter
.
getConfig
().
UploadLogPort
),
0
);
uploadLogServer
.
createContext
(
// log-upload-os.mihoyo.com
"/crash/dataUpload"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
);
);
uploadLogServer
.
createContext
(
"/gacha"
,
t
->
{
server
.
createContext
(
"/gacha"
,
t
->
responseHTML
(
t
,
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
));
//Create a response form the request query parameters
String
response
=
"<!doctype html><html lang=\"en\"><head><title>Gacha</title></head><body></body></html>"
;
// Start server
//Set the response header status and length
server
.
start
();
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
Grasscutter
.
getLogger
().
info
(
"[Dispatch] Dispatch server started on port "
+
getAddress
().
getPort
());
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
}
//Write the response string
OutputStream
os
=
t
.
getResponseBody
();
private
void
responseJSON
(
HttpExchange
t
,
Object
data
)
throws
IOException
{
os
.
write
(
response
.
getBytes
());
// Create a response
os
.
close
();
String
response
=
getGsonFactory
().
toJson
(
data
);
});
// Set the response header status and length
uploadLogServer
.
start
();
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"application/json"
));
Grasscutter
.
getLogger
().
info
(
"Log server (log-upload-os) started on port "
+
Grasscutter
.
getConfig
().
UploadLogPort
);
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
// Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
}
private
void
responseHTML
(
HttpExchange
t
,
String
response
)
throws
IOException
{
// Set the response header status and length
t
.
getResponseHeaders
().
put
(
"Content-Type"
,
Collections
.
singletonList
(
"text/html; charset=UTF-8"
));
t
.
sendResponseHeaders
(
200
,
response
.
getBytes
().
length
);
//Write the response string
OutputStream
os
=
t
.
getResponseBody
();
os
.
write
(
response
.
getBytes
());
os
.
close
();
}
}
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
Map
<
String
,
String
>
result
=
new
HashMap
<>();
Map
<
String
,
String
>
result
=
new
HashMap
<>();
if
(
qs
==
null
)
if
(
qs
==
null
)
{
return
result
;
return
result
;
}
int
last
=
0
,
next
,
l
=
qs
.
length
();
while
(
last
<
l
)
{
int
last
=
0
,
next
,
l
=
qs
.
length
();
next
=
qs
.
indexOf
(
'&'
,
last
);
while
(
last
<
l
)
{
if
(
next
==
-
1
)
next
=
qs
.
indexOf
(
'&'
,
last
);
next
=
l
;
if
(
next
==
-
1
)
{
next
=
l
;
if
(
next
>
last
)
{
}
int
eqPos
=
qs
.
indexOf
(
'='
,
last
);
try
{
if
(
next
>
last
)
{
if
(
eqPos
<
0
||
eqPos
>
next
)
int
eqPos
=
qs
.
indexOf
(
'='
,
last
);
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
next
),
"utf-8"
),
""
);
try
{
else
if
(
eqPos
<
0
||
eqPos
>
next
)
{
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
eqPos
),
"utf-8"
),
URLDecoder
.
decode
(
qs
.
substring
(
eqPos
+
1
,
next
),
"utf-8"
));
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
next
),
"utf-8"
),
""
);
}
catch
(
UnsupportedEncodingException
e
)
{
}
else
{
throw
new
RuntimeException
(
e
);
// will never happen, utf-8 support is mandatory for java
result
.
put
(
URLDecoder
.
decode
(
qs
.
substring
(
last
,
eqPos
),
"utf-8"
),
URLDecoder
.
decode
(
qs
.
substring
(
eqPos
+
1
,
next
),
"utf-8"
));
}
}
}
}
catch
(
UnsupportedEncodingException
e
)
{
last
=
next
+
1
;
throw
new
RuntimeException
(
e
);
// will never happen, utf-8 support is mandatory for java
}
}
return
result
;
}
last
=
next
+
1
;
}
return
result
;
}
public
static
class
RegionData
{
QueryCurrRegionHttpRsp
parsedRegionQuery
;
String
Base64
;
public
RegionData
(
QueryCurrRegionHttpRsp
prq
,
String
b64
)
{
this
.
parsedRegionQuery
=
prq
;
this
.
Base64
=
b64
;
}
}
}
}
}
src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenReqJson.java
View file @
6e81dc39
...
@@ -7,7 +7,7 @@ public class ComboTokenReqJson {
...
@@ -7,7 +7,7 @@ public class ComboTokenReqJson {
public
String
device
;
public
String
device
;
public
String
sign
;
public
String
sign
;
public
class
LoginTokenData
{
public
static
class
LoginTokenData
{
public
String
uid
;
public
String
uid
;
public
String
token
;
public
String
token
;
public
boolean
guest
;
public
boolean
guest
;
...
...
src/main/java/emu/grasscutter/server/dispatch/json/ComboTokenResJson.java
View file @
6e81dc39
...
@@ -5,7 +5,7 @@ public class ComboTokenResJson {
...
@@ -5,7 +5,7 @@ public class ComboTokenResJson {
public
int
retcode
;
public
int
retcode
;
public
LoginData
data
=
new
LoginData
();
public
LoginData
data
=
new
LoginData
();
public
class
LoginData
{
public
static
class
LoginData
{
public
int
account_type
=
1
;
public
int
account_type
=
1
;
public
boolean
heartbeat
;
public
boolean
heartbeat
;
public
String
combo_id
;
public
String
combo_id
;
...
...
src/main/java/emu/grasscutter/server/dispatch/json/LoginResultJson.java
View file @
6e81dc39
...
@@ -5,7 +5,7 @@ public class LoginResultJson {
...
@@ -5,7 +5,7 @@ public class LoginResultJson {
public
int
retcode
;
public
int
retcode
;
public
VerifyData
data
=
new
VerifyData
();
public
VerifyData
data
=
new
VerifyData
();
public
class
VerifyData
{
public
static
class
VerifyData
{
public
VerifyAccountData
account
=
new
VerifyAccountData
();
public
VerifyAccountData
account
=
new
VerifyAccountData
();
public
boolean
device_grant_required
=
false
;
public
boolean
device_grant_required
=
false
;
public
String
realname_operation
=
"NONE"
;
public
String
realname_operation
=
"NONE"
;
...
@@ -13,7 +13,7 @@ public class LoginResultJson {
...
@@ -13,7 +13,7 @@ public class LoginResultJson {
public
boolean
safe_mobile_required
=
false
;
public
boolean
safe_mobile_required
=
false
;
}
}
public
class
VerifyAccountData
{
public
static
class
VerifyAccountData
{
public
String
uid
;
public
String
uid
;
public
String
name
=
""
;
public
String
name
=
""
;
public
String
email
;
public
String
email
;
...
...
src/main/java/emu/grasscutter/server/game/GameServer.java
View file @
6e81dc39
...
@@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentHashMap;
...
@@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentHashMap;
import
emu.grasscutter.GenshinConstants
;
import
emu.grasscutter.GenshinConstants
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command
s
.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.GenshinPlayer
;
...
@@ -19,6 +19,7 @@ import emu.grasscutter.game.shop.ShopManager;
...
@@ -19,6 +19,7 @@ import emu.grasscutter.game.shop.ShopManager;
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.MihoyoKcpServer
;
import
org.greenrobot.eventbus.EventBus
;
public
final
class
GameServer
extends
MihoyoKcpServer
{
public
final
class
GameServer
extends
MihoyoKcpServer
{
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
...
@@ -33,10 +34,18 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -33,10 +34,18 @@ public final class GameServer extends MihoyoKcpServer {
private
final
MultiplayerManager
multiplayerManager
;
private
final
MultiplayerManager
multiplayerManager
;
private
final
DungeonManager
dungeonManager
;
private
final
DungeonManager
dungeonManager
;
private
final
CommandMap
commandMap
;
private
final
CommandMap
commandMap
;
public
EventBus
OnGameServerStartFinish
;
public
EventBus
OnGameServerTick
;
public
EventBus
OnGameServerStop
;
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
);
...
@@ -145,7 +154,7 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -145,7 +154,7 @@ public final class GameServer extends MihoyoKcpServer {
public
Account
getAccountByName
(
String
username
)
{
public
Account
getAccountByName
(
String
username
)
{
Optional
<
GenshinPlayer
>
playerOpt
=
getPlayers
().
values
().
stream
().
filter
(
player
->
player
.
getAccount
().
getUsername
().
equals
(
username
)).
findFirst
();
Optional
<
GenshinPlayer
>
playerOpt
=
getPlayers
().
values
().
stream
().
filter
(
player
->
player
.
getAccount
().
getUsername
().
equals
(
username
)).
findFirst
();
if
(
playerOpt
.
get
()
!=
null
)
{
if
(
playerOpt
.
isPresent
()
)
{
return
playerOpt
.
get
().
getAccount
();
return
playerOpt
.
get
().
getAccount
();
}
}
return
DatabaseHelper
.
getAccountByName
(
username
);
return
DatabaseHelper
.
getAccountByName
(
username
);
...
@@ -155,14 +164,20 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -155,14 +164,20 @@ public final class GameServer extends MihoyoKcpServer {
for
(
GenshinPlayer
player
:
this
.
getPlayers
().
values
())
{
for
(
GenshinPlayer
player
:
this
.
getPlayers
().
values
())
{
player
.
onTick
();
player
.
onTick
();
}
}
OnGameServerTick
.
post
(
new
GameServerTickEvent
());
}
}
@Override
@Override
public
void
onStartFinish
()
{
public
void
onStartFinish
()
{
Grasscutter
.
getLogger
().
info
(
"Game Server started on port "
+
address
.
getPort
());
Grasscutter
.
getLogger
().
info
(
"Game Server started on port "
+
address
.
getPort
());
OnGameServerStartFinish
.
post
(
new
GameServerStartFinishEvent
());
}
}
public
void
onServerShutdown
()
{
public
void
onServerShutdown
()
{
OnGameServerStop
.
post
(
new
GameServerStopEvent
());
// Kick and save all players
// Kick and save all players
List
<
GenshinPlayer
>
list
=
new
ArrayList
<>(
this
.
getPlayers
().
size
());
List
<
GenshinPlayer
>
list
=
new
ArrayList
<>(
this
.
getPlayers
().
size
());
list
.
addAll
(
this
.
getPlayers
().
values
());
list
.
addAll
(
this
.
getPlayers
().
values
());
...
...
src/main/java/emu/grasscutter/server/game/GameServerPacketHandler.java
View file @
6e81dc39
...
@@ -87,7 +87,7 @@ public class GameServerPacketHandler {
...
@@ -87,7 +87,7 @@ public class GameServerPacketHandler {
}
}
// Log unhandled packets
// Log unhandled packets
if
(
Grasscutter
.
getConfig
().
LOG_PACKETS
)
{
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
//Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + PacketOpcodesUtil.getOpcodeName(opcode));
//Grasscutter.getLogger().info("Unhandled packet (" + opcode + "): " + PacketOpcodesUtil.getOpcodeName(opcode));
}
}
}
}
...
...
src/main/java/emu/grasscutter/server/game/GameServerStartFinishEvent.java
0 → 100644
View file @
6e81dc39
package
emu.grasscutter.server.game
;
public
class
GameServerStartFinishEvent
{
// Placeholder class for now, probably will get used later
}
src/main/java/emu/grasscutter/server/game/GameServerStopEvent.java
0 → 100644
View file @
6e81dc39
package
emu.grasscutter.server.game
;
public
class
GameServerStopEvent
{
// Placeholder class for now, probably will get used later
}
src/main/java/emu/grasscutter/server/game/GameServerTickEvent.java
0 → 100644
View file @
6e81dc39
package
emu.grasscutter.server.game
;
public
class
GameServerTickEvent
{
// Placeholder class for now, probably will get used later
}
src/main/java/emu/grasscutter/server/game/GameSession.java
View file @
6e81dc39
...
@@ -165,7 +165,7 @@ public class GameSession extends MihoyoKcpChannel {
...
@@ -165,7 +165,7 @@ public class GameSession extends MihoyoKcpChannel {
byte
[]
data
=
genshinPacket
.
build
();
byte
[]
data
=
genshinPacket
.
build
();
// Log
// Log
if
(
Grasscutter
.
getConfig
().
LOG_PACKETS
)
{
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
logPacket
(
genshinPacket
);
logPacket
(
genshinPacket
);
}
}
...
@@ -225,7 +225,7 @@ public class GameSession extends MihoyoKcpChannel {
...
@@ -225,7 +225,7 @@ public class GameSession extends MihoyoKcpChannel {
}
}
// Log packet
// Log packet
if
(
Grasscutter
.
getConfig
().
LOG_PACKETS
)
{
if
(
Grasscutter
.
getConfig
().
getGameServerOptions
().
LOG_PACKETS
)
{
Grasscutter
.
getLogger
().
info
(
"RECV: "
+
PacketOpcodesUtil
.
getOpcodeName
(
opcode
)
+
" ("
+
opcode
+
")"
);
Grasscutter
.
getLogger
().
info
(
"RECV: "
+
PacketOpcodesUtil
.
getOpcodeName
(
opcode
)
+
" ("
+
opcode
+
")"
);
System
.
out
.
println
(
Utils
.
bytesToHex
(
payload
));
System
.
out
.
println
(
Utils
.
bytesToHex
(
payload
));
}
}
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java
0 → 100644
View file @
6e81dc39
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry
;
import
emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.server.game.GameSession
;
@Opcodes
(
PacketOpcodes
.
ClientAbilityInitFinishNotify
)
public
class
HandlerClientAbilityInitFinishNotify
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
ClientAbilityInitFinishNotify
notif
=
ClientAbilityInitFinishNotify
.
parseFrom
(
payload
);
for
(
AbilityInvokeEntry
entry
:
notif
.
getInvokesList
())
{
session
.
getPlayer
().
getClientAbilityInitFinishHandler
().
addEntry
(
entry
.
getForwardType
(),
entry
);
}
if
(
notif
.
getInvokesList
().
size
()
>
0
)
{
session
.
getPlayer
().
getClientAbilityInitFinishHandler
().
update
(
session
.
getPlayer
());
}
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java
View file @
6e81dc39
...
@@ -31,8 +31,11 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
...
@@ -31,8 +31,11 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
// Locations
// Locations
session
.
send
(
new
PacketWorldPlayerLocationNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketWorldPlayerLocationNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketScenePlayerLocationNotify
(
session
.
getPlayer
()));
session
.
send
(
new
PacketScenePlayerLocationNotify
(
session
.
getPlayer
()
.
getScene
()
));
session
.
send
(
new
PacketWorldPlayerRTTNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketWorldPlayerRTTNotify
(
session
.
getPlayer
().
getWorld
()));
// Reset timer for sending player locations
session
.
getPlayer
().
resetSendPlayerLocTime
();
}
}
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerGetPlayerTokenReq.java
View file @
6e81dc39
...
@@ -35,15 +35,15 @@ public class HandlerGetPlayerTokenReq extends PacketHandler {
...
@@ -35,15 +35,15 @@ public class HandlerGetPlayerTokenReq extends PacketHandler {
// Has character
// Has character
boolean
doesPlayerExist
=
false
;
boolean
doesPlayerExist
=
false
;
if
(
account
.
getPlayer
I
d
()
>
0
)
{
if
(
account
.
getPlayer
Ui
d
()
>
0
)
{
// Set flag for player existing
// Set flag for player existing
doesPlayerExist
=
DatabaseHelper
.
checkPlayerExists
(
account
.
getPlayer
I
d
());
doesPlayerExist
=
DatabaseHelper
.
checkPlayerExists
(
account
.
getPlayer
Ui
d
());
}
}
// Set reserve player id if account doesnt exist
// Set reserve player id if account doesnt exist
if
(!
doesPlayerExist
)
{
if
(!
doesPlayerExist
)
{
int
id
=
DatabaseHelper
.
getNextPlayerId
(
session
.
getAccount
().
getPlayer
I
d
());
int
id
=
DatabaseHelper
.
getNextPlayerId
(
session
.
getAccount
().
getPlayer
Ui
d
());
if
(
id
!=
session
.
getAccount
().
getPlayer
I
d
())
{
if
(
id
!=
session
.
getAccount
().
getPlayer
Ui
d
())
{
session
.
getAccount
().
setPlayerId
(
id
);
session
.
getAccount
().
setPlayerId
(
id
);
session
.
getAccount
().
save
();
session
.
getAccount
().
save
();
}
}
...
...
Prev
1
2
3
4
5
6
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