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
81183db1
Commit
81183db1
authored
May 16, 2022
by
Melledy
Browse files
Merge branch 'development' into dev-world-scripts
parents
593de838
21478b0a
Changes
19
Expand all
Show whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/Configuration.java
View file @
81183db1
...
@@ -4,9 +4,11 @@ import emu.grasscutter.utils.ConfigContainer;
...
@@ -4,9 +4,11 @@ import emu.grasscutter.utils.ConfigContainer;
import
emu.grasscutter.utils.ConfigContainer.*
;
import
emu.grasscutter.utils.ConfigContainer.*
;
import
java.util.Locale
;
import
java.util.Locale
;
import
java.nio.file.Paths
;
import
static
emu
.
grasscutter
.
Grasscutter
.
config
;
import
static
emu
.
grasscutter
.
Grasscutter
.
config
;
/**
/**
* A data container for the server's configuration.
* A data container for the server's configuration.
*
*
...
@@ -24,12 +26,12 @@ public final class Configuration extends ConfigContainer {
...
@@ -24,12 +26,12 @@ public final class Configuration extends ConfigContainer {
public
static
final
Locale
LANGUAGE
=
config
.
language
.
language
;
public
static
final
Locale
LANGUAGE
=
config
.
language
.
language
;
public
static
final
Locale
FALLBACK_LANGUAGE
=
config
.
language
.
fallback
;
public
static
final
Locale
FALLBACK_LANGUAGE
=
config
.
language
.
fallback
;
p
ublic
static
final
String
DATA_FOLDER
=
config
.
folderStructure
.
data
;
p
rivate
static
final
String
DATA_FOLDER
=
config
.
folderStructure
.
data
;
p
ublic
static
final
String
RESOURCES_FOLDER
=
config
.
folderStructure
.
resources
;
p
rivate
static
final
String
RESOURCES_FOLDER
=
config
.
folderStructure
.
resources
;
p
ublic
static
final
String
KEYS_FOLDER
=
config
.
folderStructure
.
keys
;
p
rivate
static
final
String
KEYS_FOLDER
=
config
.
folderStructure
.
keys
;
p
ublic
static
final
String
PLUGINS_FOLDER
=
config
.
folderStructure
.
plugins
;
p
rivate
static
final
String
PLUGINS_FOLDER
=
config
.
folderStructure
.
plugins
;
p
ublic
static
final
String
SCRIPTS_FOLDER
=
config
.
folderStructure
.
scripts
;
p
rivate
static
final
String
SCRIPTS_FOLDER
=
config
.
folderStructure
.
scripts
;
p
ublic
static
final
String
PACKETS_FOLDER
=
config
.
folderStructure
.
packets
;
p
rivate
static
final
String
PACKETS_FOLDER
=
config
.
folderStructure
.
packets
;
public
static
final
Server
SERVER
=
config
.
server
;
public
static
final
Server
SERVER
=
config
.
server
;
public
static
final
Database
DATABASE
=
config
.
databaseInfo
;
public
static
final
Database
DATABASE
=
config
.
databaseInfo
;
...
@@ -49,17 +51,36 @@ public final class Configuration extends ConfigContainer {
...
@@ -49,17 +51,36 @@ public final class Configuration extends ConfigContainer {
/*
/*
* Utilities
* Utilities
*/
*/
public
static
String
DATA
()
{
return
DATA_FOLDER
;
}
public
static
String
DATA
(
String
path
)
{
public
static
String
DATA
(
String
path
)
{
return
DATA_FOLDER
+
"/"
+
path
;
return
Paths
.
get
(
DATA_FOLDER
,
path
).
toString
()
;
}
}
public
static
String
RESOURCE
(
String
path
)
{
public
static
String
RESOURCE
(
String
path
)
{
return
RESOURCES_FOLDER
+
"/"
+
path
;
return
Paths
.
get
(
RESOURCES_FOLDER
,
path
).
toString
();
}
public
static
String
KEY
(
String
path
)
{
return
Paths
.
get
(
KEYS_FOLDER
,
path
).
toString
();
}
public
static
String
PLUGIN
()
{
return
PLUGINS_FOLDER
;
}
public
static
String
PLUGIN
(
String
path
)
{
return
Paths
.
get
(
PLUGINS_FOLDER
,
path
).
toString
();
}
}
public
static
String
SCRIPT
(
String
path
)
{
public
static
String
SCRIPT
(
String
path
)
{
return
SCRIPTS_FOLDER
+
"/"
+
path
;
return
Paths
.
get
(
SCRIPTS_FOLDER
,
path
).
toString
();
}
public
static
String
PACKET
(
String
path
)
{
return
Paths
.
get
(
PACKETS_FOLDER
,
path
).
toString
();
}
}
/**
/**
...
...
src/main/java/emu/grasscutter/Grasscutter.java
View file @
81183db1
...
@@ -304,7 +304,7 @@ public final class Grasscutter {
...
@@ -304,7 +304,7 @@ public final class Grasscutter {
getLogger
().
info
(
translate
(
"messages.status.done"
));
getLogger
().
info
(
translate
(
"messages.status.done"
));
String
input
=
null
;
String
input
=
null
;
boolean
isLastInterrupted
=
false
;
boolean
isLastInterrupted
=
false
;
while
(
tru
e
)
{
while
(
config
.
server
.
game
.
enableConsol
e
)
{
try
{
try
{
input
=
consoleLineReader
.
readLine
(
"> "
);
input
=
consoleLineReader
.
readLine
(
"> "
);
}
catch
(
UserInterruptException
e
)
{
}
catch
(
UserInterruptException
e
)
{
...
...
src/main/java/emu/grasscutter/command/commands/JoinCommand.java
deleted
100644 → 0
View file @
593de838
package
emu.grasscutter.command.commands
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp
;
import
java.util.ArrayList
;
import
java.util.List
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
@Command
(
label
=
"join"
,
usage
=
"join [AvatarIDs] such as\"join 10000038 10000039\""
,
description
=
"commands.join.description"
,
permission
=
"player.join"
)
public
class
JoinCommand
implements
CommandHandler
{
@Override
public
void
execute
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.execution.need_target"
));
return
;
}
List
<
Integer
>
avatarIds
=
new
ArrayList
<>();
for
(
String
arg
:
args
)
{
try
{
int
avatarId
=
Integer
.
parseInt
(
arg
);
avatarIds
.
add
(
avatarId
);
}
catch
(
Exception
ignored
)
{
ignored
.
printStackTrace
();
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.generic.invalid.avatarId"
));
return
;
}
}
for
(
int
i
=
0
;
i
<
args
.
size
();
i
++)
{
Avatar
avatar
=
targetPlayer
.
getAvatars
().
getAvatarById
(
avatarIds
.
get
(
i
));
if
(
avatar
==
null
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.generic.invalid.avatarId"
));
return
;
}
if
(
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
contains
(
avatar
)){
continue
;
}
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
addAvatar
(
avatar
);
}
// Packet
targetPlayer
.
getTeamManager
().
updateTeamEntities
(
new
PacketChangeMpTeamAvatarRsp
(
targetPlayer
,
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
()));
}
}
src/main/java/emu/grasscutter/command/commands/RemoveCommand.java
deleted
100644 → 0
View file @
593de838
package
emu.grasscutter.command.commands
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
@Command
(
label
=
"remove"
,
usage
=
"remove [indexOfYourTeams] index start from 1"
,
description
=
"commands.remove.description"
,
permission
=
"player.remove"
)
public
class
RemoveCommand
implements
CommandHandler
{
@Override
public
void
execute
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.execution.need_target"
));
return
;
}
List
<
Integer
>
avatarIndexList
=
new
ArrayList
<>();
for
(
String
arg
:
args
)
{
try
{
int
avatarIndex
=
Integer
.
parseInt
(
arg
);
if
(!
avatarIndexList
.
contains
(
avatarIndex
))
{
avatarIndexList
.
add
(
avatarIndex
);
}
}
catch
(
Exception
ignored
)
{
ignored
.
printStackTrace
();
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.remove.invalid_index"
));
return
;
}
}
Collections
.
sort
(
avatarIndexList
,
Collections
.
reverseOrder
());
for
(
int
i
=
0
;
i
<
avatarIndexList
.
size
();
i
++)
{
if
(
avatarIndexList
.
get
(
i
)
>
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
getAvatars
().
size
()
||
avatarIndexList
.
get
(
i
)
<=
0
)
{
CommandHandler
.
sendMessage
(
targetPlayer
,
translate
(
"commands.remove.invalid_index"
));
return
;
}
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
removeAvatar
(
avatarIndexList
.
get
(
i
)
-
1
);
}
// Packet
targetPlayer
.
getTeamManager
().
updateTeamEntities
(
new
PacketChangeMpTeamAvatarRsp
(
targetPlayer
,
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
()));
}
}
src/main/java/emu/grasscutter/command/commands/TeamCommand.java
0 → 100644
View file @
81183db1
package
emu.grasscutter.command.commands
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp
;
import
java.util.List
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
import
static
emu
.
grasscutter
.
Configuration
.*;
@Command
(
label
=
"team"
,
usage
=
"team <add|remove|set> [avatarId,...] [index|first|last|index-index,...]"
,
permission
=
"player.team"
,
permissionTargeted
=
"player.team.others"
,
description
=
"commands.team.description"
)
public
final
class
TeamCommand
implements
CommandHandler
{
private
static
final
int
BASE_AVATARID
=
10000000
;
@Override
public
void
execute
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.execution.need_target"
));
return
;
}
if
(
args
.
isEmpty
())
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.usage"
));
return
;
}
switch
(
args
.
get
(
0
))
{
case
"add"
:
if
(!
addCommand
(
sender
,
targetPlayer
,
args
))
return
;
break
;
case
"remove"
:
if
(!
removeCommand
(
sender
,
targetPlayer
,
args
))
return
;
break
;
case
"set"
:
if
(!
setCommand
(
sender
,
targetPlayer
,
args
))
return
;
break
;
default
:
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.invalid_usage"
));
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.usage"
));
return
;
}
targetPlayer
.
getTeamManager
().
updateTeamEntities
(
new
PacketChangeMpTeamAvatarRsp
(
targetPlayer
,
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
()));
}
private
boolean
addCommand
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
if
(
args
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.invalid_usage"
));
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.add_usage"
));
return
false
;
}
int
index
=
-
1
;
if
(
args
.
size
()
>
2
)
{
try
{
index
=
Integer
.
parseInt
(
args
.
get
(
2
))
-
1
;
if
(
index
<
0
)
index
=
0
;
}
catch
(
Exception
e
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.invalid_index"
));
return
false
;
}
}
var
avatarIds
=
args
.
get
(
1
).
split
(
","
);
var
currentTeamAvatars
=
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
getAvatars
();
if
(
currentTeamAvatars
.
size
()
+
avatarIds
.
length
>
GAME_OPTIONS
.
avatarLimits
.
singlePlayerTeam
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.add_too_much"
,
GAME_OPTIONS
.
avatarLimits
.
singlePlayerTeam
));
return
false
;
}
for
(
var
avatarId:
avatarIds
)
{
try
{
int
id
=
Integer
.
parseInt
(
avatarId
);
var
ret
=
addAvatar
(
sender
,
targetPlayer
,
id
,
index
);
if
(
index
>
0
)
++
index
;
if
(!
ret
)
continue
;
}
catch
(
Exception
e
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.failed_to_add_avatar"
,
avatarId
));
continue
;
}
}
return
true
;
}
private
boolean
removeCommand
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
if
(
args
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.invalid_usage"
));
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.remove_usage"
));
return
false
;
}
var
currentTeamAvatars
=
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
getAvatars
();
var
avatarCount
=
currentTeamAvatars
.
size
();
var
metaIndexList
=
args
.
get
(
1
).
split
(
","
);
var
indexes
=
new
HashSet
<
Integer
>();
var
ignoreList
=
new
ArrayList
<
Integer
>();
for
(
var
metaIndex:
metaIndexList
)
{
// step 1: parse metaIndex to indexes
var
subIndexes
=
transformToIndexes
(
metaIndex
,
avatarCount
);
if
(
subIndexes
==
null
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.failed_to_parse_index"
,
metaIndex
));
continue
;
}
// step 2: get all of the avatar id through indexes
for
(
var
avatarIndex:
subIndexes
)
{
try
{
indexes
.
add
(
currentTeamAvatars
.
get
(
avatarIndex
-
1
));
}
catch
(
Exception
e
)
{
ignoreList
.
add
(
avatarIndex
);
continue
;
}
}
}
// step 3: check if user remove all of the avatar
if
(
indexes
.
size
()
>=
avatarCount
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.remove_too_much"
));
return
false
;
}
// step 4: hint user for ignore index
if
(!
ignoreList
.
isEmpty
())
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.ignore_index"
,
ignoreList
));
}
// step 5: remove
currentTeamAvatars
.
removeAll
(
indexes
);
return
true
;
}
private
boolean
setCommand
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
if
(
args
.
size
()
<
3
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.invalid_usage"
));
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.set_usage"
));
return
false
;
}
var
currentTeamAvatars
=
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
getAvatars
();
int
index
;
try
{
index
=
Integer
.
parseInt
(
args
.
get
(
1
))
-
1
;
if
(
index
<
0
)
index
=
0
;
}
catch
(
Exception
e
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.failed_to_parse_index"
,
args
.
get
(
1
)));
return
false
;
}
if
(
index
+
1
>
currentTeamAvatars
.
size
())
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.index_out_of_range"
));
return
false
;
}
int
avatarId
;
try
{
avatarId
=
Integer
.
parseInt
(
args
.
get
(
2
));
}
catch
(
Exception
e
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.failed_parse_avatar_id"
,
args
.
get
(
2
)));
return
false
;
}
if
(
avatarId
<
BASE_AVATARID
)
{
avatarId
+=
BASE_AVATARID
;
}
if
(
currentTeamAvatars
.
contains
(
avatarId
))
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.avatar_already_in_team"
,
avatarId
));
return
false
;
}
if
(!
targetPlayer
.
getAvatars
().
hasAvatar
(
avatarId
))
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.avatar_not_found"
,
avatarId
));
return
false
;
}
currentTeamAvatars
.
set
(
index
,
avatarId
);
return
true
;
}
private
boolean
addAvatar
(
Player
sender
,
Player
targetPlayer
,
int
avatarId
,
int
index
)
{
if
(
avatarId
<
BASE_AVATARID
)
{
avatarId
+=
BASE_AVATARID
;
}
var
currentTeamAvatars
=
targetPlayer
.
getTeamManager
().
getCurrentTeamInfo
().
getAvatars
();
if
(
currentTeamAvatars
.
contains
(
avatarId
))
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.avatar_already_in_team"
,
avatarId
));
return
false
;
}
if
(!
sender
.
getAvatars
().
hasAvatar
(
avatarId
))
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.team.avatar_not_found"
,
avatarId
));
return
false
;
}
if
(
index
<
0
)
{
currentTeamAvatars
.
add
(
avatarId
);
}
else
{
currentTeamAvatars
.
add
(
index
,
avatarId
);
}
return
true
;
}
private
List
<
Integer
>
transformToIndexes
(
String
metaIndexes
,
int
listLength
)
{
// step 1: check if metaIndexes is a special constants
if
(
metaIndexes
.
equals
(
"first"
))
{
return
List
.
of
(
1
);
}
else
if
(
metaIndexes
.
equals
(
"last"
))
{
return
List
.
of
(
listLength
);
}
// step 2: check if metaIndexes is a range
if
(
metaIndexes
.
contains
(
"-"
))
{
var
range
=
metaIndexes
.
split
(
"-"
);
if
(
range
.
length
<
2
)
{
return
null
;
}
int
min
,
max
;
try
{
min
=
switch
(
range
[
0
])
{
case
"first"
->
1
;
case
"last"
->
listLength
;
default
->
Integer
.
parseInt
(
range
[
0
]);
};
max
=
switch
(
range
[
1
])
{
case
"first"
->
1
;
case
"last"
->
listLength
;
default
->
Integer
.
parseInt
(
range
[
1
]);
};
}
catch
(
Exception
e
)
{
return
null
;
}
if
(
min
>
max
)
{
min
^=
max
;
max
^=
min
;
min
^=
max
;
}
var
indexes
=
new
ArrayList
<
Integer
>();
for
(
int
i
=
min
;
i
<=
max
;
++
i
)
{
indexes
.
add
(
i
);
}
return
indexes
;
}
// step 3: index is a value, simply return
try
{
int
index
=
Integer
.
parseInt
(
metaIndexes
);
return
List
.
of
(
index
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
}
src/main/java/emu/grasscutter/game/gacha/GachaManager.java
View file @
81183db1
...
@@ -358,7 +358,7 @@ public class GachaManager {
...
@@ -358,7 +358,7 @@ public class GachaManager {
if
(
this
.
watchService
==
null
)
{
if
(
this
.
watchService
==
null
)
{
try
{
try
{
this
.
watchService
=
FileSystems
.
getDefault
().
newWatchService
();
this
.
watchService
=
FileSystems
.
getDefault
().
newWatchService
();
Path
path
=
new
File
(
DATA
_FOLDER
).
toPath
();
Path
path
=
new
File
(
DATA
()
).
toPath
();
path
.
register
(
watchService
,
new
WatchEvent
.
Kind
[]{
StandardWatchEventKinds
.
ENTRY_MODIFY
},
SensitivityWatchEventModifier
.
HIGH
);
path
.
register
(
watchService
,
new
WatchEvent
.
Kind
[]{
StandardWatchEventKinds
.
ENTRY_MODIFY
},
SensitivityWatchEventModifier
.
HIGH
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"
);
Grasscutter
.
getLogger
().
error
(
"Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"
);
...
...
src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java
View file @
81183db1
This diff is collapsed.
Click to expand it.
src/main/java/emu/grasscutter/plugin/Plugin.java
View file @
81183db1
...
@@ -37,7 +37,7 @@ public abstract class Plugin {
...
@@ -37,7 +37,7 @@ public abstract class Plugin {
this
.
identifier
=
identifier
;
this
.
identifier
=
identifier
;
this
.
classLoader
=
classLoader
;
this
.
classLoader
=
classLoader
;
this
.
dataFolder
=
new
File
(
PLUGIN
S_FOLDER
,
identifier
.
name
);
this
.
dataFolder
=
new
File
(
PLUGIN
()
,
identifier
.
name
);
this
.
logger
=
LoggerFactory
.
getLogger
(
identifier
.
name
);
this
.
logger
=
LoggerFactory
.
getLogger
(
identifier
.
name
);
if
(!
this
.
dataFolder
.
exists
()
&&
!
this
.
dataFolder
.
mkdirs
())
{
if
(!
this
.
dataFolder
.
exists
()
&&
!
this
.
dataFolder
.
mkdirs
())
{
...
...
src/main/java/emu/grasscutter/plugin/PluginManager.java
View file @
81183db1
...
@@ -34,7 +34,7 @@ public final class PluginManager {
...
@@ -34,7 +34,7 @@ public final class PluginManager {
* Loads plugins from the config-specified directory.
* Loads plugins from the config-specified directory.
*/
*/
private
void
loadPlugins
()
{
private
void
loadPlugins
()
{
File
pluginsDir
=
new
File
(
Utils
.
toFilePath
(
PLUGIN
S_FOLDER
));
File
pluginsDir
=
new
File
(
Utils
.
toFilePath
(
PLUGIN
()
));
if
(!
pluginsDir
.
exists
()
&&
!
pluginsDir
.
mkdirs
())
{
if
(!
pluginsDir
.
exists
()
&&
!
pluginsDir
.
mkdirs
())
{
Grasscutter
.
getLogger
().
error
(
"Failed to create plugins directory: "
+
pluginsDir
.
getAbsolutePath
());
Grasscutter
.
getLogger
().
error
(
"Failed to create plugins directory: "
+
pluginsDir
.
getAbsolutePath
());
return
;
return
;
...
...
src/main/java/emu/grasscutter/server/game/GameSession.java
View file @
81183db1
...
@@ -140,7 +140,7 @@ public class GameSession extends KcpChannel {
...
@@ -140,7 +140,7 @@ public class GameSession extends KcpChannel {
}
}
public
void
replayPacket
(
int
opcode
,
String
name
)
{
public
void
replayPacket
(
int
opcode
,
String
name
)
{
String
filePath
=
PACKET
S_FOLDER
+
name
;
String
filePath
=
PACKET
(
name
)
;
File
p
=
new
File
(
filePath
);
File
p
=
new
File
(
filePath
);
if
(!
p
.
exists
())
return
;
if
(!
p
.
exists
())
return
;
...
...
src/main/java/emu/grasscutter/server/http/HttpServer.java
View file @
81183db1
...
@@ -141,7 +141,7 @@ public final class HttpServer {
...
@@ -141,7 +141,7 @@ public final class HttpServer {
public
static
class
DefaultRequestRouter
implements
Router
{
public
static
class
DefaultRequestRouter
implements
Router
{
@Override
public
void
applyRoutes
(
Express
express
,
Javalin
handle
)
{
@Override
public
void
applyRoutes
(
Express
express
,
Javalin
handle
)
{
express
.
get
(
"/"
,
(
request
,
response
)
->
{
express
.
get
(
"/"
,
(
request
,
response
)
->
{
File
file
=
new
File
(
HTTP_STATIC_FILES
.
error
File
);
File
file
=
new
File
(
HTTP_STATIC_FILES
.
index
File
);
if
(!
file
.
exists
())
if
(!
file
.
exists
())
response
.
send
(
"""
response
.
send
(
"""
<!DOCTYPE html>
<!DOCTYPE html>
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicle
Spawn
Req.java
→
src/main/java/emu/grasscutter/server/packet/recv/Handler
Create
VehicleReq.java
View file @
81183db1
...
@@ -3,19 +3,19 @@ package emu.grasscutter.server.packet.recv;
...
@@ -3,19 +3,19 @@ package emu.grasscutter.server.packet.recv;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.Vehicle
Spawn
ReqOuterClass
;
import
emu.grasscutter.net.proto.
Create
VehicleReqOuterClass
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketVehicle
Spawn
Rsp
;
import
emu.grasscutter.server.packet.send.Packet
Create
VehicleRsp
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Position
;
@Opcodes
(
PacketOpcodes
.
Vehicle
Spawn
Req
)
@Opcodes
(
PacketOpcodes
.
Create
VehicleReq
)
public
class
HandlerVehicle
Spawn
Req
extends
PacketHandler
{
public
class
Handler
Create
VehicleReq
extends
PacketHandler
{
@Override
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
Vehicle
Spawn
ReqOuterClass
.
Vehicle
Spawn
Req
req
=
Vehicle
Spawn
ReqOuterClass
.
Vehicle
Spawn
Req
.
parseFrom
(
payload
);
Create
VehicleReqOuterClass
.
Create
VehicleReq
req
=
Create
VehicleReqOuterClass
.
Create
VehicleReq
.
parseFrom
(
payload
);
session
.
send
(
new
PacketVehicle
Spawn
Rsp
(
session
.
getPlayer
(),
req
.
getVehicleId
(),
req
.
getPointId
(),
new
Position
(
req
.
getPos
()),
new
Position
(
req
.
getRot
())));
session
.
send
(
new
Packet
Create
VehicleRsp
(
session
.
getPlayer
(),
req
.
getVehicleId
(),
req
.
getPointId
(),
new
Position
(
req
.
getPos
()),
new
Position
(
req
.
getRot
())));
}
}
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java
View file @
81183db1
...
@@ -9,12 +9,12 @@ import emu.grasscutter.server.game.GameSession;
...
@@ -9,12 +9,12 @@ import emu.grasscutter.server.game.GameSession;
import
emu.grasscutter.server.packet.send.PacketHostPlayerNotify
;
import
emu.grasscutter.server.packet.send.PacketHostPlayerNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerEnterSceneInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerEnterSceneInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerGameTimeNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerGameTimeNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerWorldSceneInfoListNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneInitFinishRsp
;
import
emu.grasscutter.server.packet.send.PacketSceneInitFinishRsp
;
import
emu.grasscutter.server.packet.send.PacketScenePlayerInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketScenePlayerInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneTeamUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneTeamUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneTimeNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneTimeNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneUnlockInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketServerTimeNotify
;
import
emu.grasscutter.server.packet.send.PacketServerTimeNotify
;
import
emu.grasscutter.server.packet.send.PacketSyncScenePlayTeamEntityNotify
;
import
emu.grasscutter.server.packet.send.PacketSyncScenePlayTeamEntityNotify
;
import
emu.grasscutter.server.packet.send.PacketSyncTeamEntityNotify
;
import
emu.grasscutter.server.packet.send.PacketSyncTeamEntityNotify
;
...
@@ -30,7 +30,7 @@ public class HandlerSceneInitFinishReq extends PacketHandler {
...
@@ -30,7 +30,7 @@ public class HandlerSceneInitFinishReq extends PacketHandler {
session
.
send
(
new
PacketServerTimeNotify
());
session
.
send
(
new
PacketServerTimeNotify
());
session
.
send
(
new
PacketWorldPlayerInfoNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketWorldPlayerInfoNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketWorldDataNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketWorldDataNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
Packet
SceneUnlockInfo
Notify
());
session
.
send
(
new
Packet
PlayerWorldSceneInfoList
Notify
());
session
.
send
(
new
BasePacket
(
PacketOpcodes
.
SceneForceUnlockNotify
));
session
.
send
(
new
BasePacket
(
PacketOpcodes
.
SceneForceUnlockNotify
));
session
.
send
(
new
PacketHostPlayerNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketHostPlayerNotify
(
session
.
getPlayer
().
getWorld
()));
...
...
src/main/java/emu/grasscutter/server/packet/send/PacketVehicle
Spawn
Rsp.java
→
src/main/java/emu/grasscutter/server/packet/send/Packet
Create
VehicleRsp.java
View file @
81183db1
...
@@ -10,7 +10,7 @@ import emu.grasscutter.net.packet.BasePacket;
...
@@ -10,7 +10,7 @@ import emu.grasscutter.net.packet.BasePacket;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember
;
import
emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember
;
import
emu.grasscutter.net.proto.Vehicle
Spawn
RspOuterClass.Vehicle
Spawn
Rsp
;
import
emu.grasscutter.net.proto.
Create
VehicleRspOuterClass.
Create
VehicleRsp
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Position
;
...
@@ -19,11 +19,11 @@ import java.util.List;
...
@@ -19,11 +19,11 @@ import java.util.List;
import
static
emu
.
grasscutter
.
net
.
proto
.
VehicleInteractTypeOuterClass
.
VehicleInteractType
.
VEHICLE_INTERACT_OUT
;
import
static
emu
.
grasscutter
.
net
.
proto
.
VehicleInteractTypeOuterClass
.
VehicleInteractType
.
VEHICLE_INTERACT_OUT
;
public
class
PacketVehicle
Spawn
Rsp
extends
BasePacket
{
public
class
Packet
Create
VehicleRsp
extends
BasePacket
{
public
PacketVehicle
Spawn
Rsp
(
Player
player
,
int
vehicleId
,
int
pointId
,
Position
pos
,
Position
rot
)
{
public
Packet
Create
VehicleRsp
(
Player
player
,
int
vehicleId
,
int
pointId
,
Position
pos
,
Position
rot
)
{
super
(
PacketOpcodes
.
Vehicle
Spawn
Rsp
);
super
(
PacketOpcodes
.
Create
VehicleRsp
);
Vehicle
Spawn
Rsp
.
Builder
proto
=
Vehicle
Spawn
Rsp
.
newBuilder
();
Create
VehicleRsp
.
Builder
proto
=
Create
VehicleRsp
.
newBuilder
();
// Eject vehicle members and Kill previous vehicles if there are any
// Eject vehicle members and Kill previous vehicles if there are any
List
<
GameEntity
>
previousVehicles
=
player
.
getScene
().
getEntities
().
values
().
stream
()
List
<
GameEntity
>
previousVehicles
=
player
.
getScene
().
getEntities
().
values
().
stream
()
...
...
src/main/java/emu/grasscutter/server/packet/send/Packet
SceneUnlockInfo
Notify.java
→
src/main/java/emu/grasscutter/server/packet/send/Packet
PlayerWorldSceneInfoList
Notify.java
View file @
81183db1
...
@@ -2,15 +2,15 @@ package emu.grasscutter.server.packet.send;
...
@@ -2,15 +2,15 @@ package emu.grasscutter.server.packet.send;
import
emu.grasscutter.net.packet.BasePacket
;
import
emu.grasscutter.net.packet.BasePacket
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.
SceneUnlockInfoNotifyOuterClass.SceneUnlockInfo
Notify
;
import
emu.grasscutter.net.proto.
PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoList
Notify
;
import
emu.grasscutter.net.proto.SceneUnlockInfoOuterClass.SceneUnlockInfo
;
import
emu.grasscutter.net.proto.SceneUnlockInfoOuterClass.SceneUnlockInfo
;
public
class
Packet
SceneUnlockInfo
Notify
extends
BasePacket
{
public
class
Packet
PlayerWorldSceneInfoList
Notify
extends
BasePacket
{
public
Packet
SceneUnlockInfo
Notify
()
{
public
Packet
PlayerWorldSceneInfoList
Notify
()
{
super
(
PacketOpcodes
.
SceneUnlockInfo
Notify
);
// Rename opcode later
super
(
PacketOpcodes
.
PlayerWorldSceneInfoList
Notify
);
// Rename opcode later
SceneUnlockInfoNotify
proto
=
SceneUnlockInfo
Notify
.
newBuilder
()
PlayerWorldSceneInfoListNotify
proto
=
PlayerWorldSceneInfoList
Notify
.
newBuilder
()
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
1
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
1
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
3
).
addSceneTagIdList
(
102
).
addSceneTagIdList
(
113
).
addSceneTagIdList
(
117
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
3
).
addSceneTagIdList
(
102
).
addSceneTagIdList
(
113
).
addSceneTagIdList
(
117
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
4
).
addSceneTagIdList
(
106
).
addSceneTagIdList
(
109
))
.
addUnlockInfos
(
SceneUnlockInfo
.
newBuilder
().
setSceneId
(
4
).
addSceneTagIdList
(
106
).
addSceneTagIdList
(
109
))
...
...
src/main/java/emu/grasscutter/utils/ConfigContainer.java
View file @
81183db1
...
@@ -136,8 +136,9 @@ public class ConfigContainer {
...
@@ -136,8 +136,9 @@ public class ConfigContainer {
public
int
bindPort
=
22102
;
public
int
bindPort
=
22102
;
/* This is the port used in the default region. */
/* This is the port used in the default region. */
public
int
accessPort
=
0
;
public
int
accessPort
=
0
;
public
boolean
enableScriptInBigWorld
=
false
;
public
boolean
enableScriptInBigWorld
=
false
;
public
boolean
enableConsole
=
true
;
public
GameOptions
gameOptions
=
new
GameOptions
();
public
GameOptions
gameOptions
=
new
GameOptions
();
public
JoinOptions
joinOptions
=
new
JoinOptions
();
public
JoinOptions
joinOptions
=
new
JoinOptions
();
public
ConsoleAccount
serverAccount
=
new
ConsoleAccount
();
public
ConsoleAccount
serverAccount
=
new
ConsoleAccount
();
...
...
src/main/java/emu/grasscutter/utils/Crypto.java
View file @
81183db1
...
@@ -20,11 +20,11 @@ public final class Crypto {
...
@@ -20,11 +20,11 @@ public final class Crypto {
public
static
byte
[]
ENCRYPT_SEED_BUFFER
=
new
byte
[
0
];
public
static
byte
[]
ENCRYPT_SEED_BUFFER
=
new
byte
[
0
];
public
static
void
loadKeys
()
{
public
static
void
loadKeys
()
{
DISPATCH_KEY
=
FileUtils
.
read
(
KEY
S_FOLDER
+
"/
dispatchKey.bin"
);
DISPATCH_KEY
=
FileUtils
.
read
(
KEY
(
"
dispatchKey.bin"
)
)
;
DISPATCH_SEED
=
FileUtils
.
read
(
KEY
S_FOLDER
+
"/
dispatchSeed.bin"
);
DISPATCH_SEED
=
FileUtils
.
read
(
KEY
(
"
dispatchSeed.bin"
)
)
;
ENCRYPT_KEY
=
FileUtils
.
read
(
KEY
S_FOLDER
+
"/
secretKey.bin"
);
ENCRYPT_KEY
=
FileUtils
.
read
(
KEY
(
"
secretKey.bin"
)
)
;
ENCRYPT_SEED_BUFFER
=
FileUtils
.
read
(
KEY
S_FOLDER
+
"/
secretKeyBuffer.bin"
);
ENCRYPT_SEED_BUFFER
=
FileUtils
.
read
(
KEY
(
"
secretKeyBuffer.bin"
)
)
;
}
}
public
static
void
xor
(
byte
[]
packet
,
byte
[]
key
)
{
public
static
void
xor
(
byte
[]
packet
,
byte
[]
key
)
{
...
@@ -40,7 +40,7 @@ public final class Crypto {
...
@@ -40,7 +40,7 @@ public final class Crypto {
public
static
void
extractSecretKeyBuffer
(
byte
[]
data
)
{
public
static
void
extractSecretKeyBuffer
(
byte
[]
data
)
{
try
{
try
{
GetPlayerTokenRsp
p
=
GetPlayerTokenRsp
.
parseFrom
(
data
);
GetPlayerTokenRsp
p
=
GetPlayerTokenRsp
.
parseFrom
(
data
);
FileUtils
.
write
(
KEY
S_FOLDER
+
"/secretKeyBuffer.bin"
,
p
.
getSecretKeyBytes
().
toByteArray
());
FileUtils
.
write
(
KEY
(
"/secretKeyBuffer.bin"
)
,
p
.
getSecretKeyBytes
().
toByteArray
());
Grasscutter
.
getLogger
().
info
(
"Secret Key: "
+
p
.
getSecretKey
());
Grasscutter
.
getLogger
().
info
(
"Secret Key: "
+
p
.
getSecretKey
());
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
...
@@ -50,7 +50,7 @@ public final class Crypto {
...
@@ -50,7 +50,7 @@ public final class Crypto {
public
static
void
extractDispatchSeed
(
String
data
)
{
public
static
void
extractDispatchSeed
(
String
data
)
{
try
{
try
{
QueryCurrRegionHttpRsp
p
=
QueryCurrRegionHttpRsp
.
parseFrom
(
Base64
.
getDecoder
().
decode
(
data
));
QueryCurrRegionHttpRsp
p
=
QueryCurrRegionHttpRsp
.
parseFrom
(
Base64
.
getDecoder
().
decode
(
data
));
FileUtils
.
write
(
KEY
S_FOLDER
+
"/dispatchSeed.bin"
,
p
.
getRegionInfo
().
getSecretKey
().
toByteArray
());
FileUtils
.
write
(
KEY
(
"/dispatchSeed.bin"
)
,
p
.
getRegionInfo
().
getSecretKey
().
toByteArray
());
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
Grasscutter
.
getLogger
().
error
(
"Crypto error."
,
e
);
}
}
...
...
src/main/resources/languages/en-US.json
View file @
81183db1
...
@@ -181,10 +181,6 @@
...
@@ -181,10 +181,6 @@
"success"
:
"All characters have been healed."
,
"success"
:
"All characters have been healed."
,
"description"
:
"Heal all characters in your current team."
"description"
:
"Heal all characters in your current team."
},
},
"join"
:
{
"usage"
:
"Usage: join [AvatarIDs] such as
\"
join 10000038 10000039
\"
"
,
"description"
:
"force join avatar into your team"
},
"kick"
:
{
"kick"
:
{
"player_kick_player"
:
"Player [%s:%s] has kicked player [%s:%s]"
,
"player_kick_player"
:
"Player [%s:%s] has kicked player [%s:%s]"
,
"server_kick_player"
:
"Kicking player [%s:%s]"
,
"server_kick_player"
:
"Kicking player [%s:%s]"
,
...
@@ -237,11 +233,6 @@
...
@@ -237,11 +233,6 @@
"reload_done"
:
"Reload complete."
,
"reload_done"
:
"Reload complete."
,
"description"
:
"Reload server config"
"description"
:
"Reload server config"
},
},
"remove"
:
{
"usage"
:
"Usage: remove [indexOfYourTeam] index start from 1"
,
"invalid_index"
:
"The index number is illegal. It starts from 1 and the maximum value is the number of roles in the team"
,
"description"
:
"force remove avatar into your team. Such as `remove 1 2`."
},
"resetConst"
:
{
"resetConst"
:
{
"reset_all"
:
"Reset all avatars' constellations."
,
"reset_all"
:
"Reset all avatars' constellations."
,
"success"
:
"Constellations for %s have been reset. Please relog to see changes."
,
"success"
:
"Constellations for %s have been reset. Please relog to see changes."
,
...
@@ -331,6 +322,24 @@
...
@@ -331,6 +322,24 @@
"q_skill_id"
:
"Q skill ID %s."
,
"q_skill_id"
:
"Q skill ID %s."
,
"description"
:
"Set talent level for your current active character"
"description"
:
"Set talent level for your current active character"
},
},
"team"
:
{
"usage"
:
"Usage: team <add|remove|set> [avatarId,...] [index|first|last|index-index,...]"
,
"invalid_usage"
:
"invalid usage"
,
"add_usage"
:
"usage(add): team add <avatarId,...> [index]"
,
"invalid_index"
:
"index is invalid"
,
"add_too_much"
:
"server is only allow you to have at most %d avatar(s) in your team"
,
"failed_to_add_avatar"
:
"failed to add avatar by id: %s"
,
"remove_usage"
:
"usage(remove): team remove <index|first|last|index-index,...>"
,
"failed_parse_index"
:
"failed to parse index: %s"
,
"remove_too_much"
:
"you can't remove so many avatars, your team list will be empty for this"
,
"ignore_index"
:
"ignored index(es): %s"
,
"set_usage"
:
"usage(set): team set <index> <avatarId>"
,
"index_out_of_range"
:
"index your specified is out of range"
,
"failed_parse_avatar_id"
:
"failed to parse avatar id: %s"
,
"avatar_already_in_team"
:
"avatar is already in team"
,
"avatar_not_found"
:
"avatar not found: %d"
,
"description"
:
"modify your team manually"
},
"teleportAll"
:
{
"teleportAll"
:
{
"success"
:
"Summoned all players to your location."
,
"success"
:
"Summoned all players to your location."
,
"error"
:
"You only can use this command in MP mode."
,
"error"
:
"You only can use this command in MP mode."
,
...
...
src/main/resources/languages/zh-CN.json
View file @
81183db1
...
@@ -180,10 +180,6 @@
...
@@ -180,10 +180,6 @@
"success"
:
"已治疗所有角色。"
,
"success"
:
"已治疗所有角色。"
,
"description"
:
"治疗当前队伍的角色"
"description"
:
"治疗当前队伍的角色"
},
},
"join"
:
{
"usage"
:
"用法:join <角色IDs> 例如
\"
join 10000038 10000039
\"
空格分开"
,
"description"
:
"强制将角色加入到当前队伍中"
},
"kick"
:
{
"kick"
:
{
"player_kick_player"
:
"玩家 [%s:%s] 已将 [%s:%s] 踢出。"
,
"player_kick_player"
:
"玩家 [%s:%s] 已将 [%s:%s] 踢出。"
,
"server_kick_player"
:
"正在踢出玩家 [%s:%s]..."
,
"server_kick_player"
:
"正在踢出玩家 [%s:%s]..."
,
...
@@ -236,11 +232,6 @@
...
@@ -236,11 +232,6 @@
"reload_done"
:
"重载完成。"
,
"reload_done"
:
"重载完成。"
,
"description"
:
"重载配置文件和数据"
"description"
:
"重载配置文件和数据"
},
},
"remove"
:
{
"usage"
:
"用法: remove [多个角色在队伍中的序号] 序号从1开始"
,
"invalid_index"
:
"序号不合法,从1开始,最大值为队内角色数量"
,
"description"
:
"强制将某个角色从当前队伍中移除。例如`remove 1 2`表示将1号和2号角色从队伍中移除"
},
"resetConst"
:
{
"resetConst"
:
{
"reset_all"
:
"重置所有角色的命座。"
,
"reset_all"
:
"重置所有角色的命座。"
,
"success"
:
"已重置 %s 的命座,重新登录后生效。"
,
"success"
:
"已重置 %s 的命座,重新登录后生效。"
,
...
@@ -330,6 +321,24 @@
...
@@ -330,6 +321,24 @@
"q_skill_id"
:
"元素爆发ID %s。"
,
"q_skill_id"
:
"元素爆发ID %s。"
,
"description"
:
"设置当前角色的天赋等级"
"description"
:
"设置当前角色的天赋等级"
},
},
"team"
:
{
"usage"
:
"用法: team <add|remove|set> [avatarId,...] [index|first|last|index-index,...]"
,
"invalid_usage"
:
"无效用法"
,
"add_usage"
:
"用法(add): team add <avatarId,...> [index]"
,
"invalid_index"
:
"无效索引"
,
"add_too_much"
:
"服务端仅允许你队伍里至多有%d名角色"
,
"failed_to_add_avatar"
:
"无法根据id %s 添加角色"
,
"remove_usage"
:
"用法(remove): team remove <index|first|last|index-index,...>"
,
"failed_parse_index"
:
"无法解析索引: %s"
,
"remove_too_much"
:
"你不能删除那么多角色,你的队伍列表将会变空"
,
"ignore_index"
:
"忽略的索引列表: %s"
,
"set_usage"
:
"用法(set): team set <index> <avatarId>"
,
"index_out_of_range"
:
"你指定的索引超出了范围"
,
"failed_parse_avatar_id"
:
"无法解析的角色id: %s"
,
"avatar_already_in_team"
:
"角色已经在你的队伍中了"
,
"avatar_not_found"
:
"无法找到该角色: %d"
,
"description"
:
"手动修改你的队伍"
},
"teleportAll"
:
{
"teleportAll"
:
{
"success"
:
"已将所有玩家传送到你的位置。"
,
"success"
:
"已将所有玩家传送到你的位置。"
,
"error"
:
"你只能在多人游戏状态下执行此命令。"
,
"error"
:
"你只能在多人游戏状态下执行此命令。"
,
...
...
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