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
eac3745f
Commit
eac3745f
authored
Apr 19, 2022
by
Jaida Wu
Committed by
GitHub
Apr 19, 2022
Browse files
Merge branch 'Melledy:main' into main
parents
49f640cb
3e7dc503
Changes
21
Hide whitespace changes
Inline
Side-by-side
src/deprecated/java/emu/grasscutter/commands/PlayerCommands.java
0 → 100644
View file @
eac3745f
package
emu.grasscutter.commands
;
import
java.lang.reflect.Modifier
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.avatar.GenshinAvatar
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.entity.EntityItem
;
import
emu.grasscutter.game.entity.EntityMonster
;
import
emu.grasscutter.game.entity.GenshinEntity
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.inventory.ItemType
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketItemAddHintNotify
;
import
emu.grasscutter.utils.Position
;
public
class
PlayerCommands
{
private
static
HashMap
<
String
,
PlayerCommand
>
list
=
new
HashMap
<>();
static
{
try
{
// Look for classes
for
(
Class
<?>
cls
:
PlayerCommands
.
class
.
getDeclaredClasses
())
{
// Get non abstract classes
if
(!
Modifier
.
isAbstract
(
cls
.
getModifiers
()))
{
Command
commandAnnotation
=
cls
.
getAnnotation
(
Command
.
class
);
PlayerCommand
command
=
(
PlayerCommand
)
cls
.
newInstance
();
if
(
commandAnnotation
!=
null
)
{
command
.
setLevel
(
commandAnnotation
.
gmLevel
());
for
(
String
alias
:
commandAnnotation
.
aliases
())
{
if
(
alias
.
length
()
==
0
)
{
continue
;
}
String
commandName
=
"!"
+
alias
;
list
.
put
(
commandName
,
command
);
commandName
=
"/"
+
alias
;
list
.
put
(
commandName
,
command
);
}
}
String
commandName
=
"!"
+
cls
.
getSimpleName
().
toLowerCase
();
list
.
put
(
commandName
,
command
);
commandName
=
"/"
+
cls
.
getSimpleName
().
toLowerCase
();
list
.
put
(
commandName
,
command
);
}
}
}
catch
(
Exception
e
)
{
}
}
public
static
void
handle
(
GenshinPlayer
player
,
String
msg
)
{
String
[]
split
=
msg
.
split
(
" "
);
// End if invalid
if
(
split
.
length
==
0
)
{
return
;
}
//
String
first
=
split
[
0
].
toLowerCase
();
PlayerCommand
c
=
PlayerCommands
.
list
.
get
(
first
);
if
(
c
!=
null
)
{
// Level check
if
(
player
.
getGmLevel
()
<
c
.
getLevel
())
{
return
;
}
// Execute
int
len
=
Math
.
min
(
first
.
length
()
+
1
,
msg
.
length
());
c
.
execute
(
player
,
msg
.
substring
(
len
));
}
}
public
static
abstract
class
PlayerCommand
{
// GM level required to use this command
private
int
level
;
protected
int
getLevel
()
{
return
this
.
level
;
}
protected
void
setLevel
(
int
minLevel
)
{
this
.
level
=
minLevel
;
}
// Main
public
abstract
void
execute
(
GenshinPlayer
player
,
String
raw
);
}
// ================ Commands ================
@Command
(
aliases
=
{
"g"
,
"item"
,
"additem"
},
helpText
=
"/give [item id] [count] - Gives {count} amount of {item id}"
)
public
static
class
Give
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
itemId
=
0
,
count
=
1
;
try
{
itemId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
itemId
=
0
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
GenshinItem
item
;
if
(
itemData
==
null
)
{
player
.
dropMessage
(
"Error: Item data not found"
);
return
;
}
if
(
itemData
.
isEquip
())
{
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
item
=
new
GenshinItem
(
itemData
);
items
.
add
(
item
);
}
player
.
getInventory
().
addItems
(
items
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
}
else
{
item
=
new
GenshinItem
(
itemData
,
count
);
player
.
getInventory
().
addItem
(
item
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
item
,
ActionReason
.
SubfieldDrop
));
}
}
}
@Command
(
aliases
=
{
"d"
},
helpText
=
"/drop [item id] [count] - Drops {count} amount of {item id}"
)
public
static
class
Drop
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
itemId
=
0
,
count
=
1
;
try
{
itemId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
itemId
=
0
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
if
(
itemData
==
null
)
{
player
.
dropMessage
(
"Error: Item data not found"
);
return
;
}
if
(
itemData
.
isEquip
())
{
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
pos
,
1
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
else
{
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
count
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
@Command
(
helpText
=
"/spawn [monster id] [count] - Creates {count} amount of {item id}"
)
public
static
class
Spawn
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
monsterId
=
0
,
count
=
1
,
level
=
1
;
try
{
monsterId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
monsterId
=
0
;
}
try
{
level
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
200
),
1
);
}
catch
(
Exception
e
)
{
level
=
1
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
2
]),
1000
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
MonsterData
monsterData
=
GenshinData
.
getMonsterDataMap
().
get
(
monsterId
);
if
(
monsterData
==
null
)
{
player
.
dropMessage
(
"Error: Monster data not found"
);
return
;
}
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityMonster
entity
=
new
EntityMonster
(
player
.
getWorld
(),
monsterData
,
pos
,
level
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
@Command
(
helpText
=
"/killall"
)
public
static
class
KillAll
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
List
<
GenshinEntity
>
toRemove
=
new
LinkedList
<>();
for
(
GenshinEntity
entity
:
player
.
getWorld
().
getEntities
().
values
())
{
if
(
entity
instanceof
EntityMonster
)
{
toRemove
.
add
(
entity
);
}
}
toRemove
.
forEach
(
e
->
player
.
getWorld
().
killEntity
(
e
,
0
));
}
}
@Command
(
helpText
=
"/resetconst - Resets all constellations for the currently active character"
)
public
static
class
ResetConst
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
{
return
;
}
GenshinAvatar
avatar
=
entity
.
getAvatar
();
avatar
.
getTalentIdList
().
clear
();
avatar
.
setCoreProudSkillLevel
(
0
);
avatar
.
recalcStats
();
avatar
.
save
();
player
.
dropMessage
(
"Constellations for "
+
entity
.
getAvatar
().
getAvatarData
().
getName
()
+
" have been reset. Please relogin to see changes."
);
}
}
@Command
(
helpText
=
"/godmode - Prevents you from taking damage"
)
public
static
class
Godmode
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
player
.
setGodmode
(!
player
.
hasGodmode
());
player
.
dropMessage
(
"Godmode is now "
+
(
player
.
hasGodmode
()
?
"ON"
:
"OFF"
));
}
}
@Command
(
helpText
=
"/sethp [hp]"
)
public
static
class
Sethp
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
hp
=
0
;
try
{
hp
=
Math
.
max
(
Integer
.
parseInt
(
split
[
0
]),
1
);
}
catch
(
Exception
e
)
{
hp
=
1
;
}
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
{
return
;
}
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
hp
);
entity
.
getWorld
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
}
}
@Command
(
aliases
=
{
"clearart"
},
helpText
=
"/clearartifacts"
)
public
static
class
ClearArtifacts
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
List
<
GenshinItem
>
toRemove
=
new
LinkedList
<>();
for
(
GenshinItem
item
:
player
.
getInventory
().
getItems
().
values
())
{
if
(
item
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
&&
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
&&
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
{
toRemove
.
add
(
item
);
}
}
player
.
getInventory
().
removeItems
(
toRemove
);
}
}
}
src/deprecated/java/emu/grasscutter/commands/ServerCommands.java
0 → 100644
View file @
eac3745f
package
emu.grasscutter.commands
;
import
java.lang.reflect.Modifier
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.Utils
;
public
class
ServerCommands
{
private
static
HashMap
<
String
,
ServerCommand
>
list
=
new
HashMap
<>();
static
{
try
{
// Look for classes
for
(
Class
<?>
cls
:
ServerCommands
.
class
.
getDeclaredClasses
())
{
// Get non abstract classes
if
(!
Modifier
.
isAbstract
(
cls
.
getModifiers
()))
{
String
commandName
=
cls
.
getSimpleName
().
toLowerCase
();
list
.
put
(
commandName
,
(
ServerCommand
)
cls
.
newInstance
());
}
}
}
catch
(
Exception
e
)
{
}
}
public
static
void
handle
(
String
msg
)
{
String
[]
split
=
msg
.
split
(
" "
);
// End if invalid
if
(
split
.
length
==
0
)
{
return
;
}
//
String
first
=
split
[
0
].
toLowerCase
();
ServerCommand
c
=
ServerCommands
.
list
.
get
(
first
);
if
(
c
!=
null
)
{
// Execute
int
len
=
Math
.
min
(
first
.
length
()
+
1
,
msg
.
length
());
c
.
execute
(
msg
.
substring
(
len
));
}
}
public
static
abstract
class
ServerCommand
{
public
abstract
void
execute
(
String
raw
);
}
// ================ Commands ================
public
static
class
Reload
extends
ServerCommand
{
@Override
public
void
execute
(
String
raw
)
{
Grasscutter
.
getLogger
().
info
(
"Reloading config."
);
Grasscutter
.
loadConfig
();
Grasscutter
.
getDispatchServer
().
loadQueries
();
Grasscutter
.
getLogger
().
info
(
"Reload complete."
);
}
}
public
static
class
sendMsg
extends
ServerCommand
{
@Override
public
void
execute
(
String
raw
)
{
List
<
String
>
split
=
Arrays
.
asList
(
raw
.
split
(
" "
));
if
(
split
.
size
()
<
2
)
{
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
return
;
}
String
playerID
=
split
.
get
(
0
);
String
message
=
split
.
stream
().
skip
(
1
).
collect
(
Collectors
.
joining
(
" "
));
emu
.
grasscutter
.
game
.
Account
account
=
DatabaseHelper
.
getAccountByPlayerId
(
Integer
.
parseInt
(
playerID
));
if
(
account
!=
null
)
{
GenshinPlayer
player
=
Grasscutter
.
getGameServer
().
getPlayerById
(
Integer
.
parseInt
(
playerID
));
if
(
player
!=
null
)
{
player
.
dropMessage
(
message
);
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"Successfully sent message to %s: %s"
,
playerID
,
message
));
}
else
{
Grasscutter
.
getLogger
().
error
(
"Player not online"
);
}
}
else
{
Grasscutter
.
getLogger
().
error
(
String
.
format
(
"Player %s does not exist"
,
playerID
));
}
}
}
public
static
class
Account
extends
ServerCommand
{
@Override
public
void
execute
(
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
if
(
split
.
length
<
2
)
{
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
return
;
}
String
command
=
split
[
0
].
toLowerCase
();
String
username
=
split
[
1
];
switch
(
command
)
{
case
"create"
:
if
(
split
.
length
<
2
)
{
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
return
;
}
int
reservedId
=
0
;
try
{
reservedId
=
Integer
.
parseInt
(
split
[
2
]);
}
catch
(
Exception
e
)
{
reservedId
=
0
;
}
emu
.
grasscutter
.
game
.
Account
account
=
DatabaseHelper
.
createAccountWithId
(
username
,
reservedId
);
if
(
account
!=
null
)
{
Grasscutter
.
getLogger
().
info
(
"Account created"
+
(
reservedId
>
0
?
" with an id of "
+
reservedId
:
""
));
}
else
{
Grasscutter
.
getLogger
().
error
(
"Account already exists"
);
}
break
;
case
"delete"
:
boolean
success
=
DatabaseHelper
.
deleteAccount
(
username
);
if
(
success
)
{
Grasscutter
.
getLogger
().
info
(
"Account deleted"
);
}
break
;
/*
case "setpw":
case "setpass":
case "setpassword":
if (split.length < 3) {
Grasscutter.getLogger().error("Invalid amount of args");
return;
}
account = DatabaseHelper.getAccountByName(username);
if (account == null) {
Grasscutter.getLogger().error("No account found!");
return;
}
token = split[2];
token = PasswordHelper.hashPassword(token);
account.setPassword(token);
DatabaseHelper.saveAccount(account);
Grasscutter.getLogger().info("Password set");
break;
*/
}
}
}
}
src/main/java/emu/grasscutter/Config.java
View file @
eac3745f
...
@@ -6,12 +6,15 @@ public final class Config {
...
@@ -6,12 +6,15 @@ public final class Config {
public
int
DispatchServerPort
=
443
;
public
int
DispatchServerPort
=
443
;
public
String
DispatchServerKeystorePath
=
"./keystore.p12"
;
public
String
DispatchServerKeystorePath
=
"./keystore.p12"
;
public
String
DispatchServerKeystorePassword
=
""
;
public
String
DispatchServerKeystorePassword
=
""
;
public
Boolean
UseSSL
=
true
;
public
String
GameServerName
=
"Test"
;
public
String
GameServerName
=
"Test"
;
public
String
GameServerIp
=
"127.0.0.1"
;
public
String
GameServerIp
=
"127.0.0.1"
;
public
String
GameServerPublicIp
=
""
;
public
String
GameServerPublicIp
=
""
;
public
int
GameServerPort
=
22102
;
public
int
GameServerPort
=
22102
;
public
int
UploadLogPort
=
80
;
public
String
DatabaseUrl
=
"mongodb://localhost:27017"
;
public
String
DatabaseUrl
=
"mongodb://localhost:27017"
;
public
String
DatabaseCollection
=
"grasscutter"
;
public
String
DatabaseCollection
=
"grasscutter"
;
...
...
src/main/java/emu/grasscutter/Grasscutter.java
View file @
eac3745f
...
@@ -7,14 +7,15 @@ import java.io.FileWriter;
...
@@ -7,14 +7,15 @@ import java.io.FileWriter;
import
java.io.InputStreamReader
;
import
java.io.InputStreamReader
;
import
java.net.InetSocketAddress
;
import
java.net.InetSocketAddress
;
import
emu.grasscutter.commands.CommandMap
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
import
org.reflections.Reflections
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
com.google.gson.Gson
;
import
com.google.gson.Gson
;
import
com.google.gson.GsonBuilder
;
import
com.google.gson.GsonBuilder
;
import
ch.qos.logback.classic.Logger
;
import
ch.qos.logback.classic.Logger
;
import
emu.grasscutter.commands.ServerCommands
;
import
emu.grasscutter.data.ResourceLoader
;
import
emu.grasscutter.data.ResourceLoader
;
import
emu.grasscutter.database.DatabaseManager
;
import
emu.grasscutter.database.DatabaseManager
;
import
emu.grasscutter.server.dispatch.DispatchServer
;
import
emu.grasscutter.server.dispatch.DispatchServer
;
...
@@ -23,10 +24,6 @@ import emu.grasscutter.tools.Tools;
...
@@ -23,10 +24,6 @@ import emu.grasscutter.tools.Tools;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.Crypto
;
public
final
class
Grasscutter
{
public
final
class
Grasscutter
{
static
{
System
.
setProperty
(
"logback.configurationFile"
,
"src/main/resources/logback.xml"
);
}
private
static
final
Logger
log
=
(
Logger
)
LoggerFactory
.
getLogger
(
Grasscutter
.
class
);
private
static
final
Logger
log
=
(
Logger
)
LoggerFactory
.
getLogger
(
Grasscutter
.
class
);
private
static
Config
config
;
private
static
Config
config
;
...
@@ -37,8 +34,13 @@ public final class Grasscutter {
...
@@ -37,8 +34,13 @@ public final class Grasscutter {
private
static
DispatchServer
dispatchServer
;
private
static
DispatchServer
dispatchServer
;
private
static
GameServer
gameServer
;
private
static
GameServer
gameServer
;
public
static
final
Reflections
reflector
=
new
Reflections
();
static
{
static
{
// Load configuration.
// Declare logback configuration.
System
.
setProperty
(
"logback.configurationFile"
,
"src/main/resources/logback.xml"
);
// Load server configuration.
Grasscutter
.
loadConfig
();
Grasscutter
.
loadConfig
();
// Check server structure.
// Check server structure.
Utils
.
startupCheck
();
Utils
.
startupCheck
();
...
@@ -100,7 +102,11 @@ public final class Grasscutter {
...
@@ -100,7 +102,11 @@ public final class Grasscutter {
String
input
;
String
input
;
try
(
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
)))
{
try
(
BufferedReader
br
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
)))
{
while
((
input
=
br
.
readLine
())
!=
null
)
{
while
((
input
=
br
.
readLine
())
!=
null
)
{
ServerCommands
.
handle
(
input
);
try
{
CommandMap
.
getInstance
().
invoke
(
null
,
input
);
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Command error: "
+
e
.
getMessage
());
}
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"An error occurred."
,
e
);
Grasscutter
.
getLogger
().
error
(
"An error occurred."
,
e
);
...
...
src/main/java/emu/grasscutter/commands/Command.java
View file @
eac3745f
...
@@ -5,9 +5,19 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -5,9 +5,19 @@ import java.lang.annotation.RetentionPolicy;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Command
{
public
@interface
Command
{
String
[]
aliases
()
default
""
;
String
label
()
default
""
;
String
usage
()
default
""
;
String
[]
aliases
()
default
{
""
};
Execution
execution
()
default
Execution
.
ALL
;
int
gmLevel
()
default
1
;
String
permission
()
default
""
;
String
helpText
()
default
""
;
enum
Execution
{
ALL
,
CONSOLE
,
PLAYER
}
}
}
src/main/java/emu/grasscutter/commands/CommandHandler.java
0 → 100644
View file @
eac3745f
package
emu.grasscutter.commands
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.game.GenshinPlayer
;
import
java.util.List
;
public
interface
CommandHandler
{
/* Invoked on player execution. */
default
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
}
/* Invoked on server execution. */
default
void
execute
(
List
<
String
>
args
)
{
}
/*
* Utilities.
*/
/**
* Send a message to the target.
* @param player The player to send the message to, or null for the server console.
* @param message The message to send.
*/
static
void
sendMessage
(
GenshinPlayer
player
,
String
message
)
{
if
(
player
==
null
)
{
Grasscutter
.
getLogger
().
info
(
message
);
}
else
player
.
dropMessage
(
message
);
}
}
src/main/java/emu/grasscutter/commands/CommandMap.java
0 → 100644
View file @
eac3745f
package
emu.grasscutter.commands
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.GenshinPlayer
;
import
org.reflections.Reflections
;
import
java.util.*
;
@SuppressWarnings
(
"UnusedReturnValue"
)
public
final
class
CommandMap
{
public
static
CommandMap
getInstance
()
{
return
Grasscutter
.
getGameServer
().
getCommandMap
();
}
private
final
Map
<
String
,
CommandHandler
>
commands
=
new
HashMap
<>();
private
final
Map
<
String
,
Command
>
annotations
=
new
HashMap
<>();
/**
* Register a command handler.
* @param label The command label.
* @param command The command handler.
* @return Instance chaining.
*/
public
CommandMap
registerCommand
(
String
label
,
CommandHandler
command
)
{
Grasscutter
.
getLogger
().
debug
(
"Registered command: "
+
label
);
// Get command data.
Command
annotation
=
command
.
getClass
().
getAnnotation
(
Command
.
class
);
this
.
annotations
.
put
(
label
,
annotation
);
this
.
commands
.
put
(
label
,
command
);
// Register aliases.
if
(
annotation
.
aliases
().
length
>
0
)
{
for
(
String
alias
:
annotation
.
aliases
())
{
this
.
commands
.
put
(
alias
,
command
);
this
.
annotations
.
put
(
alias
,
annotation
);
}
}
return
this
;
}
/**
* Removes a registered command handler.
* @param label The command label.
* @return Instance chaining.
*/
public
CommandMap
unregisterCommand
(
String
label
)
{
Grasscutter
.
getLogger
().
debug
(
"Unregistered command: "
+
label
);
CommandHandler
handler
=
this
.
commands
.
get
(
label
);
if
(
handler
==
null
)
return
this
;
Command
annotation
=
handler
.
getClass
().
getAnnotation
(
Command
.
class
);
this
.
annotations
.
remove
(
label
);
this
.
commands
.
remove
(
label
);
// Unregister aliases.
if
(
annotation
.
aliases
().
length
>
0
)
{
for
(
String
alias
:
annotation
.
aliases
())
{
this
.
commands
.
remove
(
alias
);
this
.
annotations
.
remove
(
alias
);
}
}
return
this
;
}
/**
* Returns a list of all registered commands.
* @return All command handlers as a list.
*/
public
List
<
CommandHandler
>
getHandlers
()
{
return
new
LinkedList
<>(
this
.
commands
.
values
());
}
/**
* Returns a handler by label/alias.
* @param label The command label.
* @return The command handler.
*/
public
CommandHandler
getHandler
(
String
label
)
{
return
this
.
commands
.
get
(
label
);
}
/**
* Invoke a command handler with the given arguments.
* @param player The player invoking the command or null for the server console.
* @param rawMessage The messaged used to invoke the command.
*/
public
void
invoke
(
GenshinPlayer
player
,
String
rawMessage
)
{
rawMessage
=
rawMessage
.
trim
();
if
(
rawMessage
.
length
()
==
0
)
{
CommandHandler
.
sendMessage
(
player
,
"No command specified."
);
}
// Remove prefix if present.
if
(!
Character
.
isLetter
(
rawMessage
.
charAt
(
0
)))
rawMessage
=
rawMessage
.
substring
(
1
);
// Parse message.
String
[]
split
=
rawMessage
.
split
(
" "
);
List
<
String
>
args
=
new
LinkedList
<>(
Arrays
.
asList
(
split
));
String
label
=
args
.
remove
(
0
);
// Get command handler.
CommandHandler
handler
=
this
.
commands
.
get
(
label
);
if
(
handler
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Unknown command: "
+
label
);
return
;
}
// Check for permission.
if
(
player
!=
null
)
{
String
permissionNode
=
this
.
annotations
.
get
(
label
).
permission
();
Account
account
=
player
.
getAccount
();
List
<
String
>
permissions
=
account
.
getPermissions
();
if
(!
permissions
.
contains
(
"*"
)
&&
!
permissions
.
contains
(
permissionNode
))
{
CommandHandler
.
sendMessage
(
player
,
"You do not have permission to run this command."
);
return
;
}
}
// Execution power check.
Command
.
Execution
executionPower
=
this
.
annotations
.
get
(
label
).
execution
();
if
(
player
==
null
&&
executionPower
==
Command
.
Execution
.
PLAYER
)
{
CommandHandler
.
sendMessage
(
null
,
"Run this command in-game."
);
return
;
}
else
if
(
player
!=
null
&&
executionPower
==
Command
.
Execution
.
CONSOLE
)
{
CommandHandler
.
sendMessage
(
player
,
"This command can only be run from the console."
);
return
;
}
// Invoke execute method for handler.
if
(
player
==
null
)
handler
.
execute
(
args
);
else
handler
.
execute
(
player
,
args
);
}
public
CommandMap
()
{
this
(
false
);
}
public
CommandMap
(
boolean
scan
)
{
if
(
scan
)
this
.
scan
();
}
/**
* Scans for all classes annotated with {@link Command} and registers them.
*/
private
void
scan
()
{
Reflections
reflector
=
Grasscutter
.
reflector
;
Set
<
Class
<?>>
classes
=
reflector
.
getTypesAnnotatedWith
(
Command
.
class
);
classes
.
forEach
(
annotated
->
{
try
{
Command
cmdData
=
annotated
.
getAnnotation
(
Command
.
class
);
Object
object
=
annotated
.
newInstance
();
if
(
object
instanceof
CommandHandler
)
this
.
registerCommand
(
cmdData
.
label
(),
(
CommandHandler
)
object
);
else
Grasscutter
.
getLogger
().
error
(
"Class "
+
annotated
.
getName
()
+
" is not a CommandHandler!"
);
}
catch
(
Exception
exception
)
{
Grasscutter
.
getLogger
().
error
(
"Failed to register command handler for "
+
annotated
.
getSimpleName
(),
exception
);
}
});
}
}
src/main/java/emu/grasscutter/commands/PlayerCommands.java
View file @
eac3745f
package
emu.grasscutter.commands
;
package
emu.grasscutter.commands
;
import
java.lang.reflect.Modifier
;
import
emu.grasscutter.Grasscutter
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.avatar.GenshinAvatar
;
import
emu.grasscutter.game.avatar.GenshinAvatar
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.entity.EntityItem
;
import
emu.grasscutter.game.entity.EntityItem
;
import
emu.grasscutter.game.entity.EntityMonster
;
import
emu.grasscutter.game.entity.EntityMonster
;
import
emu.grasscutter.game.entity.GenshinEntity
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.inventory.Inventory
;
import
emu.grasscutter.game.inventory.ItemType
;
import
emu.grasscutter.game.inventory.ItemType
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.FightProperty
;
...
@@ -23,306 +19,302 @@ import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
...
@@ -23,306 +19,302 @@ import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import
emu.grasscutter.server.packet.send.PacketItemAddHintNotify
;
import
emu.grasscutter.server.packet.send.PacketItemAddHintNotify
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Position
;
public
class
PlayerCommands
{
import
java.util.LinkedList
;
private
static
HashMap
<
String
,
PlayerCommand
>
commandList
=
new
HashMap
<
String
,
PlayerCommand
>();
import
java.util.List
;
private
static
HashMap
<
String
,
PlayerCommand
>
commandAliasList
=
new
HashMap
<
String
,
PlayerCommand
>();
/**
* A container for player-related commands.
*/
public
final
class
PlayerCommands
{
@Command
(
label
=
"give"
,
aliases
=
{
"g"
,
"item"
,
"giveitem"
},
usage
=
"Usage: give [player] <itemId|itemName> [amount]"
)
public
static
class
GiveCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
int
target
,
item
,
amount
=
1
;
switch
(
args
.
size
())
{
default
:
CommandHandler
.
sendMessage
(
player
,
"Usage: give <player> <itemId|itemName> [amount]"
);
return
;
case
1
:
try
{
item
=
Integer
.
parseInt
(
args
.
get
(
0
));
target
=
player
.
getAccount
().
getPlayerId
();
}
catch
(
NumberFormatException
ignored
)
{
// TODO: Parse from item name using GM Handbook.
CommandHandler
.
sendMessage
(
player
,
"Invalid item id."
);
return
;
}
break
;
case
2
:
try
{
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
if
(
Grasscutter
.
getGameServer
().
getPlayerById
(
target
)
==
null
)
{
target
=
player
.
getId
();
amount
=
Integer
.
parseInt
(
args
.
get
(
1
));
item
=
Integer
.
parseInt
(
args
.
get
(
0
));
}
else
{
item
=
Integer
.
parseInt
(
args
.
get
(
1
));
}
}
catch
(
NumberFormatException
ignored
)
{
// TODO: Parse from item name using GM Handbook.
CommandHandler
.
sendMessage
(
player
,
"Invalid item or player ID."
);
return
;
}
break
;
case
3
:
try
{
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
if
(
Grasscutter
.
getGameServer
().
getPlayerById
(
target
)
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Invalid player ID."
);
return
;
}
item
=
Integer
.
parseInt
(
args
.
get
(
1
));
amount
=
Integer
.
parseInt
(
args
.
get
(
2
));
}
catch
(
NumberFormatException
ignored
)
{
// TODO: Parse from item name using GM Handbook.
CommandHandler
.
sendMessage
(
player
,
"Invalid item or player ID."
);
return
;
}
break
;
}
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Player not found."
);
return
;
}
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
item
);
if
(
itemData
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Invalid item id."
);
return
;
}
this
.
item
(
targetPlayer
,
itemData
,
amount
);
}
/**
* give [player] [itemId|itemName] [amount]
*/
@Override
public
void
execute
(
List
<
String
>
args
)
{
if
(
args
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
null
,
"Usage: give <player> <itemId|itemName> [amount]"
);
return
;
}
try
{
static
{
int
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
try
{
int
item
=
Integer
.
parseInt
(
args
.
get
(
1
));
// Look for classes
int
amount
=
1
;
if
(
args
.
size
()
>
2
)
amount
=
Integer
.
parseInt
(
args
.
get
(
2
));
for
(
Class
<?>
cls
:
PlayerCommands
.
class
.
getDeclaredClasses
())
{
// Get non abstract classes
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
if
(!
Modifier
.
isAbstract
(
cls
.
getModifiers
()))
{
if
(
targetPlayer
==
null
)
{
Command
commandAnnotation
=
cls
.
getAnnotation
(
Command
.
class
);
CommandHandler
.
sendMessage
(
null
,
"Player not found."
);
return
;
PlayerCommand
command
=
(
PlayerCommand
)
cls
.
newInstance
();
}
if
(
commandAnnotation
!=
null
)
{
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
item
);
command
.
setLevel
(
commandAnnotation
.
gmLevel
());
if
(
itemData
==
null
)
{
command
.
setHelpText
(
commandAnnotation
.
helpText
());
CommandHandler
.
sendMessage
(
null
,
"Invalid item id."
);
return
;
for
(
String
alias
:
commandAnnotation
.
aliases
())
{
}
if
(
alias
.
length
()
==
0
)
{
continue
;
this
.
item
(
targetPlayer
,
itemData
,
amount
);
}
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid item or player ID."
);
}
}
private
void
item
(
GenshinPlayer
player
,
ItemData
itemData
,
int
amount
)
{
GenshinItem
genshinItem
=
new
GenshinItem
(
itemData
);
if
(
itemData
.
isEquip
())
{
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
amount
;
i
++)
{
items
.
add
(
genshinItem
);
}
player
.
getInventory
().
addItems
(
items
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
}
else
{
genshinItem
.
setCount
(
amount
);
player
.
getInventory
().
addItem
(
genshinItem
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
genshinItem
,
ActionReason
.
SubfieldDrop
));
}
}
}
@Command
(
label
=
"drop"
,
aliases
=
{
"d"
,
"dropitem"
},
usage
=
"Usage: drop <itemId|itemName> [amount]"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
DropCommand
implements
CommandHandler
{
String
commandName
=
alias
;
@Override
commandAliasList
.
put
(
commandName
,
command
);
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
}
if
(
args
.
size
()
<
1
)
{
}
CommandHandler
.
sendMessage
(
player
,
"Usage: drop <itemId|itemName> [amount]"
);
return
;
}
String
commandName
=
cls
.
getSimpleName
().
toLowerCase
();
try
{
commandList
.
put
(
commandName
,
command
);
int
item
=
Integer
.
parseInt
(
args
.
get
(
0
));
}
int
amount
=
1
;
if
(
args
.
size
()
>
1
)
amount
=
Integer
.
parseInt
(
args
.
get
(
1
));
}
}
catch
(
Exception
e
)
{
}
}
public
static
void
handle
(
GenshinPlayer
player
,
String
msg
)
{
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
item
);
String
[]
split
=
msg
.
split
(
" "
);
if
(
itemData
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Invalid item id."
);
return
;
// End if invalid
}
if
(
split
.
length
==
0
)
{
return
;
}
String
first
=
split
[
0
].
toLowerCase
().
substring
(
1
);
if
(
itemData
.
isEquip
())
{
PlayerCommand
c
=
PlayerCommands
.
commandList
.
get
(
first
);
float
range
=
(
5
f
+
(.
1
f
*
amount
));
PlayerCommand
a
=
PlayerCommands
.
commandAliasList
.
get
(
first
);
for
(
int
i
=
0
;
i
<
amount
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
if
(
c
!=
null
||
a
!=
null
)
{
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
pos
,
1
);
PlayerCommand
cmd
=
c
!=
null
?
c
:
a
;
player
.
getWorld
().
addEntity
(
entity
);
// Level check
}
if
(
player
.
getGmLevel
()
<
cmd
.
getLevel
())
{
}
else
{
return
;
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
amount
);
}
player
.
getWorld
().
addEntity
(
entity
);
// Execute
}
int
len
=
Math
.
min
(
split
[
0
].
length
()
+
1
,
msg
.
length
());
}
catch
(
NumberFormatException
ignored
)
{
cmd
.
execute
(
player
,
msg
.
substring
(
len
));
CommandHandler
.
sendMessage
(
player
,
"Invalid item or player ID."
);
}
}
}
}
}
public
static
abstract
class
PlayerCommand
{
// GM level required to use this command
@Command
(
label
=
"spawn"
,
execution
=
Command
.
Execution
.
PLAYER
,
private
int
level
;
usage
=
"Usage: spawn <entityId|entityName> [level] [amount]"
)
private
String
helpText
;
public
static
class
SpawnCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
if
(
args
.
size
()
<
1
)
{
CommandHandler
.
sendMessage
(
null
,
"Usage: spawn <entityId|entityName> [amount]"
);
return
;
}
protected
int
getLevel
()
{
return
this
.
level
;
}
try
{
protected
void
setLevel
(
int
minLevel
)
{
this
.
level
=
minLevel
;
}
int
entity
=
Integer
.
parseInt
(
args
.
get
(
0
));
int
level
=
1
;
if
(
args
.
size
()
>
1
)
level
=
Integer
.
parseInt
(
args
.
get
(
1
));
int
amount
=
1
;
if
(
args
.
size
()
>
2
)
amount
=
Integer
.
parseInt
(
args
.
get
(
2
));
protected
String
getHelpText
()
{
return
this
.
helpText
;
}
MonsterData
entityData
=
GenshinData
.
getMonsterDataMap
().
get
(
entity
);
protected
void
setHelpText
(
String
helpText
)
{
this
.
helpText
=
helpText
;
}
if
(
entityData
==
null
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid entity id."
);
return
;
}
// Main
float
range
=
(
5
f
+
(.
1
f
*
amount
));
public
abstract
void
execute
(
GenshinPlayer
player
,
String
raw
);
for
(
int
i
=
0
;
i
<
amount
;
i
++)
{
}
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityMonster
monster
=
new
EntityMonster
(
player
.
getWorld
(),
entityData
,
pos
,
level
);
// ================ Commands ================
player
.
getWorld
().
addEntity
(
monster
);
}
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid item or player ID."
);
}
}
}
@Command
(
label
=
"killall"
,
usage
=
"Usage: killall [sceneId]"
)
public
static
class
KillAllCommand
implements
CommandHandler
{
@Command
(
aliases
=
{
"h"
},
helpText
=
"Shows this command"
)
@Override
public
static
class
Help
extends
PlayerCommand
{
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
World
world
=
player
.
getWorld
();
world
.
getEntities
().
values
().
stream
()
.
filter
(
entity
->
entity
instanceof
EntityMonster
)
.
forEach
(
entity
->
world
.
killEntity
(
entity
,
0
));
}
@Override
public
void
execute
(
List
<
String
>
args
)
{
if
(
args
.
size
()
<
1
)
{
CommandHandler
.
sendMessage
(
null
,
"Usage: killall [sceneId]"
);
return
;
}
try
{
int
sceneId
=
Integer
.
parseInt
(
args
.
get
(
0
));
CommandHandler
.
sendMessage
(
null
,
"Killing all monsters in scene "
+
sceneId
);
// TODO: Implement getting worlds by scene ID.
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid scene id."
);
}
}
}
@Command
(
label
=
"resetconst"
,
aliases
=
{
"resetconstellation"
},
usage
=
"Usage: resetconst [all]"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
ResetConstellationCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
if
(
args
.
size
()
>
0
&&
args
.
get
(
0
).
equalsIgnoreCase
(
"all"
))
{
player
.
getAvatars
().
forEach
(
this
::
resetConstellation
);
player
.
dropMessage
(
"Reset all avatars' constellations."
);
}
else
{
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
return
;
GenshinAvatar
avatar
=
entity
.
getAvatar
();
this
.
resetConstellation
(
avatar
);
@Override
player
.
dropMessage
(
"Constellations for "
+
avatar
.
getAvatarData
().
getName
()
+
" have been reset. Please relog to see changes."
);
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
}
String
helpMessage
=
"Grasscutter Commands: "
;
}
for
(
Map
.
Entry
<
String
,
PlayerCommand
>
cmd
:
commandList
.
entrySet
())
{
private
void
resetConstellation
(
GenshinAvatar
avatar
)
{
avatar
.
getTalentIdList
().
clear
();
avatar
.
setCoreProudSkillLevel
(
0
);
avatar
.
recalcStats
();
avatar
.
save
();
}
}
@Command
(
label
=
"godmode"
,
usage
=
"Usage: godmode"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
GodModeCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
player
.
setGodmode
(!
player
.
inGodmode
());
player
.
dropMessage
(
"Godmode is now "
+
(
player
.
inGodmode
()
?
"enabled"
:
"disabled"
)
+
"."
);
}
}
@Command
(
label
=
"sethealth"
,
aliases
=
{
"sethp"
},
usage
=
"Usage: sethealth <hp>"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
SetHealthCommand
implements
CommandHandler
{
helpMessage
+=
"\n"
+
cmd
.
getKey
()
+
" - "
+
cmd
.
getValue
().
helpText
;
@Override
}
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
if
(
args
.
size
()
<
1
)
{
CommandHandler
.
sendMessage
(
null
,
"Usage: sethealth <hp>"
);
return
;
}
try
{
int
health
=
Integer
.
parseInt
(
args
.
get
(
0
));
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
return
;
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
health
);
entity
.
getWorld
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
player
.
dropMessage
(
"Health set to "
+
health
+
"."
);
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid health value."
);
}
}
}
@Command
(
label
=
"clearartifacts"
,
aliases
=
{
"clearart"
},
usage
=
"Usage: clearartifacts"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
ClearArtifactsCommand
implements
CommandHandler
{
player
.
dropMessage
(
helpMessage
);
@Override
}
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
}
Inventory
playerInventory
=
player
.
getInventory
();
playerInventory
.
getItems
().
values
().
stream
()
@Command
(
aliases
=
{
"g"
,
"item"
,
"additem"
},
helpText
=
"/give [item id] [count] - Gives {count} amount of {item id}"
)
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
)
public
static
class
Give
extends
PlayerCommand
{
.
filter
(
item
->
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
)
@Override
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
String
[]
split
=
raw
.
split
(
" "
);
}
int
itemId
=
0
,
count
=
1
;
}
try
{
itemId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
itemId
=
0
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
GenshinItem
item
;
if
(
itemData
==
null
)
{
player
.
dropMessage
(
"Error: Item data not found"
);
return
;
}
if
(
itemData
.
isEquip
())
{
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
item
=
new
GenshinItem
(
itemData
);
items
.
add
(
item
);
}
player
.
getInventory
().
addItems
(
items
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
}
else
{
item
=
new
GenshinItem
(
itemData
,
count
);
player
.
getInventory
().
addItem
(
item
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
item
,
ActionReason
.
SubfieldDrop
));
}
}
}
@Command
(
aliases
=
{
"d"
},
helpText
=
"/drop [item id] [count] - Drops {count} amount of {item id}"
)
public
static
class
Drop
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
itemId
=
0
,
count
=
1
;
try
{
itemId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
itemId
=
0
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
if
(
itemData
==
null
)
{
player
.
dropMessage
(
"Error: Item data not found"
);
return
;
}
if
(
itemData
.
isEquip
())
{
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
pos
,
1
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
else
{
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
count
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
@Command
(
helpText
=
"/spawn [monster id] [count] - Creates {count} amount of {item id}"
)
public
static
class
Spawn
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
monsterId
=
0
,
count
=
1
,
level
=
1
;
try
{
monsterId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
monsterId
=
0
;
}
try
{
level
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
200
),
1
);
}
catch
(
Exception
e
)
{
level
=
1
;
}
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
2
]),
1000
),
1
);
}
catch
(
Exception
e
)
{
count
=
1
;
}
// Give
MonsterData
monsterData
=
GenshinData
.
getMonsterDataMap
().
get
(
monsterId
);
if
(
monsterData
==
null
)
{
player
.
dropMessage
(
"Error: Monster data not found"
);
return
;
}
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityMonster
entity
=
new
EntityMonster
(
player
.
getWorld
(),
monsterData
,
pos
,
level
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
@Command
(
helpText
=
"/killall"
)
public
static
class
KillAll
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
List
<
GenshinEntity
>
toRemove
=
new
LinkedList
<>();
for
(
GenshinEntity
entity
:
player
.
getWorld
().
getEntities
().
values
())
{
if
(
entity
instanceof
EntityMonster
)
{
toRemove
.
add
(
entity
);
}
}
toRemove
.
forEach
(
e
->
player
.
getWorld
().
killEntity
(
e
,
0
));
}
}
@Command
(
helpText
=
"/resetconst - Resets all constellations for the currently active character"
)
public
static
class
ResetConst
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
{
return
;
}
GenshinAvatar
avatar
=
entity
.
getAvatar
();
avatar
.
getTalentIdList
().
clear
();
avatar
.
setCoreProudSkillLevel
(
0
);
avatar
.
recalcStats
();
avatar
.
save
();
player
.
dropMessage
(
"Constellations for "
+
entity
.
getAvatar
().
getAvatarData
().
getName
()
+
" have been reset. Please relogin to see changes."
);
}
}
@Command
(
helpText
=
"/godmode - Prevents you from taking damage"
)
public
static
class
Godmode
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
player
.
setGodmode
(!
player
.
hasGodmode
());
player
.
dropMessage
(
"Godmode is now "
+
(
player
.
hasGodmode
()
?
"ON"
:
"OFF"
));
}
}
@Command
(
helpText
=
"/sethp [hp]"
)
public
static
class
Sethp
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
hp
=
0
;
try
{
hp
=
Math
.
max
(
Integer
.
parseInt
(
split
[
0
]),
1
);
}
catch
(
Exception
e
)
{
hp
=
1
;
}
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
{
return
;
}
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
hp
);
entity
.
getWorld
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
}
}
@Command
(
aliases
=
{
"clearart"
},
helpText
=
"/clearartifacts"
)
public
static
class
ClearArtifacts
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
List
<
GenshinItem
>
toRemove
=
new
LinkedList
<>();
for
(
GenshinItem
item
:
player
.
getInventory
().
getItems
().
values
())
{
if
(
item
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
&&
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
&&
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
{
toRemove
.
add
(
item
);
}
}
player
.
getInventory
().
removeItems
(
toRemove
);
}
}
}
}
src/main/java/emu/grasscutter/commands/ServerCommands.java
View file @
eac3745f
package
emu.grasscutter.commands
;
package
emu.grasscutter.commands
;
import
java.lang.reflect.Modifier
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.utils.Crypto
;
import
java.util.List
;
import
emu.grasscutter.utils.Utils
;
import
java.util.stream.Collectors
;
public
class
ServerCommands
{
/**
private
static
HashMap
<
String
,
ServerCommand
>
list
=
new
HashMap
<>();
* A container for server-related commands.
*/
static
{
public
final
class
ServerCommands
{
try
{
@Command
(
label
=
"reload"
,
usage
=
"Usage: reload"
)
// Look for classes
public
static
class
ReloadCommand
implements
CommandHandler
{
for
(
Class
<?>
cls
:
ServerCommands
.
class
.
getDeclaredClasses
())
{
// Get non abstract classes
@Override
if
(!
Modifier
.
isAbstract
(
cls
.
getModifiers
()))
{
public
void
execute
(
List
<
String
>
args
)
{
String
commandName
=
cls
.
getSimpleName
().
toLowerCase
();
Grasscutter
.
getLogger
().
info
(
"Reloading config."
);
list
.
put
(
commandName
,
(
ServerCommand
)
cls
.
newInstance
());
Grasscutter
.
loadConfig
();
}
Grasscutter
.
getDispatchServer
().
loadQueries
();
Grasscutter
.
getLogger
().
info
(
"Reload complete."
);
}
}
}
catch
(
Exception
e
)
{
@Override
}
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
}
this
.
execute
(
args
);
}
public
static
void
handle
(
String
msg
)
{
}
String
[]
split
=
msg
.
split
(
" "
);
@Command
(
label
=
"sendmessage"
,
aliases
=
{
"sendmsg"
,
"msg"
},
// End if invalid
usage
=
"Usage: sendmessage <player> <message>"
)
if
(
split
.
length
==
0
)
{
public
static
class
SendMessageCommand
implements
CommandHandler
{
return
;
}
@Override
public
void
execute
(
List
<
String
>
args
)
{
//
if
(
args
.
size
()
<
2
)
{
String
first
=
split
[
0
].
toLowerCase
();
CommandHandler
.
sendMessage
(
null
,
"Usage: sendmessage <player> <message>"
);
return
;
ServerCommand
c
=
ServerCommands
.
list
.
get
(
first
);
}
if
(
c
!=
null
)
{
try
{
// Execute
int
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
int
len
=
Math
.
min
(
first
.
length
()
+
1
,
msg
.
length
());
String
message
=
String
.
join
(
" "
,
args
.
subList
(
1
,
args
.
size
()));
c
.
execute
(
msg
.
substring
(
len
));
}
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
}
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
null
,
"Player not found."
);
return
;
public
static
abstract
class
ServerCommand
{
}
public
abstract
void
execute
(
String
raw
);
}
targetPlayer
.
dropMessage
(
message
);
CommandHandler
.
sendMessage
(
null
,
"Message sent."
);
// ================ Commands ================
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid player ID."
);
public
static
class
Reload
extends
ServerCommand
{
}
@Override
}
public
void
execute
(
String
raw
)
{
Grasscutter
.
getLogger
().
info
(
"Reloading config."
);
@Override
Grasscutter
.
loadConfig
();
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
Grasscutter
.
getDispatchServer
().
loadQueries
();
if
(
args
.
size
()
<
2
)
{
Grasscutter
.
getLogger
().
info
(
"Reload complete."
);
CommandHandler
.
sendMessage
(
player
,
"Usage: sendmessage <player> <message>"
);
return
;
}
}
}
try
{
public
static
class
sendMsg
extends
ServerCommand
{
int
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
@Override
String
message
=
String
.
join
(
" "
,
args
.
subList
(
1
,
args
.
size
()));
public
void
execute
(
String
raw
)
{
List
<
String
>
split
=
Arrays
.
asList
(
raw
.
split
(
" "
));
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
if
(
targetPlayer
==
null
)
{
if
(
split
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
player
,
"Player not found."
);
return
;
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
}
return
;
}
targetPlayer
.
sendMessage
(
player
,
message
);
CommandHandler
.
sendMessage
(
player
,
"Message sent."
);
String
playerID
=
split
.
get
(
0
);
}
catch
(
NumberFormatException
ignored
)
{
String
message
=
split
.
stream
().
skip
(
1
).
collect
(
Collectors
.
joining
(
" "
));
CommandHandler
.
sendMessage
(
player
,
"Invalid player ID."
);
}
}
emu
.
grasscutter
.
game
.
Account
account
=
DatabaseHelper
.
getAccountByPlayerId
(
Integer
.
parseInt
(
playerID
));
}
if
(
account
!=
null
)
{
GenshinPlayer
player
=
Grasscutter
.
getGameServer
().
getPlayerById
(
Integer
.
parseInt
(
playerID
));
@Command
(
label
=
"account"
,
if
(
player
!=
null
)
{
usage
=
"Usage: account <create|delete> <username> [uid]"
,
player
.
dropMessage
(
message
);
execution
=
Command
.
Execution
.
CONSOLE
)
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"Successfully sent message to %s: %s"
,
playerID
,
message
));
public
static
class
AccountCommand
implements
CommandHandler
{
}
else
{
Grasscutter
.
getLogger
().
error
(
"Player not online"
);
@Override
}
public
void
execute
(
List
<
String
>
args
)
{
}
else
{
if
(
args
.
size
()
<
2
)
{
Grasscutter
.
getLogger
().
error
(
String
.
format
(
"Player %s does not exist"
,
playerID
));
CommandHandler
.
sendMessage
(
null
,
"Usage: account <create|delete> <username> [uid]"
);
return
;
}
}
}
}
String
action
=
args
.
get
(
0
);
String
username
=
args
.
get
(
1
);
public
static
class
Account
extends
ServerCommand
{
@Override
switch
(
action
)
{
public
void
execute
(
String
raw
)
{
default
:
String
[]
split
=
raw
.
split
(
" "
);
CommandHandler
.
sendMessage
(
null
,
"Usage: account <create|delete> <username> [uid]"
);
return
;
if
(
split
.
length
<
2
)
{
case
"create"
:
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
int
uid
=
0
;
return
;
if
(
args
.
size
()
>
2
)
{
}
try
{
uid
=
Integer
.
parseInt
(
args
.
get
(
2
));
String
command
=
split
[
0
].
toLowerCase
();
}
catch
(
NumberFormatException
ignored
)
{
String
username
=
split
[
1
];
CommandHandler
.
sendMessage
(
null
,
"Invalid UID."
);
return
;
}
switch
(
command
)
{
}
case
"create"
:
if
(
split
.
length
<
2
)
{
Account
account
=
DatabaseHelper
.
createAccountWithId
(
username
,
uid
);
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
if
(
account
==
null
)
{
return
;
CommandHandler
.
sendMessage
(
null
,
"Account already exists."
);
return
;
}
}
else
{
CommandHandler
.
sendMessage
(
null
,
"Account created with UID "
+
account
.
getPlayerId
()
+
"."
);
int
reservedId
=
0
;
account
.
addPermission
(
"*"
);
// Grant the player superuser permissions.
try
{
}
reservedId
=
Integer
.
parseInt
(
split
[
2
]);
return
;
}
catch
(
Exception
e
)
{
case
"delete"
:
reservedId
=
0
;
if
(
DatabaseHelper
.
deleteAccount
(
username
))
{
}
CommandHandler
.
sendMessage
(
null
,
"Account deleted."
);
return
;
}
else
CommandHandler
.
sendMessage
(
null
,
"Account not found."
);
emu
.
grasscutter
.
game
.
Account
account
=
DatabaseHelper
.
createAccountWithId
(
username
,
reservedId
);
return
;
if
(
account
!=
null
)
{
}
Grasscutter
.
getLogger
().
info
(
"Account created"
+
(
reservedId
>
0
?
" with an id of "
+
reservedId
:
""
));
}
}
else
{
}
Grasscutter
.
getLogger
().
error
(
"Account already exists"
);
}
@Command
(
label
=
"permission"
,
break
;
usage
=
"Usage: permission <add|remove> <username> <permission>"
,
case
"delete"
:
execution
=
Command
.
Execution
.
CONSOLE
)
boolean
success
=
DatabaseHelper
.
deleteAccount
(
username
);
public
static
class
PermissionCommand
implements
CommandHandler
{
if
(
success
)
{
@Override
Grasscutter
.
getLogger
().
info
(
"Account deleted"
);
public
void
execute
(
List
<
String
>
args
)
{
}
if
(
args
.
size
()
<
3
)
{
break
;
CommandHandler
.
sendMessage
(
null
,
"Usage: permission <add|remove> <username> <permission>"
);
return
;
/*
}
case "setpw":
case "setpass":
String
action
=
args
.
get
(
0
);
case "setpassword":
String
username
=
args
.
get
(
1
);
if (split.length < 3) {
String
permission
=
args
.
get
(
2
);
Grasscutter.getLogger().error("Invalid amount of args");
return;
Account
account
=
Grasscutter
.
getGameServer
().
getAccountByName
(
username
);
}
if
(
account
==
null
)
{
CommandHandler
.
sendMessage
(
null
,
"Account not found."
);
return
;
account = DatabaseHelper.getAccountByName(username);
}
if (account == null) {
switch
(
action
)
{
Grasscutter.getLogger().error("No account found!");
default
:
return;
CommandHandler
.
sendMessage
(
null
,
"Usage: permission <add|remove> <username> <permission>"
);
}
break
;
case
"add"
:
token = split[2];
if
(
account
.
addPermission
(
permission
))
{
token = PasswordHelper.hashPassword(token);
CommandHandler
.
sendMessage
(
null
,
"Permission added."
);
}
else
CommandHandler
.
sendMessage
(
null
,
"They already have this permission!"
);
account.setPassword(token);
break
;
DatabaseHelper.saveAccount(account);
case
"remove"
:
if
(
account
.
removePermission
(
permission
))
{
Grasscutter.getLogger().info("Password set");
CommandHandler
.
sendMessage
(
null
,
"Permission removed."
);
break;
}
else
CommandHandler
.
sendMessage
(
null
,
"They don't have this permission!"
);
*/
break
;
}
}
}
}
account
.
save
();
}
}
@Command
(
label
=
"help"
,
usage
=
"Usage: help [command]"
)
public
static
class
HelpCommand
implements
CommandHandler
{
@Override
public
void
execute
(
List
<
String
>
args
)
{
List
<
CommandHandler
>
handlers
=
CommandMap
.
getInstance
().
getHandlers
();
List
<
Command
>
annotations
=
handlers
.
stream
()
.
map
(
handler
->
handler
.
getClass
().
getAnnotation
(
Command
.
class
))
.
collect
(
Collectors
.
toList
());
if
(
args
.
size
()
<
1
)
{
StringBuilder
builder
=
new
StringBuilder
(
"Available commands:\n"
);
annotations
.
forEach
(
annotation
->
builder
.
append
(
annotation
.
usage
()).
append
(
"\n"
));
CommandHandler
.
sendMessage
(
null
,
builder
.
toString
());
}
else
{
String
command
=
args
.
get
(
0
);
CommandHandler
handler
=
CommandMap
.
getInstance
().
getHandler
(
command
);
if
(
handler
==
null
)
{
CommandHandler
.
sendMessage
(
null
,
"Command not found."
);
return
;
}
Command
annotation
=
handler
.
getClass
().
getAnnotation
(
Command
.
class
);
CommandHandler
.
sendMessage
(
null
,
annotation
.
usage
());
}
}
@Override
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
List
<
CommandHandler
>
handlers
=
CommandMap
.
getInstance
().
getHandlers
();
List
<
Command
>
annotations
=
handlers
.
stream
()
.
map
(
handler
->
handler
.
getClass
().
getAnnotation
(
Command
.
class
))
.
collect
(
Collectors
.
toList
());
if
(
args
.
size
()
<
1
)
{
annotations
.
forEach
(
annotation
->
player
.
dropMessage
(
annotation
.
usage
()));
}
else
{
String
command
=
args
.
get
(
0
);
CommandHandler
handler
=
CommandMap
.
getInstance
().
getHandler
(
command
);
if
(
handler
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Command not found."
);
return
;
}
Command
annotation
=
handler
.
getClass
().
getAnnotation
(
Command
.
class
);
CommandHandler
.
sendMessage
(
player
,
annotation
.
usage
());
}
}
}
}
}
src/main/java/emu/grasscutter/data/ResourceLoader.java
View file @
eac3745f
...
@@ -2,20 +2,12 @@ package emu.grasscutter.data;
...
@@ -2,20 +2,12 @@ package emu.grasscutter.data;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.FileReader
;
import
java.nio.file.Files
;
import
java.util.*
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TreeMap
;
import
java.util.Map.Entry
;
import
java.util.Map.Entry
;
import
java.util.regex.Matcher
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
import
java.util.stream.Stream
;
import
emu.grasscutter.utils.Utils
;
import
org.reflections.Reflections
;
import
org.reflections.Reflections
;
import
com.google.gson.reflect.TypeToken
;
import
com.google.gson.reflect.TypeToken
;
...
@@ -39,19 +31,12 @@ public class ResourceLoader {
...
@@ -39,19 +31,12 @@ public class ResourceLoader {
}
}
});
});
classList
.
sort
((
a
,
b
)
->
{
classList
.
sort
((
a
,
b
)
->
b
.
getAnnotation
(
ResourceType
.
class
).
loadPriority
().
value
()
-
a
.
getAnnotation
(
ResourceType
.
class
).
loadPriority
().
value
());
return
b
.
getAnnotation
(
ResourceType
.
class
).
loadPriority
().
value
()
-
a
.
getAnnotation
(
ResourceType
.
class
).
loadPriority
().
value
();
});
return
classList
;
return
classList
;
}
}
public
static
void
loadAll
()
{
public
static
void
loadAll
()
{
// Create resource folder if it doesnt exist
File
resFolder
=
new
File
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
);
if
(!
resFolder
.
exists
())
{
resFolder
.
mkdir
();
}
// Load ability lists
// Load ability lists
loadAbilityEmbryos
();
loadAbilityEmbryos
();
loadOpenConfig
();
loadOpenConfig
();
...
@@ -110,7 +95,7 @@ public class ResourceLoader {
...
@@ -110,7 +95,7 @@ public class ResourceLoader {
try
{
try
{
loadFromResource
(
resourceDefinition
,
type
,
map
);
loadFromResource
(
resourceDefinition
,
type
,
map
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Error loading resource file: "
+
type
.
name
(),
e
);
Grasscutter
.
getLogger
().
error
(
"Error loading resource file: "
+
Arrays
.
toString
(
type
.
name
()
)
,
e
);
}
}
}
}
}
}
...
@@ -153,10 +138,16 @@ public class ResourceLoader {
...
@@ -153,10 +138,16 @@ public class ResourceLoader {
Pattern
pattern
=
Pattern
.
compile
(
"(?<=ConfigAvatar_)(.*?)(?=.json)"
);
Pattern
pattern
=
Pattern
.
compile
(
"(?<=ConfigAvatar_)(.*?)(?=.json)"
);
embryoList
=
new
LinkedList
<>();
embryoList
=
new
LinkedList
<>();
File
folder
=
new
File
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
"BinOutput\\Avatar\\"
);
File
folder
=
new
File
(
Utils
.
toFilePath
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
"BinOutput/Avatar/"
));
for
(
File
file
:
folder
.
listFiles
())
{
File
[]
files
=
folder
.
listFiles
();
AvatarConfig
config
=
null
;
if
(
files
==
null
)
{
String
avatarName
=
null
;
Grasscutter
.
getLogger
().
error
(
"Error loading ability embryos: no files found in "
+
folder
.
getAbsolutePath
());
return
;
}
for
(
File
file
:
files
)
{
AvatarConfig
config
;
String
avatarName
;
Matcher
matcher
=
pattern
.
matcher
(
file
.
getName
());
Matcher
matcher
=
pattern
.
matcher
(
file
.
getName
());
if
(
matcher
.
find
())
{
if
(
matcher
.
find
())
{
...
@@ -209,14 +200,18 @@ public class ResourceLoader {
...
@@ -209,14 +200,18 @@ public class ResourceLoader {
String
[]
folderNames
=
{
"BinOutput\\Talent\\EquipTalents\\"
,
"BinOutput\\Talent\\AvatarTalents\\"
};
String
[]
folderNames
=
{
"BinOutput\\Talent\\EquipTalents\\"
,
"BinOutput\\Talent\\AvatarTalents\\"
};
for
(
String
name
:
folderNames
)
{
for
(
String
name
:
folderNames
)
{
File
folder
=
new
File
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
name
);
File
folder
=
new
File
(
Utils
.
toFilePath
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
name
));
File
[]
files
=
folder
.
listFiles
();
if
(
files
==
null
)
{
Grasscutter
.
getLogger
().
error
(
"Error loading open config: no files found in "
+
folder
.
getAbsolutePath
());
return
;
}
for
(
File
file
:
f
older
.
listF
iles
()
)
{
for
(
File
file
:
files
)
{
if
(!
file
.
getName
().
endsWith
(
".json"
))
{
if
(!
file
.
getName
().
endsWith
(
".json"
))
{
continue
;
continue
;
}
}
Map
<
String
,
OpenConfigData
[]>
config
=
null
;
Map
<
String
,
OpenConfigData
[]>
config
;
try
(
FileReader
fileReader
=
new
FileReader
(
file
))
{
try
(
FileReader
fileReader
=
new
FileReader
(
file
))
{
config
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
type
);
config
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
type
);
...
...
src/main/java/emu/grasscutter/database/DatabaseHelper.java
View file @
eac3745f
...
@@ -36,6 +36,7 @@ public class DatabaseHelper {
...
@@ -36,6 +36,7 @@ public class DatabaseHelper {
if
(
reservedId
==
GenshinConstants
.
SERVER_CONSOLE_UID
)
{
if
(
reservedId
==
GenshinConstants
.
SERVER_CONSOLE_UID
)
{
return
null
;
return
null
;
}
}
exists
=
DatabaseHelper
.
getAccountByPlayerId
(
reservedId
);
exists
=
DatabaseHelper
.
getAccountByPlayerId
(
reservedId
);
if
(
exists
!=
null
)
{
if
(
exists
!=
null
)
{
return
null
;
return
null
;
...
...
src/main/java/emu/grasscutter/game/Account.java
View file @
eac3745f
...
@@ -4,11 +4,17 @@ import dev.morphia.annotations.Collation;
...
@@ -4,11 +4,17 @@ import dev.morphia.annotations.Collation;
import
dev.morphia.annotations.Entity
;
import
dev.morphia.annotations.Entity
;
import
dev.morphia.annotations.Id
;
import
dev.morphia.annotations.Id
;
import
dev.morphia.annotations.Indexed
;
import
dev.morphia.annotations.Indexed
;
import
dev.morphia.annotations.PreLoad
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.Crypto
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
import
dev.morphia.annotations.IndexOptions
;
import
dev.morphia.annotations.IndexOptions
;
import
java.util.ArrayList
;
import
java.util.List
;
import
com.mongodb.DBObject
;
@Entity
(
value
=
"accounts"
,
noClassnameStored
=
true
)
@Entity
(
value
=
"accounts"
,
noClassnameStored
=
true
)
public
class
Account
{
public
class
Account
{
@Id
private
String
id
;
@Id
private
String
id
;
...
@@ -23,9 +29,12 @@ public class Account {
...
@@ -23,9 +29,12 @@ public class Account {
private
String
token
;
private
String
token
;
private
String
sessionKey
;
// Session token for dispatch server
private
String
sessionKey
;
// Session token for dispatch server
private
List
<
String
>
permissions
;
@Deprecated
@Deprecated
public
Account
()
{}
public
Account
()
{
this
.
permissions
=
new
ArrayList
<>();
}
public
String
getId
()
{
public
String
getId
()
{
return
id
;
return
id
;
...
@@ -84,6 +93,22 @@ public class Account {
...
@@ -84,6 +93,22 @@ public class Account {
this
.
save
();
this
.
save
();
return
this
.
sessionKey
;
return
this
.
sessionKey
;
}
}
/**
* The collection of a player's permissions.
*/
public
List
<
String
>
getPermissions
()
{
return
this
.
permissions
;
}
public
boolean
addPermission
(
String
permission
)
{
if
(
this
.
permissions
.
contains
(
permission
))
return
false
;
this
.
permissions
.
add
(
permission
);
return
true
;
}
public
boolean
removePermission
(
String
permission
)
{
return
this
.
permissions
.
remove
(
permission
);
}
// TODO make unique
// TODO make unique
public
String
generateLoginToken
()
{
public
String
generateLoginToken
()
{
...
@@ -92,6 +117,14 @@ public class Account {
...
@@ -92,6 +117,14 @@ public class Account {
return
this
.
token
;
return
this
.
token
;
}
}
@PreLoad
public
void
onLoad
(
DBObject
dbObj
)
{
// Grant the superuser permissions to accounts created before the permissions update
if
(!
dbObj
.
containsField
(
"permissions"
))
{
this
.
addPermission
(
"*"
);
}
}
public
void
save
()
{
public
void
save
()
{
DatabaseHelper
.
saveAccount
(
this
);
DatabaseHelper
.
saveAccount
(
this
);
}
}
...
...
src/main/java/emu/grasscutter/game/GenshinPlayer.java
View file @
eac3745f
package
emu.grasscutter.game
;
package
emu.grasscutter.game
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Set
;
import
dev.morphia.annotations.*
;
import
dev.morphia.annotations.*
;
import
emu.grasscutter.GenshinConstants
;
import
emu.grasscutter.GenshinConstants
;
...
@@ -485,7 +480,7 @@ public class GenshinPlayer {
...
@@ -485,7 +480,7 @@ public class GenshinPlayer {
this
.
regionId
=
regionId
;
this
.
regionId
=
regionId
;
}
}
public
boolean
has
Godmode
()
{
public
boolean
in
Godmode
()
{
return
godmode
;
return
godmode
;
}
}
...
@@ -558,6 +553,15 @@ public class GenshinPlayer {
...
@@ -558,6 +553,15 @@ public class GenshinPlayer {
public
void
dropMessage
(
Object
message
)
{
public
void
dropMessage
(
Object
message
)
{
this
.
sendPacket
(
new
PacketPrivateChatNotify
(
GenshinConstants
.
SERVER_CONSOLE_UID
,
getId
(),
message
.
toString
()));
this
.
sendPacket
(
new
PacketPrivateChatNotify
(
GenshinConstants
.
SERVER_CONSOLE_UID
,
getId
(),
message
.
toString
()));
}
}
/**
* Sends a message to another player.
* @param sender The sender of the message.
* @param message The message to send.
*/
public
void
sendMessage
(
GenshinPlayer
sender
,
Object
message
)
{
this
.
sendPacket
(
new
PacketPrivateChatNotify
(
sender
.
getId
(),
this
.
getId
(),
message
.
toString
()));
}
public
void
interactWith
(
int
gadgetEntityId
)
{
public
void
interactWith
(
int
gadgetEntityId
)
{
GenshinEntity
entity
=
getWorld
().
getEntityById
(
gadgetEntityId
);
GenshinEntity
entity
=
getWorld
().
getEntityById
(
gadgetEntityId
);
...
...
src/main/java/emu/grasscutter/game/World.java
View file @
eac3745f
...
@@ -344,7 +344,7 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -344,7 +344,7 @@ public class World implements Iterable<GenshinPlayer> {
// Godmode check
// Godmode check
if
(
target
instanceof
EntityAvatar
)
{
if
(
target
instanceof
EntityAvatar
)
{
if
(((
EntityAvatar
)
target
).
getPlayer
().
has
Godmode
())
{
if
(((
EntityAvatar
)
target
).
getPlayer
().
in
Godmode
())
{
return
;
return
;
}
}
}
}
...
...
src/main/java/emu/grasscutter/game/managers/ChatManager.java
View file @
eac3745f
package
emu.grasscutter.game.managers
;
package
emu.grasscutter.game.managers
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.commands.CommandMap
;
import
emu.grasscutter.commands.PlayerCommands
;
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
;
import
emu.grasscutter.server.packet.send.PacketPlayerChatNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerChatNotify
;
import
emu.grasscutter.server.packet.send.PacketPrivateChatNotify
;
import
emu.grasscutter.server.packet.send.PacketPrivateChatNotify
;
import
java.util.Arrays
;
import
java.util.List
;
public
class
ChatManager
{
public
class
ChatManager
{
static
final
List
<
Character
>
PREFIXES
=
Arrays
.
asList
(
'/'
,
'!'
);
private
final
GameServer
server
;
private
final
GameServer
server
;
public
ChatManager
(
GameServer
server
)
{
public
ChatManager
(
GameServer
server
)
{
...
@@ -19,15 +23,15 @@ public class ChatManager {
...
@@ -19,15 +23,15 @@ public class ChatManager {
return
server
;
return
server
;
}
}
public
void
sendPriv
Ch
at
(
GenshinPlayer
player
,
int
targetUid
,
String
message
)
{
public
void
sendPrivat
eMessage
(
GenshinPlayer
player
,
int
targetUid
,
String
message
)
{
// Sanity checks
// Sanity checks
if
(
message
==
null
||
message
.
length
()
==
0
)
{
if
(
message
==
null
||
message
.
length
()
==
0
)
{
return
;
return
;
}
}
// Check if command
// Check if command
if
(
message
.
charAt
(
0
)
==
'!'
||
message
.
charAt
(
0
)
==
'/'
)
{
if
(
PREFIXES
.
contains
(
message
.
charAt
(
0
)
)
)
{
Player
Command
s
.
handl
e
(
player
,
message
);
Command
Map
.
getInstance
().
invok
e
(
player
,
message
);
return
;
return
;
}
}
...
@@ -45,7 +49,7 @@ public class ChatManager {
...
@@ -45,7 +49,7 @@ public class ChatManager {
target
.
sendPacket
(
packet
);
target
.
sendPacket
(
packet
);
}
}
public
void
sendPriv
Ch
at
(
GenshinPlayer
player
,
int
targetUid
,
int
emote
)
{
public
void
sendPrivat
eMessage
(
GenshinPlayer
player
,
int
targetUid
,
int
emote
)
{
// Get target
// Get target
GenshinPlayer
target
=
getServer
().
getPlayerById
(
targetUid
);
GenshinPlayer
target
=
getServer
().
getPlayerById
(
targetUid
);
...
@@ -60,15 +64,15 @@ public class ChatManager {
...
@@ -60,15 +64,15 @@ public class ChatManager {
target
.
sendPacket
(
packet
);
target
.
sendPacket
(
packet
);
}
}
public
void
sendTeam
Chat
(
GenshinPlayer
player
,
int
channel
,
String
message
)
{
public
void
sendTeam
Message
(
GenshinPlayer
player
,
int
channel
,
String
message
)
{
// Sanity checks
// Sanity checks
if
(
message
==
null
||
message
.
length
()
==
0
)
{
if
(
message
==
null
||
message
.
length
()
==
0
)
{
return
;
return
;
}
}
// Check if command
// Check if command
if
(
message
.
charAt
(
0
)
==
'!'
)
{
if
(
PREFIXES
.
contains
(
message
.
charAt
(
0
)
)
)
{
Player
Command
s
.
handl
e
(
player
,
message
);
Command
Map
.
getInstance
().
invok
e
(
player
,
message
);
return
;
return
;
}
}
...
@@ -76,7 +80,7 @@ public class ChatManager {
...
@@ -76,7 +80,7 @@ public class ChatManager {
player
.
getWorld
().
broadcastPacket
(
new
PacketPlayerChatNotify
(
player
,
channel
,
message
));
player
.
getWorld
().
broadcastPacket
(
new
PacketPlayerChatNotify
(
player
,
channel
,
message
));
}
}
public
void
sendTeam
Chat
(
GenshinPlayer
player
,
int
channel
,
int
icon
)
{
public
void
sendTeam
Message
(
GenshinPlayer
player
,
int
channel
,
int
icon
)
{
// Create and send chat packet
// Create and send chat packet
player
.
getWorld
().
broadcastPacket
(
new
PacketPlayerChatNotify
(
player
,
channel
,
icon
));
player
.
getWorld
().
broadcastPacket
(
new
PacketPlayerChatNotify
(
player
,
channel
,
icon
));
}
}
...
...
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
eac3745f
...
@@ -139,22 +139,28 @@ public final class DispatchServer {
...
@@ -139,22 +139,28 @@ public final class DispatchServer {
}
}
public
void
start
()
throws
Exception
{
public
void
start
()
throws
Exception
{
HttpsServer
server
=
HttpsServer
.
create
(
getAddress
(),
0
);
HttpServer
server
;
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
if
(
Grasscutter
.
getConfig
().
UseSSL
)
{
HttpsServer
httpsServer
;
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
DispatchServerKeystorePath
))
{
httpsServer
=
HttpsServer
.
create
(
getAddress
(),
0
);
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
DispatchServerKeystorePassword
.
toCharArray
();
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
DispatchServerKeystorePath
))
{
ks
.
load
(
fis
,
keystorePassword
);
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
DispatchServerKeystorePassword
.
toCharArray
();
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"SunX509"
);
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
kmf
.
init
(
ks
,
keystorePassword
);
ks
.
load
(
fis
,
keystorePassword
);
KeyManagerFactory
kmf
=
KeyManagerFactory
.
getInstance
(
"SunX509"
);
sslContext
.
init
(
kmf
.
getKeyManagers
(),
null
,
null
);
kmf
.
init
(
ks
,
keystorePassword
);
server
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
sslContext
.
init
(
kmf
.
getKeyManagers
(),
null
,
null
);
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"No SSL cert found!"
);
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
return
;
server
=
httpsServer
;
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"No SSL cert found!"
);
return
;
}
}
else
{
server
=
HttpServer
.
create
(
getAddress
(),
0
);
}
}
server
.
createContext
(
"/"
,
t
->
{
server
.
createContext
(
"/"
,
t
->
{
...
@@ -396,7 +402,7 @@ public final class DispatchServer {
...
@@ -396,7 +402,7 @@ public final class DispatchServer {
overseaLogServer
.
start
();
overseaLogServer
.
start
();
Grasscutter
.
getLogger
().
info
(
"Log server (overseauspider) started on port "
+
8888
);
Grasscutter
.
getLogger
().
info
(
"Log server (overseauspider) started on port "
+
8888
);
HttpServer
uploadLogServer
=
HttpServer
.
create
(
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
DispatchServerIp
,
80
),
0
);
HttpServer
uploadLogServer
=
HttpServer
.
create
(
new
InetSocketAddress
(
Grasscutter
.
getConfig
().
DispatchServerIp
,
Grasscutter
.
getConfig
().
UploadLogPort
),
0
);
uploadLogServer
.
createContext
(
// log-upload-os.mihoyo.com
uploadLogServer
.
createContext
(
// log-upload-os.mihoyo.com
"/crash/dataUpload"
,
"/crash/dataUpload"
,
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
new
DispatchHttpJsonHandler
(
"{\"code\":0}"
)
...
@@ -413,7 +419,7 @@ public final class DispatchServer {
...
@@ -413,7 +419,7 @@ public final class DispatchServer {
os
.
close
();
os
.
close
();
});
});
uploadLogServer
.
start
();
uploadLogServer
.
start
();
Grasscutter
.
getLogger
().
info
(
"Log server (log-upload-os) started on port "
+
80
);
Grasscutter
.
getLogger
().
info
(
"Log server (log-upload-os) started on port "
+
Grasscutter
.
getConfig
().
UploadLogPort
);
}
}
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
private
Map
<
String
,
String
>
parseQueryString
(
String
qs
)
{
...
...
src/main/java/emu/grasscutter/server/game/GameServer.java
View file @
eac3745f
package
emu.grasscutter.server.game
;
package
emu.grasscutter.server.game
;
import
java.net.InetSocketAddress
;
import
java.net.InetSocketAddress
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Timer
;
import
java.util.TimerTask
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
import
emu.grasscutter.GenshinConstants
;
import
emu.grasscutter.GenshinConstants
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.commands.CommandMap
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.dungeons.DungeonManager
;
import
emu.grasscutter.game.dungeons.DungeonManager
;
import
emu.grasscutter.game.gacha.GachaManager
;
import
emu.grasscutter.game.gacha.GachaManager
;
...
@@ -23,11 +20,10 @@ import emu.grasscutter.net.packet.PacketHandler;
...
@@ -23,11 +20,10 @@ 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
;
public
class
GameServer
extends
MihoyoKcpServer
{
public
final
class
GameServer
extends
MihoyoKcpServer
{
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
private
final
GameServerPacketHandler
packetHandler
;
private
final
GameServerPacketHandler
packetHandler
;
private
final
Timer
gameLoop
;
private
final
Map
<
Integer
,
GenshinPlayer
>
players
;
private
final
Map
<
Integer
,
GenshinPlayer
>
players
;
private
final
ChatManager
chatManager
;
private
final
ChatManager
chatManager
;
...
@@ -36,9 +32,11 @@ public class GameServer extends MihoyoKcpServer {
...
@@ -36,9 +32,11 @@ public 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
CommandMap
commandMap
;
public
GameServer
(
InetSocketAddress
address
)
{
public
GameServer
(
InetSocketAddress
address
)
{
super
(
address
);
super
(
address
);
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
);
...
@@ -50,22 +48,22 @@ public class GameServer extends MihoyoKcpServer {
...
@@ -50,22 +48,22 @@ public class GameServer extends MihoyoKcpServer {
this
.
shopManager
=
new
ShopManager
(
this
);
this
.
shopManager
=
new
ShopManager
(
this
);
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
);
//
Ticker
//
Schedule game loop.
this
.
gameLoop
=
new
Timer
();
Timer
gameLoop
=
new
Timer
();
this
.
gameLoop
.
scheduleAtFixedRate
(
new
TimerTask
()
{
gameLoop
.
scheduleAtFixedRate
(
new
TimerTask
()
{
@Override
@Override
public
void
run
()
{
public
void
run
()
{
try
{
try
{
onTick
();
onTick
();
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
// TODO Auto-generated catch block
Grasscutter
.
getLogger
().
error
(
"An error occurred during game update."
,
e
);
e
.
printStackTrace
();
}
}
}
}
},
new
Date
(),
1000L
);
},
new
Date
(),
1000L
);
//
S
hutdown
hook
//
Hook into s
hutdown
event.
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(
this
::
onServerShutdown
));
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(
this
::
onServerShutdown
));
}
}
...
@@ -101,6 +99,10 @@ public class GameServer extends MihoyoKcpServer {
...
@@ -101,6 +99,10 @@ public class GameServer extends MihoyoKcpServer {
return
dungeonManager
;
return
dungeonManager
;
}
}
public
CommandMap
getCommandMap
()
{
return
this
.
commandMap
;
}
public
void
registerPlayer
(
GenshinPlayer
player
)
{
public
void
registerPlayer
(
GenshinPlayer
player
)
{
getPlayers
().
put
(
player
.
getId
(),
player
);
getPlayers
().
put
(
player
.
getId
(),
player
);
}
}
...
@@ -137,6 +139,14 @@ public class GameServer extends MihoyoKcpServer {
...
@@ -137,6 +139,14 @@ public class GameServer extends MihoyoKcpServer {
return
player
.
getSocialDetail
();
return
player
.
getSocialDetail
();
}
}
public
Account
getAccountByName
(
String
username
)
{
Optional
<
GenshinPlayer
>
playerOpt
=
getPlayers
().
values
().
stream
().
filter
(
player
->
player
.
getAccount
().
getUsername
().
equals
(
username
)).
findFirst
();
if
(
playerOpt
.
get
()
!=
null
)
{
return
playerOpt
.
get
().
getAccount
();
}
return
DatabaseHelper
.
getAccountByName
(
username
);
}
public
void
onTick
()
throws
Exception
{
public
void
onTick
()
throws
Exception
{
for
(
GenshinPlayer
player
:
this
.
getPlayers
().
values
())
{
for
(
GenshinPlayer
player
:
this
.
getPlayers
().
values
())
{
player
.
onTick
();
player
.
onTick
();
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerPlayerChatReq.java
View file @
eac3745f
...
@@ -17,9 +17,9 @@ public class HandlerPlayerChatReq extends PacketHandler {
...
@@ -17,9 +17,9 @@ public class HandlerPlayerChatReq extends PacketHandler {
ChatInfo
.
ContentCase
content
=
req
.
getChatInfo
().
getContentCase
();
ChatInfo
.
ContentCase
content
=
req
.
getChatInfo
().
getContentCase
();
if
(
content
==
ChatInfo
.
ContentCase
.
TEXT
)
{
if
(
content
==
ChatInfo
.
ContentCase
.
TEXT
)
{
session
.
getServer
().
getChatManager
().
sendTeam
Chat
(
session
.
getPlayer
(),
req
.
getChannelId
(),
req
.
getChatInfo
().
getText
());
session
.
getServer
().
getChatManager
().
sendTeam
Message
(
session
.
getPlayer
(),
req
.
getChannelId
(),
req
.
getChatInfo
().
getText
());
}
else
if
(
content
==
ChatInfo
.
ContentCase
.
ICON
)
{
}
else
if
(
content
==
ChatInfo
.
ContentCase
.
ICON
)
{
session
.
getServer
().
getChatManager
().
sendTeam
Chat
(
session
.
getPlayer
(),
req
.
getChannelId
(),
req
.
getChatInfo
().
getIcon
());
session
.
getServer
().
getChatManager
().
sendTeam
Message
(
session
.
getPlayer
(),
req
.
getChannelId
(),
req
.
getChatInfo
().
getIcon
());
}
}
session
.
send
(
new
PacketPlayerChatRsp
());
session
.
send
(
new
PacketPlayerChatRsp
());
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerPrivateChatReq.java
View file @
eac3745f
...
@@ -15,9 +15,9 @@ public class HandlerPrivateChatReq extends PacketHandler {
...
@@ -15,9 +15,9 @@ public class HandlerPrivateChatReq extends PacketHandler {
PrivateChatReq
.
ContentCase
content
=
req
.
getContentCase
();
PrivateChatReq
.
ContentCase
content
=
req
.
getContentCase
();
if
(
content
==
PrivateChatReq
.
ContentCase
.
TEXT
)
{
if
(
content
==
PrivateChatReq
.
ContentCase
.
TEXT
)
{
session
.
getServer
().
getChatManager
().
sendPriv
Ch
at
(
session
.
getPlayer
(),
req
.
getTargetUid
(),
req
.
getText
());
session
.
getServer
().
getChatManager
().
sendPrivat
eMessage
(
session
.
getPlayer
(),
req
.
getTargetUid
(),
req
.
getText
());
}
else
if
(
content
==
PrivateChatReq
.
ContentCase
.
ICON
)
{
}
else
if
(
content
==
PrivateChatReq
.
ContentCase
.
ICON
)
{
session
.
getServer
().
getChatManager
().
sendPriv
Ch
at
(
session
.
getPlayer
(),
req
.
getTargetUid
(),
req
.
getIcon
());
session
.
getServer
().
getChatManager
().
sendPrivat
eMessage
(
session
.
getPlayer
(),
req
.
getTargetUid
(),
req
.
getIcon
());
}
}
//session.send(new GenshinPacket(PacketOpcodes.PrivateChatRsp)); // Unused by server
//session.send(new GenshinPacket(PacketOpcodes.PrivateChatRsp)); // Unused by server
...
...
src/main/java/emu/grasscutter/utils/Utils.java
View file @
eac3745f
...
@@ -79,6 +79,15 @@ public final class Utils {
...
@@ -79,6 +79,15 @@ public final class Utils {
return
v7
;
return
v7
;
}
}
/**
* Creates a string with the path to a file.
* @param path The path to the file.
* @return A path using the operating system's file separator.
*/
public
static
String
toFilePath
(
String
path
)
{
return
path
.
replace
(
"/"
,
File
.
separator
);
}
/**
/**
* Checks if a file exists on the file system.
* Checks if a file exists on the file system.
* @param path The path to the file.
* @param path The path to the file.
...
@@ -118,6 +127,16 @@ public final class Utils {
...
@@ -118,6 +127,16 @@ public final class Utils {
}
}
}
}
/**
* Get object with null fallback.
* @param nonNull The object to return if not null.
* @param fallback The object to return if null.
* @return One of the two provided objects.
*/
public
static
<
T
>
T
requireNonNullElseGet
(
T
nonNull
,
T
fallback
)
{
return
nonNull
!=
null
?
nonNull
:
fallback
;
}
/**
/**
* Checks for required files and folders before startup.
* Checks for required files and folders before startup.
*/
*/
...
...
Prev
1
2
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