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
Show 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
""
;
int
gmLevel
()
default
1
;
String
usage
()
default
""
;
String
helpText
()
default
""
;
String
[]
aliases
()
default
{
""
};
Execution
execution
()
default
Execution
.
ALL
;
String
permission
()
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
>();
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
());
command
.
setHelpText
(
commandAnnotation
.
helpText
());
for
(
String
alias
:
commandAnnotation
.
aliases
())
{
if
(
alias
.
length
()
==
0
)
{
continue
;
}
String
commandName
=
alias
;
commandAliasList
.
put
(
commandName
,
command
);
}
}
String
commandName
=
cls
.
getSimpleName
().
toLowerCase
();
/**
commandList
.
put
(
commandName
,
command
);
* 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
}
catch
(
Exception
e
)
{
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
)
{
public
static
void
handle
(
GenshinPlayer
player
,
String
msg
)
{
// TODO: Parse from item name using GM Handbook.
String
[]
split
=
msg
.
split
(
" "
);
CommandHandler
.
sendMessage
(
player
,
"Invalid item or player ID."
);
// End if invalid
if
(
split
.
length
==
0
)
{
return
;
return
;
}
}
break
;
case
3
:
try
{
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
if
(
Grasscutter
.
getGameServer
().
getPlayerById
(
target
)
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Invalid player ID."
);
return
;
}
String
first
=
split
[
0
].
toLowerCase
().
substring
(
1
);
item
=
Integer
.
parseInt
(
args
.
get
(
1
));
PlayerCommand
c
=
PlayerCommands
.
commandList
.
get
(
first
);
amount
=
Integer
.
parseInt
(
args
.
get
(
2
));
PlayerCommand
a
=
PlayerCommands
.
commandAliasList
.
get
(
first
);
}
catch
(
NumberFormatException
ignored
)
{
// TODO: Parse from item name using GM Handbook.
if
(
c
!=
null
||
a
!=
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Invalid item or player ID."
);
PlayerCommand
cmd
=
c
!=
null
?
c
:
a
;
// Level check
if
(
player
.
getGmLevel
()
<
cmd
.
getLevel
())
{
return
;
return
;
}
}
// Execute
break
;
int
len
=
Math
.
min
(
split
[
0
].
length
()
+
1
,
msg
.
length
());
cmd
.
execute
(
player
,
msg
.
substring
(
len
));
}
}
}
public
static
abstract
class
PlayerCommand
{
// GM level required to use this command
private
int
level
;
private
String
helpText
;
protected
int
getLevel
()
{
return
this
.
level
;
}
protected
void
setLevel
(
int
minLevel
)
{
this
.
level
=
minLevel
;
}
protected
String
getHelpText
()
{
return
this
.
helpText
;
}
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
protected
void
setHelpText
(
String
helpText
)
{
this
.
helpText
=
helpText
;
}
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
player
,
"Player not found."
);
return
;
// Main
public
abstract
void
execute
(
GenshinPlayer
player
,
String
raw
);
}
}
// ================ Commands ================
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
item
);
if
(
itemData
==
null
)
{
@Command
(
aliases
=
{
"h"
},
helpText
=
"Shows this command"
)
CommandHandler
.
sendMessage
(
player
,
"Invalid item id."
);
return
;
public
static
class
Help
extends
PlayerCommand
{
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
helpMessage
=
"Grasscutter Commands: "
;
for
(
Map
.
Entry
<
String
,
PlayerCommand
>
cmd
:
commandList
.
entrySet
())
{
helpMessage
+=
"\n"
+
cmd
.
getKey
()
+
" - "
+
cmd
.
getValue
().
helpText
;
}
}
player
.
dropMessage
(
helpMessage
);
this
.
item
(
targetPlayer
,
itemData
,
amount
);
}
}
}
@Command
(
aliases
=
{
"g"
,
"item"
,
"additem"
},
helpText
=
"/give [item id] [count] - Gives {count} amount of {item id}"
)
/**
public
static
class
Give
extends
PlayerCommand
{
* give [player] [itemId|itemName] [amount]
@Override
*/
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
@Override
public
void
execute
(
List
<
String
>
args
)
{
String
[]
split
=
raw
.
split
(
" "
);
if
(
args
.
size
()
<
2
)
{
int
itemId
=
0
,
count
=
1
;
CommandHandler
.
sendMessage
(
null
,
"Usage: give <player> <itemId|itemName> [amount]"
);
return
;
try
{
itemId
=
Integer
.
parseInt
(
split
[
0
]);
}
catch
(
Exception
e
)
{
itemId
=
0
;
}
}
try
{
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
int
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
}
catch
(
Exception
e
)
{
int
item
=
Integer
.
parseInt
(
args
.
get
(
1
));
count
=
1
;
int
amount
=
1
;
if
(
args
.
size
()
>
2
)
amount
=
Integer
.
parseInt
(
args
.
get
(
2
));
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
null
,
"Player not found."
);
return
;
}
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
item
);
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
if
(
itemData
==
null
)
{
GenshinItem
item
;
CommandHandler
.
sendMessage
(
null
,
"Invalid item id."
);
return
;
}
if
(
itemData
==
null
)
{
this
.
item
(
targetPlayer
,
itemData
,
amount
);
player
.
dropMessage
(
"Error: Item data not found"
);
}
catch
(
NumberFormatException
ignored
)
{
return
;
CommandHandler
.
sendMessage
(
null
,
"Invalid item or player ID."
);
}
}
}
if
(
itemData
.
isEquip
())
{
private
void
item
(
GenshinPlayer
player
,
ItemData
itemData
,
int
amount
)
{
GenshinItem
genshinItem
=
new
GenshinItem
(
itemData
);
if
(
itemData
.
isEquip
())
{
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
List
<
GenshinItem
>
items
=
new
LinkedList
<>();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
for
(
int
i
=
0
;
i
<
amount
;
i
++)
{
item
=
new
GenshinItem
(
itemData
);
items
.
add
(
genshinItem
);
items
.
add
(
item
);
}
player
.
getInventory
().
addItems
(
items
);
}
player
.
getInventory
().
addItems
(
items
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
items
,
ActionReason
.
SubfieldDrop
));
}
else
{
}
else
{
item
=
new
GenshinItem
(
itemData
,
c
ount
);
genshinItem
.
setCount
(
am
ount
);
player
.
getInventory
().
addItem
(
i
tem
);
player
.
getInventory
().
addItem
(
genshinI
tem
);
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
i
tem
,
ActionReason
.
SubfieldDrop
));
player
.
sendPacket
(
new
PacketItemAddHintNotify
(
genshinI
tem
,
ActionReason
.
SubfieldDrop
));
}
}
}
}
}
}
@Command
(
aliases
=
{
"d"
},
helpText
=
"/drop [item id] [count] - Drops {count} amount of {item id}"
)
@Command
(
label
=
"drop"
,
aliases
=
{
"d"
,
"dropitem"
},
public
static
class
Drop
extends
PlayerCommand
{
usage
=
"Usage: drop <itemId|itemName> [amount]"
,
@Override
execution
=
Command
.
Execution
.
PLAYER
)
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
public
static
class
DropCommand
implements
CommandHandler
{
String
[]
split
=
raw
.
split
(
" "
);
int
itemId
=
0
,
count
=
1
;
try
{
@Override
itemId
=
Integer
.
parseInt
(
split
[
0
]);
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
}
catch
(
Exception
e
)
{
if
(
args
.
size
()
<
1
)
{
itemId
=
0
;
CommandHandler
.
sendMessage
(
player
,
"Usage: drop <itemId|itemName> [amount]"
);
return
;
}
}
try
{
try
{
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
Integer
.
MAX_VALUE
),
1
);
int
item
=
Integer
.
parseInt
(
args
.
get
(
0
));
}
catch
(
Exception
e
)
{
int
amount
=
1
;
if
(
args
.
size
()
>
1
)
amount
=
Integer
.
parseInt
(
args
.
get
(
1
));
count
=
1
;
}
// Give
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
itemId
);
if
(
itemData
==
null
)
{
ItemData
itemData
=
GenshinData
.
getItemDataMap
().
get
(
item
);
player
.
dropMessage
(
"Error: I
tem
d
ata
not found"
);
if
(
i
tem
D
ata
==
null
)
{
return
;
CommandHandler
.
sendMessage
(
player
,
"Invalid item id."
);
return
;
}
}
if
(
itemData
.
isEquip
())
{
if
(
itemData
.
isEquip
())
{
float
range
=
(
5
f
+
(.
1
f
*
c
ount
));
float
range
=
(
5
f
+
(.
1
f
*
am
ount
));
for
(
int
i
=
0
;
i
<
c
ount
;
i
++)
{
for
(
int
i
=
0
;
i
<
am
ount
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
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
);
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
pos
,
1
);
player
.
getWorld
().
addEntity
(
entity
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
else
{
}
else
{
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
c
ount
);
EntityItem
entity
=
new
EntityItem
(
player
.
getWorld
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
am
ount
);
player
.
getWorld
().
addEntity
(
entity
);
player
.
getWorld
().
addEntity
(
entity
);
}
}
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
player
,
"Invalid item or player ID."
);
}
}
}
}
@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
{
@Command
(
label
=
"spawn"
,
execution
=
Command
.
Execution
.
PLAYER
,
level
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
1
]),
200
),
1
);
usage
=
"Usage: spawn <entityId|entityName> [level] [amount]"
)
}
catch
(
Exception
e
)
{
public
static
class
SpawnCommand
implements
CommandHandler
{
level
=
1
;
}
try
{
@Override
count
=
Math
.
max
(
Math
.
min
(
Integer
.
parseInt
(
split
[
2
]),
1000
),
1
);
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
}
catch
(
Exception
e
)
{
if
(
args
.
size
()
<
1
)
{
count
=
1
;
CommandHandler
.
sendMessage
(
null
,
"Usage: spawn <entityId|entityName> [amount]"
);
return
;
}
}
// Give
try
{
MonsterData
monsterData
=
GenshinData
.
getMonsterDataMap
().
get
(
monsterId
);
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
));
if
(
monsterData
==
null
)
{
MonsterData
entityData
=
GenshinData
.
getMonsterDataMap
().
get
(
entity
);
player
.
dropMessage
(
"Error: Monster data not found"
);
if
(
entityData
==
null
)
{
return
;
CommandHandler
.
sendMessage
(
null
,
"Invalid entity id."
);
return
;
}
}
float
range
=
(
5
f
+
(.
1
f
*
c
ount
));
float
range
=
(
5
f
+
(.
1
f
*
am
ount
));
for
(
int
i
=
0
;
i
<
c
ount
;
i
++)
{
for
(
int
i
=
0
;
i
<
am
ount
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
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
(),
monster
Data
,
pos
,
level
);
EntityMonster
monster
=
new
EntityMonster
(
player
.
getWorld
(),
entity
Data
,
pos
,
level
);
player
.
getWorld
().
addEntity
(
entity
);
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
(
helpText
=
"/killall"
)
public
static
class
KillAll
extends
PlayerCommand
{
@Override
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
List
<
GenshinEntity
>
toRemove
=
new
LinkedList
<>
();
World
world
=
player
.
getWorld
();
for
(
GenshinEntity
entity
:
player
.
getW
orld
()
.
getEntities
().
values
()
)
{
w
orld
.
getEntities
().
values
()
.
stream
()
if
(
entity
instanceof
EntityMonster
)
{
.
filter
(
entity
->
entity
instanceof
EntityMonster
)
toRemove
.
add
(
entity
);
.
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."
);
}
}
toRemove
.
forEach
(
e
->
player
.
getWorld
().
killEntity
(
e
,
0
));
}
}
}
}
@Command
(
helpText
=
"/resetconst - Resets all constellations for the currently active character"
)
@Command
(
label
=
"resetconst"
,
aliases
=
{
"resetconstellation"
},
public
static
class
ResetConst
extends
PlayerCommand
{
usage
=
"Usage: resetconst [all]"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
ResetConstellationCommand
implements
CommandHandler
{
@Override
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
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
();
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
if
(
entity
==
null
)
{
return
;
return
;
}
GenshinAvatar
avatar
=
entity
.
getAvatar
();
GenshinAvatar
avatar
=
entity
.
getAvatar
();
this
.
resetConstellation
(
avatar
);
player
.
dropMessage
(
"Constellations for "
+
avatar
.
getAvatarData
().
getName
()
+
" have been reset. Please relog to see changes."
);
}
}
private
void
resetConstellation
(
GenshinAvatar
avatar
)
{
avatar
.
getTalentIdList
().
clear
();
avatar
.
getTalentIdList
().
clear
();
avatar
.
setCoreProudSkillLevel
(
0
);
avatar
.
setCoreProudSkillLevel
(
0
);
avatar
.
recalcStats
();
avatar
.
recalcStats
();
avatar
.
save
();
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"
)
@Command
(
label
=
"godmode"
,
public
static
class
Godmode
extends
PlayerCommand
{
usage
=
"Usage: godmode"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
GodModeCommand
implements
CommandHandler
{
@Override
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
player
.
setGodmode
(!
player
.
has
Godmode
());
player
.
setGodmode
(!
player
.
in
Godmode
());
player
.
dropMessage
(
"Godmode is now "
+
(
player
.
has
Godmode
()
?
"
ON"
:
"OFF"
)
);
player
.
dropMessage
(
"Godmode is now "
+
(
player
.
in
Godmode
()
?
"
enabled"
:
"disabled"
)
+
"."
);
}
}
}
}
@Command
(
helpText
=
"/sethp [hp]"
)
@Command
(
label
=
"sethealth"
,
aliases
=
{
"sethp"
},
public
static
class
Sethp
extends
PlayerCommand
{
usage
=
"Usage: sethealth <hp>"
,
execution
=
Command
.
Execution
.
PLAYER
)
@Override
public
static
class
SetHealthCommand
implements
CommandHandler
{
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
String
[]
split
=
raw
.
split
(
" "
);
int
hp
=
0
;
try
{
@Override
hp
=
Math
.
max
(
Integer
.
parseInt
(
split
[
0
]),
1
);
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
}
catch
(
Exception
e
)
{
if
(
args
.
size
()
<
1
)
{
hp
=
1
;
CommandHandler
.
sendMessage
(
null
,
"Usage: sethealth <hp>"
);
return
;
}
}
try
{
int
health
=
Integer
.
parseInt
(
args
.
get
(
0
));
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
EntityAvatar
entity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
if
(
entity
==
null
)
if
(
entity
==
null
)
{
return
;
return
;
}
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
h
p
);
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
h
ealth
);
entity
.
getWorld
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
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
(
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
);
@Command
(
label
=
"clearartifacts"
,
aliases
=
{
"clearart"
},
usage
=
"Usage: clearartifacts"
,
execution
=
Command
.
Execution
.
PLAYER
)
public
static
class
ClearArtifactsCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
Inventory
playerInventory
=
player
.
getInventory
();
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
)
.
filter
(
item
->
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
)
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
}
}
}
}
}
}
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
emu.grasscutter.utils.Utils
;
public
class
ServerCommands
{
import
java.util.List
;
private
static
HashMap
<
String
,
ServerCommand
>
list
=
new
HashMap
<>()
;
import
java.util.stream.Collectors
;
static
{
/**
try
{
* A container for server-related commands.
// Look for classes
*/
for
(
Class
<?>
cls
:
ServerCommands
.
class
.
getDeclaredClasses
())
{
public
final
class
ServerCommands
{
// Get non abstract classes
@Command
(
label
=
"reload"
,
usage
=
"Usage: reload"
)
if
(!
Modifier
.
isAbstract
(
cls
.
getModifiers
()))
{
public
static
class
ReloadCommand
implements
CommandHandler
{
String
commandName
=
cls
.
getSimpleName
().
toLowerCase
();
list
.
put
(
commandName
,
(
ServerCommand
)
cls
.
newInstance
());
}
@Override
public
void
execute
(
List
<
String
>
args
)
{
Grasscutter
.
getLogger
().
info
(
"Reloading config."
);
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
)
{
@Command
(
label
=
"sendmessage"
,
aliases
=
{
"sendmsg"
,
"msg"
},
String
[]
split
=
msg
.
split
(
" "
);
usage
=
"Usage: sendmessage <player> <message>"
)
public
static
class
SendMessageCommand
implements
CommandHandler
{
// End if invalid
@Override
if
(
split
.
length
==
0
)
{
public
void
execute
(
List
<
String
>
args
)
{
return
;
if
(
args
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
null
,
"Usage: sendmessage <player> <message>"
);
return
;
}
}
//
try
{
String
first
=
split
[
0
].
toLowerCase
();
int
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
ServerCommand
c
=
ServerCommands
.
list
.
get
(
first
);
String
message
=
String
.
join
(
" "
,
args
.
subList
(
1
,
args
.
size
()));
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
null
,
"Player not found."
);
return
;
}
if
(
c
!=
null
)
{
targetPlayer
.
dropMessage
(
message
);
// Execute
CommandHandler
.
sendMessage
(
null
,
"Message sent."
);
int
len
=
Math
.
min
(
first
.
length
()
+
1
,
msg
.
length
());
}
catch
(
NumberFormatException
ignored
)
{
c
.
execute
(
msg
.
substring
(
len
)
);
CommandHandler
.
sendMessage
(
null
,
"Invalid player ID."
);
}
}
}
}
public
static
abstract
class
ServerCommand
{
@Override
public
abstract
void
execute
(
String
raw
);
public
void
execute
(
GenshinPlayer
player
,
List
<
String
>
args
)
{
if
(
args
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
player
,
"Usage: sendmessage <player> <message>"
);
return
;
}
}
// ================ Commands ================
try
{
int
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
String
message
=
String
.
join
(
" "
,
args
.
subList
(
1
,
args
.
size
()));
public
static
class
Reload
extends
ServerCommand
{
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerById
(
target
);
@Override
if
(
targetPlayer
==
null
)
{
public
void
execute
(
String
raw
)
{
CommandHandler
.
sendMessage
(
player
,
"Player not found."
);
return
;
Grasscutter
.
getLogger
().
info
(
"Reloading config."
);
}
Grasscutter
.
loadConfig
();
Grasscutter
.
getDispatchServer
().
loadQueries
();
targetPlayer
.
sendMessage
(
player
,
message
);
Grasscutter
.
getLogger
().
info
(
"Reload complete."
);
CommandHandler
.
sendMessage
(
player
,
"Message sent."
);
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
player
,
"Invalid player ID."
);
}
}
}
}
}
public
static
class
sendMsg
extends
ServerCommand
{
@Command
(
label
=
"account"
,
@Override
usage
=
"Usage: account <create|delete> <username> [uid]"
,
public
void
execute
(
String
raw
)
{
execution
=
Command
.
Execution
.
CONSOLE
)
List
<
String
>
split
=
Arrays
.
asList
(
raw
.
split
(
" "
));
public
static
class
AccountCommand
implements
CommandHandler
{
if
(
split
.
size
()
<
2
)
{
@Override
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
public
void
execute
(
List
<
String
>
args
)
{
return
;
if
(
args
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
null
,
"Usage: account <create|delete> <username> [uid]"
);
return
;
}
}
String
playerID
=
split
.
get
(
0
);
String
action
=
args
.
get
(
0
);
String
message
=
split
.
stream
().
skip
(
1
).
collect
(
Collectors
.
joining
(
" "
)
);
String
username
=
args
.
get
(
1
);
switch
(
action
)
{
default
:
CommandHandler
.
sendMessage
(
null
,
"Usage: account <create|delete> <username> [uid]"
);
return
;
case
"create"
:
int
uid
=
0
;
if
(
args
.
size
()
>
2
)
{
try
{
uid
=
Integer
.
parseInt
(
args
.
get
(
2
));
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid UID."
);
return
;
}
}
emu
.
grasscutter
.
game
.
Account
account
=
DatabaseHelper
.
getAccountByPlayerId
(
Integer
.
parseInt
(
playerID
));
Account
account
=
DatabaseHelper
.
createAccountWithId
(
username
,
uid
);
if
(
account
!=
null
)
{
if
(
account
==
null
)
{
GenshinPlayer
player
=
Grasscutter
.
getGameServer
().
getPlayerById
(
Integer
.
parseInt
(
playerID
));
CommandHandler
.
sendMessage
(
null
,
"Account already exists."
);
return
;
if
(
player
!=
null
)
{
player
.
dropMessage
(
message
);
Grasscutter
.
getLogger
().
info
(
String
.
format
(
"Successfully sent message to %s: %s"
,
playerID
,
message
));
}
else
{
}
else
{
Grasscutter
.
getLogger
().
error
(
"Player not online"
);
CommandHandler
.
sendMessage
(
null
,
"Account created with UID "
+
account
.
getPlayerId
()
+
"."
);
account
.
addPermission
(
"*"
);
// Grant the player superuser permissions.
}
}
}
else
{
return
;
Grasscutter
.
getLogger
().
error
(
String
.
format
(
"Player %s does not exist"
,
playerID
));
case
"delete"
:
if
(
DatabaseHelper
.
deleteAccount
(
username
))
{
CommandHandler
.
sendMessage
(
null
,
"Account deleted."
);
return
;
}
else
CommandHandler
.
sendMessage
(
null
,
"Account not found."
);
return
;
}
}
}
}
}
}
public
static
class
Account
extends
ServerCommand
{
@Command
(
label
=
"permission"
,
@Override
usage
=
"Usage: permission <add|remove> <username> <permission>"
,
public
void
execute
(
String
raw
)
{
execution
=
Command
.
Execution
.
CONSOLE
)
String
[]
split
=
raw
.
split
(
" "
);
public
static
class
PermissionCommand
implements
CommandHandler
{
if
(
split
.
length
<
2
)
{
@Override
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
public
void
execute
(
List
<
String
>
args
)
{
return
;
if
(
args
.
size
()
<
3
)
{
CommandHandler
.
sendMessage
(
null
,
"Usage: permission <add|remove> <username> <permission>"
);
return
;
}
}
String
command
=
split
[
0
].
toLowerCase
();
String
action
=
args
.
get
(
0
);
String
username
=
split
[
1
];
String
username
=
args
.
get
(
1
);
String
permission
=
args
.
get
(
2
);
switch
(
command
)
{
case
"create"
:
if
(
split
.
length
<
2
)
{
Grasscutter
.
getLogger
().
error
(
"Invalid amount of args"
);
return
;
}
int
reservedId
=
0
;
Account
account
=
Grasscutter
.
getGameServer
().
getAccountByName
(
username
);
try
{
if
(
account
==
null
)
{
reservedId
=
Integer
.
parseInt
(
split
[
2
]);
CommandHandler
.
sendMessage
(
null
,
"Account not found."
);
return
;
}
catch
(
Exception
e
)
{
reservedId
=
0
;
}
}
emu
.
grasscutter
.
game
.
Account
account
=
DatabaseHelper
.
createAccountWithId
(
username
,
reservedId
);
switch
(
action
)
{
if
(
account
!=
null
)
{
default
:
Grasscutter
.
getLogger
().
info
(
"Account created"
+
(
reservedId
>
0
?
" with an id of "
+
reservedId
:
""
));
CommandHandler
.
sendMessage
(
null
,
"Usage: permission <add|remove> <username> <permission>"
);
}
else
{
Grasscutter
.
getLogger
().
error
(
"Account already exists"
);
}
break
;
break
;
case
"delete"
:
case
"add"
:
boolean
success
=
DatabaseHelper
.
deleteAccount
(
username
);
if
(
account
.
addPermission
(
permission
))
{
CommandHandler
.
sendMessage
(
null
,
"Permission added."
);
}
else
CommandHandler
.
sendMessage
(
null
,
"They already have this permission!"
);
break
;
case
"remove"
:
if
(
account
.
removePermission
(
permission
))
{
CommandHandler
.
sendMessage
(
null
,
"Permission removed."
);
}
else
CommandHandler
.
sendMessage
(
null
,
"They don't have this permission!"
);
break
;
}
if
(
success
)
{
account
.
save
();
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);
@Command
(
label
=
"help"
,
usage
=
"Usage: help [command]"
)
public
static
class
HelpCommand
implements
CommandHandler
{
if (account == null) {
@Override
Grasscutter.getLogger().error("No account found!");
public
void
execute
(
List
<
String
>
args
)
{
return;
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
;
}
}
token = split[2];
Command
annotation
=
handler
.
getClass
().
getAnnotation
(
Command
.
class
);
token = PasswordHelper.hashPassword(token);
CommandHandler
.
sendMessage
(
null
,
annotation
.
usage
());
}
}
account.setPassword(token);
@Override
DatabaseHelper.saveAccount(account);
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
;
}
Grasscutter.getLogger().info("Password set");
Command
annotation
=
handler
.
getClass
().
getAnnotation
(
Command
.
class
);
break;
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
;
...
@@ -85,6 +94,22 @@ public class Account {
...
@@ -85,6 +94,22 @@ public class Account {
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
()
{
this
.
token
=
Utils
.
bytesToHex
(
Crypto
.
createSessionKey
(
32
));
this
.
token
=
Utils
.
bytesToHex
(
Crypto
.
createSessionKey
(
32
));
...
@@ -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
;
}
}
...
@@ -559,6 +554,15 @@ public class GenshinPlayer {
...
@@ -559,6 +554,15 @@ public class GenshinPlayer {
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,9 +139,11 @@ public final class DispatchServer {
...
@@ -139,9 +139,11 @@ public final class DispatchServer {
}
}
public
void
start
()
throws
Exception
{
public
void
start
()
throws
Exception
{
HttpsServer
server
=
HttpsServer
.
create
(
getAddress
(),
0
);
HttpServer
server
;
if
(
Grasscutter
.
getConfig
().
UseSSL
)
{
HttpsServer
httpsServer
;
httpsServer
=
HttpsServer
.
create
(
getAddress
(),
0
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
DispatchServerKeystorePath
))
{
try
(
FileInputStream
fis
=
new
FileInputStream
(
Grasscutter
.
getConfig
().
DispatchServerKeystorePath
))
{
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
DispatchServerKeystorePassword
.
toCharArray
();
char
[]
keystorePassword
=
Grasscutter
.
getConfig
().
DispatchServerKeystorePassword
.
toCharArray
();
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
KeyStore
ks
=
KeyStore
.
getInstance
(
"PKCS12"
);
...
@@ -151,11 +153,15 @@ public final class DispatchServer {
...
@@ -151,11 +153,15 @@ public final class DispatchServer {
sslContext
.
init
(
kmf
.
getKeyManagers
(),
null
,
null
);
sslContext
.
init
(
kmf
.
getKeyManagers
(),
null
,
null
);
server
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
httpsServer
.
setHttpsConfigurator
(
new
HttpsConfigurator
(
sslContext
));
server
=
httpsServer
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"No SSL cert found!"
);
Grasscutter
.
getLogger
().
error
(
"No SSL cert found!"
);
return
;
return
;
}
}
}
else
{
server
=
HttpServer
.
create
(
getAddress
(),
0
);
}
server
.
createContext
(
"/"
,
t
->
{
server
.
createContext
(
"/"
,
t
->
{
//Create a response form the request query parameters
//Create a response form the request query parameters
...
@@ -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,10 +20,9 @@ import emu.grasscutter.net.packet.PacketHandler;
...
@@ -23,10 +20,9 @@ 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
;
...
@@ -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