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
39e8f810
Commit
39e8f810
authored
May 07, 2022
by
Akka
Committed by
GitHub
May 07, 2022
Browse files
Merge pull request #5 from Grasscutters/development
Development
parents
6148ee87
dc3c7447
Changes
6
Show whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/Grasscutter.java
View file @
39e8f810
...
...
@@ -77,7 +77,7 @@ public final class Grasscutter {
Tools
.
createGmHandbook
();
exitEarly
=
true
;
}
case
"-gachamap"
->
{
Tools
.
createGachaMapping
(
"
.
/gacha
-
mapping.js"
);
exitEarly
=
true
;
Tools
.
createGachaMapping
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"/gacha
_
mapping
s
.js"
);
exitEarly
=
true
;
}
}
}
...
...
src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java
View file @
39e8f810
...
...
@@ -24,7 +24,7 @@ public class MovementManager {
public
HashMap
<
String
,
HashSet
<
MotionState
>>
MotionStatesCategorized
=
new
HashMap
<>();
private
enum
Consumption
{
private
enum
Consumption
Type
{
None
(
0
),
// consume
...
...
@@ -37,6 +37,7 @@ public class MovementManager {
SWIM_DASH_START
(-
200
),
SWIM_DASH
(-
200
),
SWIMMING
(-
80
),
FIGHT
(
0
),
// restore
STANDBY
(
500
),
...
...
@@ -46,11 +47,22 @@ public class MovementManager {
POWERED_FLY
(
500
);
public
final
int
amount
;
Consumption
(
int
amount
)
{
Consumption
Type
(
int
amount
)
{
this
.
amount
=
amount
;
}
}
private
class
Consumption
{
public
ConsumptionType
consumptionType
;
public
int
amount
;
public
Consumption
(
ConsumptionType
ct
,
int
a
)
{
consumptionType
=
ct
;
amount
=
a
;
}
public
Consumption
(
ConsumptionType
ct
)
{
this
(
ct
,
ct
.
amount
);
}
}
private
MotionState
previousState
=
MotionState
.
MOTION_STANDBY
;
private
MotionState
currentState
=
MotionState
.
MOTION_STANDBY
;
...
...
@@ -64,8 +76,9 @@ public class MovementManager {
private
Timer
movementManagerTickTimer
;
private
GameSession
cachedSession
=
null
;
private
GameEntity
cachedEntity
=
null
;
private
int
staminaRecoverDelay
=
0
;
private
int
skillCaster
=
0
;
private
int
skillCasting
=
0
;
public
MovementManager
(
Player
player
)
{
previousCoordinates
.
add
(
new
Position
(
0
,
0
,
0
));
...
...
@@ -114,6 +127,12 @@ public class MovementManager {
MotionState
.
MOTION_WALK
,
MotionState
.
MOTION_DANGER_WALK
)));
MotionStatesCategorized
.
put
(
"FIGHT"
,
new
HashSet
<>(
Arrays
.
asList
(
MotionState
.
MOTION_FIGHT
)));
}
public
void
handle
(
GameSession
session
,
EntityMoveInfoOuterClass
.
EntityMoveInfo
moveInfo
,
GameEntity
entity
)
{
...
...
@@ -134,11 +153,12 @@ public class MovementManager {
currentCoordinates
=
newPos
;
}
currentState
=
motionInfo
.
getState
();
Grasscutter
.
getLogger
().
debug
(
""
+
currentState
);
Grasscutter
.
getLogger
().
debug
(
""
+
currentState
+
"\t"
+
(
moveInfo
.
getIsReliable
()
?
"reliable"
:
""
)
);
handleFallOnGround
(
motionInfo
);
}
public
void
resetTimer
()
{
Grasscutter
.
getLogger
().
debug
(
"MovementManager ticker stopped"
);
movementManagerTickTimer
.
cancel
();
movementManagerTickTimer
=
null
;
}
...
...
@@ -167,8 +187,6 @@ public class MovementManager {
return
player
.
getProperty
(
PlayerProperty
.
PROP_MAX_STAMINA
);
}
// Returns new stamina
public
int
updateStamina
(
GameSession
session
,
int
amount
)
{
int
currentStamina
=
session
.
getPlayer
().
getProperty
(
PlayerProperty
.
PROP_CUR_PERSIST_STAMINA
);
...
...
@@ -184,6 +202,7 @@ public class MovementManager {
newStamina
=
playerMaxStamina
;
}
session
.
getPlayer
().
setProperty
(
PlayerProperty
.
PROP_CUR_PERSIST_STAMINA
,
newStamina
);
session
.
send
(
new
PacketPlayerPropNotify
(
player
,
PlayerProperty
.
PROP_CUR_PERSIST_STAMINA
));
return
newStamina
;
}
...
...
@@ -269,101 +288,155 @@ public class MovementManager {
boolean
moving
=
isPlayerMoving
();
if
(
moving
||
(
getCurrentStamina
()
<
getMaximumStamina
()))
{
// Grasscutter.getLogger().debug("Player moving: " + moving + ", stamina full: " + (getCurrentStamina() >= getMaximumStamina()) + ", recalculate stamina");
Consumption
consumption
=
Consumption
.
None
;
Consumption
consumption
=
new
Consumption
(
ConsumptionType
.
None
)
;
// TODO: refactor these conditions.
if
(
MotionStatesCategorized
.
get
(
"CLIMB"
).
contains
(
currentState
))
{
consumption
=
getClimbConsumption
();
}
else
if
(
MotionStatesCategorized
.
get
(
"SWIM"
).
contains
((
currentState
)))
{
consumption
=
getSwimConsumptions
();
}
else
if
(
MotionStatesCategorized
.
get
(
"RUN"
).
contains
(
currentState
))
{
consumption
=
getRunWalkDashConsumption
();
}
else
if
(
MotionStatesCategorized
.
get
(
"FLY"
).
contains
(
currentState
))
{
consumption
=
getFlyConsumption
();
}
else
if
(
MotionStatesCategorized
.
get
(
"STANDBY"
).
contains
(
currentState
))
{
consumption
=
getStandConsumption
();
}
else
if
(
MotionStatesCategorized
.
get
(
"FIGHT"
).
contains
(
currentState
))
{
consumption
=
getFightConsumption
();
}
// delay 2 seconds before start recovering - as official server does.
if
(
cachedSession
!=
null
)
{
if
(
consumption
.
amount
<
0
)
{
staminaRecoverDelay
=
0
;
}
if
(
consumption
.
amount
>
0
&&
consumption
.
consumptionType
!=
ConsumptionType
.
POWERED_FLY
)
{
if
(
staminaRecoverDelay
<
10
)
{
staminaRecoverDelay
++;
consumption
=
new
Consumption
(
ConsumptionType
.
None
);
}
}
// Grasscutter.getLogger().debug(getCurrentStamina() + "/" + getMaximumStamina() + "\t" + currentState + "\t" + "isMoving: " + isPlayerMoving() + "\t(" + consumption.consumptionType + "," + consumption.amount + ")");
updateStamina
(
cachedSession
,
consumption
.
amount
);
}
// tick triggered
handleDrowning
();
}
}
previousState
=
currentState
;
previousCoordinates
=
new
Position
(
currentCoordinates
.
getX
(),
currentCoordinates
.
getY
(),
currentCoordinates
.
getZ
());;
}
}
private
Consumption
getClimbConsumption
()
{
Consumption
consumption
=
new
Consumption
(
ConsumptionType
.
None
);
if
(
currentState
==
MotionState
.
MOTION_CLIMB
)
{
// CLIMB
consumption
=
new
Consumption
(
ConsumptionType
.
CLIMBING
);
if
(
previousState
!=
MotionState
.
MOTION_CLIMB
&&
previousState
!=
MotionState
.
MOTION_CLIMB_JUMP
)
{
consumption
=
Consumption
.
CLIMB_START
;
}
else
{
consumption
=
Consumption
.
CLIMBING
;
consumption
=
new
Consumption
(
ConsumptionType
.
CLIMB_START
);
}
if
(!
isPlayerMoving
())
{
consumption
=
new
Consumption
(
ConsumptionType
.
None
);
}
}
if
(
currentState
==
MotionState
.
MOTION_CLIMB_JUMP
)
{
if
(
previousState
!=
MotionState
.
MOTION_CLIMB_JUMP
)
{
consumption
=
Consumption
.
CLIMB_JUMP
;
}
consumption
=
new
Consumption
(
ConsumptionType
.
CLIMB_JUMP
);
}
if
(
currentState
==
MotionState
.
MOTION_JUMP
)
{
if
(
previousState
==
MotionState
.
MOTION_CLIMB
)
{
consumption
=
Consumption
.
CLIMB_JUMP
;
}
return
consumption
;
}
}
else
if
(
MotionStatesCategorized
.
get
(
"SWIM"
).
contains
((
currentState
)))
{
// SWIM
private
Consumption
getSwimConsumptions
()
{
Consumption
consumption
=
new
Consumption
(
ConsumptionType
.
None
);
if
(
currentState
==
MotionState
.
MOTION_SWIM_MOVE
)
{
consumption
=
Consumption
.
SWIMMING
;
consumption
=
new
Consumption
(
ConsumptionType
.
SWIMMING
)
;
}
if
(
currentState
==
MotionState
.
MOTION_SWIM_DASH
)
{
if
(
previousState
!=
MotionState
.
MOTION_SWIM_DASH
)
{
consumption
=
Consumption
.
SWIM_DASH_START
;
}
else
{
consumption
=
Consumption
.
SWIM_DASH
;
consumption
=
new
Consumption
(
ConsumptionType
.
SWIM_DASH_START
);
if
(
previousState
==
MotionState
.
MOTION_SWIM_DASH
)
{
consumption
=
new
Consumption
(
ConsumptionType
.
SWIM_DASH
);
}
}
}
else
if
(
MotionStatesCategorized
.
get
(
"RUN"
).
contains
(
currentState
))
{
// RUN, DASH and WALK
// DASH
return
consumption
;
}
private
Consumption
getRunWalkDashConsumption
()
{
Consumption
consumption
=
new
Consumption
(
ConsumptionType
.
None
);
if
(
currentState
==
MotionState
.
MOTION_DASH_BEFORE_SHAKE
)
{
consumption
=
Consumption
.
DASH
;
consumption
=
new
Consumption
(
ConsumptionType
.
DASH
)
;
if
(
previousState
==
MotionState
.
MOTION_DASH_BEFORE_SHAKE
)
{
// only charge once
consumption
=
Consumption
.
SPRINT
;
consumption
=
new
Consumption
(
ConsumptionType
.
SPRINT
)
;
}
}
if
(
currentState
==
MotionState
.
MOTION_DASH
)
{
consumption
=
Consumption
.
SPRINT
;
consumption
=
new
Consumption
(
ConsumptionType
.
SPRINT
)
;
}
// RUN
if
(
currentState
==
MotionState
.
MOTION_RUN
)
{
consumption
=
Consumption
.
RUN
;
consumption
=
new
Consumption
(
ConsumptionType
.
RUN
)
;
}
// WALK
if
(
currentState
==
MotionState
.
MOTION_WALK
)
{
consumption
=
Consumption
.
WALK
;
consumption
=
new
Consumption
(
ConsumptionType
.
WALK
)
;
}
}
else
if
(
MotionStatesCategorized
.
get
(
"FLY"
).
contains
(
currentState
))
{
// FLY
consumption
=
Consumption
.
FLY
;
// POWERED_FLY, e.g. wind tunnel
if
(
currentState
==
MotionState
.
MOTION_POWERED_FLY
)
{
consumption
=
Consumption
.
POWERED_FLY
;
return
consumption
;
}
}
else
if
(
MotionStatesCategorized
.
get
(
"STANDBY"
).
contains
(
currentState
))
{
// STAND
if
(
currentState
==
MotionState
.
MOTION_STANDBY
)
{
consumption
=
Consumption
.
STANDBY
;
private
Consumption
getFlyConsumption
()
{
Consumption
consumption
=
new
Consumption
(
ConsumptionType
.
FLY
);
HashMap
<
Integer
,
Float
>
glidingCostReduction
=
new
HashMap
<>()
{{
put
(
212301
,
0.8f
);
// Amber
put
(
222301
,
0.8f
);
// Venti
}};
float
reduction
=
1
;
for
(
EntityAvatar
entity:
cachedSession
.
getPlayer
().
getTeamManager
().
getActiveTeam
())
{
for
(
int
skillId:
entity
.
getAvatar
().
getProudSkillList
())
{
if
(
glidingCostReduction
.
containsKey
(
skillId
))
{
reduction
=
glidingCostReduction
.
get
(
skillId
);
}
if
(
currentState
==
MotionState
.
MOTION_STANDBY_MOVE
)
{
consumption
=
Consumption
.
STANDBY_MOVE
;
}
}
consumption
.
amount
*=
reduction
;
// tick triggered
handleDrowning
();
if
(
cachedSession
!=
null
)
{
if
(
consumption
.
amount
<
0
)
{
staminaRecoverDelay
=
0
;
}
if
(
consumption
.
amount
>
0
)
{
if
(
staminaRecoverDelay
<
10
)
{
staminaRecoverDelay
++;
consumption
=
Consumption
.
None
;
// POWERED_FLY, e.g. wind tunnel
if
(
currentState
==
MotionState
.
MOTION_POWERED_FLY
)
{
consumption
=
new
Consumption
(
ConsumptionType
.
POWERED_FLY
);
}
return
consumption
;
}
int
newStamina
=
updateStamina
(
cachedSession
,
consumption
.
amount
);
cachedSession
.
send
(
new
PacketPlayerPropNotify
(
player
,
PlayerProperty
.
PROP_CUR_PERSIST_STAMINA
));
Grasscutter
.
getLogger
().
debug
(
player
.
getProperty
(
PlayerProperty
.
PROP_CUR_PERSIST_STAMINA
)
+
"/"
+
player
.
getProperty
(
PlayerProperty
.
PROP_MAX_STAMINA
)
+
"\t"
+
currentState
+
"\t"
+
"isMoving: "
+
isPlayerMoving
()
+
"\t"
+
consumption
+
"("
+
consumption
.
amount
+
")"
);
private
Consumption
getStandConsumption
()
{
Consumption
consumption
=
new
Consumption
(
ConsumptionType
.
None
);
if
(
currentState
==
MotionState
.
MOTION_STANDBY
)
{
consumption
=
new
Consumption
(
ConsumptionType
.
STANDBY
);
}
if
(
currentState
==
MotionState
.
MOTION_STANDBY_MOVE
)
{
consumption
=
new
Consumption
(
ConsumptionType
.
STANDBY_MOVE
);
}
return
consumption
;
}
previousState
=
currentState
;
previousCoordinates
=
new
Position
(
currentCoordinates
.
getX
(),
currentCoordinates
.
getY
(),
currentCoordinates
.
getZ
());;
private
Consumption
getFightConsumption
()
{
Consumption
consumption
=
new
Consumption
(
ConsumptionType
.
None
);
HashMap
<
Integer
,
Integer
>
fightingCost
=
new
HashMap
<>()
{{
put
(
10013
,
-
1000
);
// Kamisato Ayaka
put
(
10413
,
-
1000
);
// Mona
}};
if
(
fightingCost
.
containsKey
(
skillCasting
))
{
consumption
=
new
Consumption
(
ConsumptionType
.
FIGHT
,
fightingCost
.
get
(
skillCasting
));
// only handle once, so reset.
skillCasting
=
0
;
skillCaster
=
0
;
}
return
consumption
;
}
public
void
notifySkill
(
int
caster
,
int
skillId
)
{
skillCaster
=
caster
;
skillCasting
=
skillId
;
}
}
src/main/java/emu/grasscutter/game/player/Player.java
View file @
39e8f810
...
...
@@ -1151,8 +1151,11 @@ public class Player {
}
public
void
onLogout
()
{
// stop stamina calculation
getMovementManager
().
resetTimer
();
// force to leave the dungeon
if
(
getScene
().
getSceneType
()
==
SceneType
.
SCENE_DUNGEON
){
if
(
getScene
().
getSceneType
()
==
SceneType
.
SCENE_DUNGEON
)
{
this
.
getServer
().
getDungeonManager
().
exitDungeon
(
this
);
}
// Leave world
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java
View file @
39e8f810
...
...
@@ -16,11 +16,9 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler {
// TODO: Will be used for deducting stamina for charged skills.
int
caster
=
notify
.
getCasterId
();
int
skill
=
notify
.
getSkillId
();
int
skill
Id
=
notify
.
getSkillId
();
// Grasscutter.getLogger().warn(caster + "\t" + skill);
// session.getPlayer().getScene().broadcastPacket(new PacketEvtAvatarStandUpNotify(notify));
session
.
getPlayer
().
getMovementManager
().
notifySkill
(
caster
,
skillId
);
}
}
src/main/java/emu/grasscutter/tools/Tools.java
View file @
39e8f810
...
...
@@ -64,25 +64,26 @@ public final class Tools {
if
(
availableLangList
.
size
()
==
1
)
{
return
availableLangList
.
get
(
0
).
toUpperCase
();
}
System
.
out
.
println
(
"The following languages mappings are available, please select one: [default: EN]"
);
String
groupedLangList
=
"> "
;
String
stagedMessage
=
""
;
stagedMessage
+=
"The following languages mappings are available, please select one: [default: EN]\n"
;
String
groupedLangList
=
">\t"
;
int
groupedLangCount
=
0
;
String
input
=
""
;
for
(
String
availableLanguage:
availableLangList
){
groupedLangCount
++;
groupedLangList
=
groupedLangList
+
""
+
availableLanguage
+
"\t"
;
if
(
groupedLangCount
==
6
)
{
System
.
out
.
println
(
groupedLangList
)
;
stagedMessage
+=
groupedLangList
+
"\n"
;
groupedLangCount
=
0
;
groupedLangList
=
">
"
;
groupedLangList
=
">
\t
"
;
}
}
if
(
groupedLangCount
>
0
)
{
System
.
out
.
println
(
groupedLangList
)
;
stagedMessage
+=
groupedLangList
+
"\n"
;
}
System
.
out
.
print
(
"\nYour choice:[EN] "
)
;
stagedMessage
+=
"\nYour choice:[EN] "
;
input
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
)).
readLine
(
);
input
=
Grasscutter
.
getConsole
().
readLine
(
stagedMessage
);
if
(
availableLangList
.
contains
(
input
.
toLowerCase
()))
{
return
input
.
toUpperCase
();
}
...
...
@@ -249,6 +250,6 @@ final class ToolsWithLanguageOption {
writer
.
println
(
"}\n}"
);
}
Grasscutter
.
getLogger
().
info
(
"Mappings generated!"
);
Grasscutter
.
getLogger
().
info
(
"Mappings generated
to "
+
location
+
"
!"
);
}
}
src/main/resources/languages/zh-CN.json
0 → 100644
View file @
39e8f810
{
"messages"
:
{
"game"
:
{
"port_bind"
:
"游戏服务器已在端口 %s 上启动"
,
"connect"
:
"客户端已连接至 %s"
,
"disconnect"
:
"客户端 %s 已断开连接"
,
"game_update_error"
:
"游戏更新时发生错误"
,
"command_error"
:
"命令发生错误:"
},
"dispatch"
:
{
"port_bind"
:
"[Dispatch] 服务器已在端口 %s 上启动"
,
"request"
:
"[Dispatch] 客户端 %s 请求: %s %s"
,
"keystore"
:
{
"general_error"
:
"[Dispatch] 加载 keystore 文件时发生错误!"
,
"password_error"
:
"[Dispatch] 加载 keystore 失败。正在尝试使用预设的 keystore 密码..."
,
"no_keystore_error"
:
"[Dispatch] 未找到 SSL 证书!已降级到 HTTP 服务器"
,
"default_password"
:
"[Dispatch] 默认的 keystore 密码加载成功。请考虑将 config.json 的默认密码设置为 123456"
},
"no_commands_error"
:
"此命令不适用于 Dispatch-only 模式"
,
"unhandled_request_error"
:
"[Dispatch] 潜在的未处理请求 %s 请求:%s"
,
"account"
:
{
"login_attempt"
:
"[Dispatch] 客户端 %s 正在尝试登录"
,
"login_success"
:
"[Dispatch] 客户端 %s 已登录,UID为 %s"
,
"login_token_attempt"
:
"[Dispatch] 客户端 %s 正在尝试使用令牌登录"
,
"login_token_error"
:
"[Dispatch] 客户端 %s 使用令牌登录失败"
,
"login_token_success"
:
"[Dispatch] 客户端 %s 已通过令牌登录,UID为 %s"
,
"combo_token_success"
:
"[Dispatch] 客户端 %s 交换令牌成功"
,
"combo_token_error"
:
"[Dispatch] 客户端 %s 交换令牌失败"
,
"account_login_create_success"
:
"[Dispatch] 客户端 %s 登录失败: 已注册UID为 %s 的账号"
,
"account_login_create_error"
:
"[Dispatch] 客户端 %s 登录失败:账号创建失败。"
,
"account_login_exist_error"
:
"[Dispatch] 客户端 %s 登录失败:账号不存在"
,
"account_cache_error"
:
"游戏账号缓存信息错误"
,
"session_key_error"
:
"交换秘钥不符。"
,
"username_error"
:
"未找到此用户名。"
,
"username_create_error"
:
"未找到用户名,建立连接失败。"
}
},
"status"
:
{
"free_software"
:
"Grasscutter 是免费开源软件。如果你是付费购买的,那已经被骗了。Github:https://github.com/Grasscutters/Grasscutter"
,
"starting"
:
"正在启动 Grasscutter..."
,
"shutdown"
:
"正在关闭..."
,
"done"
:
"加載完成!输入
\"
help
\"
查看命令列表"
,
"error"
:
"发生了一个错误。"
,
"welcome"
:
"欢迎使用 Grasscutter"
,
"run_mode_error"
:
"无效的服务器运行模式: %s。"
,
"run_mode_help"
:
"服务器运行模式必须为 HYBRID、DISPATCH_ONLY 或 GAME_ONLY。Grasscutter 启动失败..."
,
"create_resources"
:
"正在创建 resources 目录..."
,
"resources_error"
:
"请将 BinOutput 和 ExcelBinOutput 复制到 resources 目录。"
}
},
"commands"
:
{
"generic"
:
{
"not_specified"
:
"没有指定命令。"
,
"unknown_command"
:
"未知的命令:%s"
,
"permission_error"
:
"您没有执行此命令的权限。"
,
"console_execute_error"
:
"此命令只能在服务器控制台执行。"
,
"player_execute_error"
:
"此命令只能在游戏内执行。"
,
"command_exist_error"
:
"找不到命令。"
,
"invalid"
:
{
"amount"
:
"无效的 数量."
,
"artifactId"
:
"无效的圣遗物ID。"
,
"avatarId"
:
"无效的角色ID。"
,
"avatarLevel"
:
"无效的角色等級。"
,
"entityId"
:
"无效的实体ID。"
,
"itemId"
:
"无效的物品ID。"
,
"itemLevel"
:
"无效的物品等級。"
,
"itemRefinement"
:
"无效的物品精炼等级。"
,
"playerId"
:
"无效的玩家ID。"
,
"uid"
:
"无效的UID。"
}
},
"execution"
:
{
"uid_error"
:
"无效的UID。"
,
"player_exist_error"
:
"用户不存在。"
,
"player_offline_error"
:
"玩家已离线。"
,
"item_id_error"
:
"无效的物品ID。."
,
"item_player_exist_error"
:
"无效的物品/玩家UID。"
,
"entity_id_error"
:
"无效的实体ID。"
,
"player_exist_offline_error"
:
"玩家不存在或已离线。"
,
"argument_error"
:
"无效的参数。"
,
"clear_target"
:
"目标已清除."
,
"set_target"
:
"随后的的命令都会以@%s为预设。"
,
"need_target"
:
"此命令需要一个目标 UID。添加 <@UID> 参数或使用 /target @UID 来设定持久目标。"
},
"status"
:
{
"enabled"
:
"已启用"
,
"disabled"
:
"未启用"
,
"help"
:
"帮助"
,
"success"
:
"成功"
},
"account"
:
{
"modify"
:
"修改使用者账号"
,
"invalid"
:
"无效的UID。"
,
"exists"
:
"账号已存在。"
,
"create"
:
"已建立账号,UID 为 %s 。"
,
"delete"
:
"账号已刪除。"
,
"no_account"
:
"账号不存在。"
,
"command_usage"
:
"用法:account <create|delete> <username> [uid]"
},
"broadcast"
:
{
"command_usage"
:
"用法:broadcast <消息>"
,
"message_sent"
:
"公告已发送。"
},
"changescene"
:
{
"usage"
:
"用法:changescene <scene id>"
,
"already_in_scene"
:
"你已经在这个秘境中了。"
,
"success"
:
"已切换至秘境 %s."
,
"exists_error"
:
"此秘境不存在。"
},
"clear"
:
{
"command_usage"
:
"用法: clear <all|wp|art|mat>"
,
"weapons"
:
"已将 %s 的武器清空。"
,
"artifacts"
:
"已将 %s 的圣遗物清空。"
,
"materials"
:
"已将 %s 的材料清空。"
,
"furniture"
:
"已将 %s 的尘歌壶家具清空。"
,
"displays"
:
"已清除 %s 的显示。"
,
"virtuals"
:
"已将 %s 的所有货币和经验值清空。"
,
"everything"
:
"已将 %s 的所有物品清空。"
},
"coop"
:
{
"usage"
:
"用法:coop <playerId> <target playerId>"
,
"success"
:
"已召唤 %s 到 %s的世界"
},
"enter_dungeon"
:
{
"usage"
:
"用法:enterdungeon <dungeon id>"
,
"changed"
:
"已进入秘境 %s"
,
"not_found_error"
:
"此秘境不存在。"
,
"in_dungeon_error"
:
"你已经在秘境中了。"
},
"giveAll"
:
{
"usage"
:
"用法:giveall [player] [amount]"
,
"started"
:
"正在给予全部物品..."
,
"success"
:
"已给予全部物品。"
,
"invalid_amount_or_playerId"
:
"无效的数量/玩家ID。"
},
"giveArtifact"
:
{
"usage"
:
"用法:giveart|gart [player] <artifactId> <mainPropId> [<appendPropId>[,<times>]]... [level]"
,
"id_error"
:
"无效的圣遗物ID。"
,
"success"
:
"已将 %s 给予 %s。"
},
"giveChar"
:
{
"usage"
:
"用法:givechar <player> <itemId|itemName> [amount]"
,
"given"
:
"Given %s with level %s to %s."
,
"invalid_avatar_id"
:
"无效的角色ID。"
,
"invalid_avatar_level"
:
"无效的角色等級。."
,
"invalid_avatar_or_player_id"
:
"无效的角色ID/玩家ID。"
},
"give"
:
{
"usage"
:
"用法:give <player> <itemId|itemName> [amount] [level] [refinement]"
,
"refinement_only_applicable_weapons"
:
"精炼等级参数仅在武器上可用"
,
"refinement_must_between_1_and_5"
:
"精炼等级必须在 1 到 5 之间。"
,
"given"
:
"已将 %s 个 %s 给予 %s。"
,
"given_with_level_and_refinement"
:
"已将 %s [等級%s, 精炼%s] %s个给予 %s"
,
"given_level"
:
"已将 %s 等级 %s %s 个给予 %s"
},
"godmode"
:
{
"success"
:
"上帝模式被设置为 %s 。 [用户:%s]"
},
"heal"
:
{
"success"
:
"所有角色已被治疗。"
},
"kick"
:
{
"player_kick_player"
:
"玩家 [%s:%s] 已将 [%s:%s] 踢出"
,
"server_kick_player"
:
"正在踢出玩家 [%s:%s]"
},
"kill"
:
{
"usage"
:
"用法:killall [playerUid] [sceneId]"
,
"scene_not_found_in_player_world"
:
"未在玩家世界中找到此场景"
,
"kill_monsters_in_scene"
:
"已杀死 %s 个怪物。 [场景ID: %s]"
},
"killCharacter"
:
{
"usage"
:
"用法:/killcharacter [playerId]"
,
"success"
:
"已杀死 %s 目前使用的角色。"
},
"list"
:
{
"message"
:
"目前在线人数:%s"
},
"permission"
:
{
"usage"
:
"用法:permission <add|remove> <username> <permission>"
,
"add"
:
"已设置权限。"
,
"has_error"
:
"此玩家已拥有此权限!"
,
"remove"
:
"权限已移除。"
,
"not_have_error"
:
"此玩家未拥有权限!"
,
"account_error"
:
"账号不存在!"
},
"position"
:
{
"success"
:
"坐标:%.3f, %.3f, %.3f
\n
场景ID:%d"
},
"reload"
:
{
"reload_start"
:
"正在重载配置文件和数据。"
,
"reload_done"
:
"重装完毕。"
},
"resetConst"
:
{
"reset_all"
:
"重置所有角色的命座。"
,
"success"
:
"已重置 %s 的命座,重新登录后将会生效。"
},
"resetShopLimit"
:
{
"usage"
:
"用法:/resetshop <player id>"
},
"sendMail"
:
{
"usage"
:
"用法:give [player] <itemId|itemName> [amount]"
,
"user_not_exist"
:
"ID '%s' 的使用者不存在。"
,
"start_composition"
:
"发送邮件流程。
\n
请使用`/send <标题>`前进到下一步。
\n
你可以在任何时间使用`/sendmail stop`来停止发送。"
,
"templates"
:
"邮件模板尚未实装..."
,
"invalid_arguments"
:
"无效的参数。
\n
指令使用方法 `/sendmail <userId|all|help> [templateId]`"
,
"send_cancel"
:
"取消发送邮件"
,
"send_done"
:
"已将邮件给 %s!"
,
"send_all_done"
:
"邮件已发送给所有人!"
,
"not_composition_end"
:
"现在邮件发送未到最后阶段。
\n
请使用 `/sendmail %s` 继续发送邮件,或使用 `/sendmail stop` 来停止发送邮件。"
,
"please_use"
:
"请使用 `/sendmail %s`"
,
"set_title"
:
"成功将邮件标题设置为 '%s'。
\n
使用 '/sendmail <content>' 来设置邮件内容。"
,
"set_contents"
:
"成功将'%s'设置为邮件内容。
\n
使用 '/sendmail <发件人>' 来设置发件人。"
,
"set_message_sender"
:
"发件人已设置为 '%s'。
\n
使用 '/sendmail <itemId|itemName|finish> [amount] [level]' 来添加附件。"
,
"send"
:
"已添加 %s 个 %s (等級为 %s) 邮件附件。
\n
如果没有要继续添加的道具请使用 `/sendmail finish` 来完成邮件发送。"
,
"invalid_arguments_please_use"
:
"错误的参数
\n
请使用 `/sendmail %s`"
,
"title"
:
"<标题>"
,
"message"
:
"<正文>"
,
"sender"
:
"<发件人>"
,
"arguments"
:
"<itemId|itemName|finish> [数量] [等级]"
,
"error"
:
"错误:无效的编写阶段 %s。需要 StackTrace 请查看服务器控制台。"
},
"sendMessage"
:
{
"usage"
:
"用法:sendmessage <player> <message>"
,
"success"
:
"消息已发送。"
},
"setFetterLevel"
:
{
"usage"
:
"用法:setfetterlevel <level>"
,
"range_error"
:
"好感度等级必须在 0 到 10 之间。"
,
"fetter_set_level"
:
"好感度已设置为 %s 级"
,
"level_error"
:
"无效的好感度等级。"
},
"setStats"
:
{
"usage_console"
:
"用法:setstats|stats @<UID> <stat> <value>"
,
"usage_ingame"
:
"用法:setstats|stats [@UID] <stat> <value>"
,
"help_message"
:
"
\n\t
可使用的数据类型:hp (生命值)| maxhp (最大生命值) | def(防御力) | atk (攻击力)| em (元素精通) | er (元素充能效率) | crate(暴击率) | cdmg (暴击伤害)| cdr (冷却缩减) | heal(治疗加成)| heali (受治疗加成)| shield (护盾强效)| defi (无视防御)
\n\t
(cont.) 元素伤害:epyro (火) | ecryo (冰) | ehydro (水) | egeo (岩) | edendro (草) | eelectro (雷) | ephys (物理)(cont.) 元素抗性:respyro (火) | rescryo (冰) | reshydro (水) | resgeo (岩) | resdendro (草) | reselectro (雷) | resphys (物理)
\n
"
,
"value_error"
:
"无效的数据值。"
,
"uid_error"
:
"无效的UID。"
,
"player_error"
:
"玩家不存在或已离线。"
,
"set_self"
:
"%s 已经设置为 %s。"
,
"set_for_uid"
:
"%s 的使用者 %s 更改为 %s。"
,
"set_max_hp"
:
"最大生命值更改为 %s。"
},
"setWorldLevel"
:
{
"usage"
:
"用法:setworldlevel <level>"
,
"value_error"
:
"世界等级必须设置在0-8之间。"
,
"success"
:
"已将世界等级设为%s。"
,
"invalid_world_level"
:
"无效的世界等级。"
},
"spawn"
:
{
"usage"
:
"用法:spawn <entityId> [amount] [level(仅限怪物]"
,
"success"
:
"已生成 %s 个 %s。"
},
"stop"
:
{
"success"
:
"正在关闭服务器..."
},
"talent"
:
{
"usage_1"
:
"设置天赋等级:/talent set <talentID> <value>"
,
"usage_2"
:
"另一种设置天赋等级的命令使用方法:/talent <n or e or q> <value>"
,
"usage_3"
:
"获取天赋ID指令用法:/talent getid"
,
"lower_16"
:
"无效的天赋等级,天赋等级应低于16。"
,
"set_id"
:
"将天赋等级设为 %s。"
,
"set_atk"
:
"将普通攻击等级设为 %s。"
,
"set_e"
:
"设定天赋E等级为 %s。"
,
"set_q"
:
"设定天赋Q等级为 %s。"
,
"invalid_skill_id"
:
"无效的技能ID。"
,
"set_this"
:
"将天赋等级设为 %s。"
,
"invalid_level"
:
"无效的天赋等级。"
,
"normal_attack_id"
:
"普通攻击的 ID 为 %s。"
,
"e_skill_id"
:
"E技能ID %s。"
,
"q_skill_id"
:
"Q技能ID %s。"
},
"teleportAll"
:
{
"success"
:
"已将全部玩家传送到你的位置"
,
"error"
:
"命令仅限多人游戏使用。"
},
"teleport"
:
{
"usage_server"
:
"用法:/tp @<player id> <x> <y> <z> [scene id]"
,
"usage"
:
"用法:/tp [@<player id>] <x> <y> <z> [scene id]"
,
"specify_player_id"
:
"你必须指定一个玩家ID。"
,
"invalid_position"
:
"无效的位置。"
,
"success"
:
"传送 %s 到坐标 %s,%s,%s,场景为 %s"
},
"weather"
:
{
"usage"
:
"用法:weather <weatherId> [climateId]"
,
"success"
:
"已将当前天气设定为 %s,气候则为 %s。"
,
"invalid_id"
:
"无效的ID。"
},
"drop"
:
{
"command_usage"
:
"用法:drop <itemId|itemName> [amount]"
,
"success"
:
"已將 %s x %s 丟在附近。"
},
"help"
:
{
"usage"
:
"用法:"
,
"aliases"
:
"別名:"
,
"available_commands"
:
"可用指令:"
}
}
}
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