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
0bfa1fa0
Commit
0bfa1fa0
authored
May 09, 2022
by
Akka
Committed by
GitHub
May 09, 2022
Browse files
Merge pull request #8 from Grasscutters/development
Development
parents
65861c3c
056b5b80
Changes
51
Expand all
Show whitespace changes
Inline
Side-by-side
LICENSE
View file @
0bfa1fa0
This diff is collapsed.
Click to expand it.
build.gradle
View file @
0bfa1fa0
...
...
@@ -70,7 +70,7 @@ dependencies {
implementation
group:
'io.netty'
,
name:
'netty-all'
,
version:
'4.1.71.Final'
implementation
group:
'com.google.code.gson'
,
name:
'gson'
,
version:
'2.
8.8
'
implementation
group:
'com.google.code.gson'
,
name:
'gson'
,
version:
'2.
9.0
'
implementation
group:
'com.google.protobuf'
,
name:
'protobuf-java'
,
version:
'3.18.2'
implementation
group:
'org.reflections'
,
name:
'reflections'
,
version:
'0.10.2'
...
...
data/TowerSchedule.json
0 → 100644
View file @
0bfa1fa0
{
"scheduleId"
:
1
,
"scheduleStartTime"
:
"2022-05-01T00:00:00+08:00"
,
"nextScheduleChangeTime"
:
"2022-05-30T00:00:00+08:00"
}
\ No newline at end of file
src/main/java/emu/grasscutter/Config.java
View file @
0bfa1fa0
...
...
@@ -16,7 +16,6 @@ public final class Config {
public
String
KEY_FOLDER
=
"./keys/"
;
public
String
SCRIPTS_FOLDER
=
"./resources/Scripts/"
;
public
String
PLUGINS_FOLDER
=
"./plugins/"
;
public
String
LANGUAGE_FOLDER
=
"./languages/"
;
public
ServerDebugMode
DebugMode
=
ServerDebugMode
.
NONE
;
// ALL, MISSING, NONE
public
ServerRunMode
RunMode
=
ServerRunMode
.
HYBRID
;
// HYBRID, DISPATCH_ONLY, GAME_ONLY
...
...
src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java
View file @
0bfa1fa0
...
...
@@ -9,28 +9,121 @@ import emu.grasscutter.game.inventory.GameItem;
import
emu.grasscutter.game.inventory.ItemType
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.game.inventory.EquipType
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
static
java
.
util
.
Map
.
entry
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
@Command
(
label
=
"giveart"
,
usage
=
"giveart <artifactId> <mainPropId> [<appendPropId>[,<times>]]... [level]"
,
aliases
=
{
"gart"
},
permission
=
"player.giveart"
,
description
=
"commands.giveArtifact.description"
)
public
final
class
GiveArtifactCommand
implements
CommandHandler
{
private
static
final
Map
<
String
,
Map
<
EquipType
,
Integer
>>
mainPropMap
=
Map
.
ofEntries
(
entry
(
"hp"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_BRACER
,
14001
))),
entry
(
"hp%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_SHOES
,
10980
),
entry
(
EquipType
.
EQUIP_RING
,
50980
),
entry
(
EquipType
.
EQUIP_DRESS
,
30980
))),
entry
(
"atk"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_NECKLACE
,
12001
))),
entry
(
"atk%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_SHOES
,
10990
),
entry
(
EquipType
.
EQUIP_RING
,
50990
),
entry
(
EquipType
.
EQUIP_DRESS
,
30990
))),
entry
(
"def%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_SHOES
,
10970
),
entry
(
EquipType
.
EQUIP_RING
,
50970
),
entry
(
EquipType
.
EQUIP_DRESS
,
30970
))),
entry
(
"er"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_SHOES
,
10960
))),
entry
(
"em"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_SHOES
,
10950
),
entry
(
EquipType
.
EQUIP_RING
,
50880
),
entry
(
EquipType
.
EQUIP_DRESS
,
30930
))),
entry
(
"hb"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_DRESS
,
30940
))),
entry
(
"cdmg"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_DRESS
,
30950
))),
entry
(
"cr"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_DRESS
,
30960
))),
entry
(
"phys%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50890
))),
entry
(
"dendro%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50900
))),
entry
(
"geo%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50910
))),
entry
(
"anemo%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50920
))),
entry
(
"hydro%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50930
))),
entry
(
"cryo%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50940
))),
entry
(
"electro%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50950
))),
entry
(
"pyro%"
,
Map
.
ofEntries
(
entry
(
EquipType
.
EQUIP_RING
,
50960
)))
);
private
static
final
Map
<
String
,
String
>
appendPropMap
=
Map
.
ofEntries
(
entry
(
"hp"
,
"0102"
),
entry
(
"hp%"
,
"0103"
),
entry
(
"atk"
,
"0105"
),
entry
(
"atk%"
,
"0106"
),
entry
(
"def"
,
"0108"
),
entry
(
"def%"
,
"0109"
),
entry
(
"er"
,
"0123"
),
entry
(
"em"
,
"0124"
),
entry
(
"cr"
,
"0120"
),
entry
(
"cdmg"
,
"0122"
)
);
private
int
getAppendPropId
(
String
substatText
,
ItemData
itemData
)
{
int
res
;
// If the given substat text is an integer, we just use that
// as the append prop ID.
try
{
res
=
Integer
.
parseInt
(
substatText
);
return
res
;
}
catch
(
NumberFormatException
ignores
)
{
// No need to handle this here. We just continue with the
// possibility of the argument being a substat string.
}
// If the argument was not an integer, we try to determine
// the append prop ID from the given text + artifact information.
// A substat string has the format `substat_tier`, with the
// `_tier` part being optional.
String
[]
substatArgs
=
substatText
.
split
(
"_"
);
String
substatType
;
int
substatTier
;
if
(
substatArgs
.
length
==
1
)
{
substatType
=
substatArgs
[
0
];
substatTier
=
itemData
.
getRankLevel
()
==
1
?
2
:
itemData
.
getRankLevel
()
==
2
?
3
:
4
;
}
else
if
(
substatArgs
.
length
==
2
)
{
substatType
=
substatArgs
[
0
];
substatTier
=
Integer
.
parseInt
(
substatArgs
[
1
]);
}
else
{
throw
new
IllegalArgumentException
();
}
// Check if the specified tier is legal for the artifact rarity.
if
(
substatTier
<
1
||
substatTier
>
4
)
{
throw
new
IllegalArgumentException
();
}
if
(
itemData
.
getRankLevel
()
==
1
&&
substatTier
>
2
)
{
throw
new
IllegalArgumentException
();
}
if
(
itemData
.
getRankLevel
()
==
2
&&
substatTier
>
3
)
{
throw
new
IllegalArgumentException
();
}
// Check if the given substat type string is a legal stat.
if
(!
appendPropMap
.
containsKey
(
substatType
))
{
throw
new
IllegalArgumentException
();
}
// Build the append prop ID.
return
Integer
.
parseInt
(
Integer
.
toString
(
itemData
.
getRankLevel
())
+
appendPropMap
.
get
(
substatType
)
+
Integer
.
toString
(
substatTier
));
}
@Override
public
void
execute
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
// Sanity checks
if
(
targetPlayer
==
null
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.execution.need_target"
));
return
;
}
if
(
args
.
size
()
<
2
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.giveArtifact.usage"
));
return
;
}
// Get the artifact piece ID from the arguments.
int
itemId
;
try
{
itemId
=
Integer
.
parseInt
(
args
.
remove
(
0
));
...
...
@@ -38,20 +131,35 @@ public final class GiveArtifactCommand implements CommandHandler {
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.giveArtifact.id_error"
));
return
;
}
ItemData
itemData
=
GameData
.
getItemDataMap
().
get
(
itemId
);
if
(
itemData
.
getItemType
()
!=
ItemType
.
ITEM_RELIQUARY
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.giveArtifact.id_error"
));
return
;
}
// Get the main stat from the arguments.
// If the given argument is an integer, we use that.
// If not, we check if the argument string is in the main prop map.
String
mainPropIdString
=
args
.
remove
(
0
);
int
mainPropId
;
try
{
mainPropId
=
Integer
.
parseInt
(
args
.
remove
(
0
)
);
mainPropId
=
Integer
.
parseInt
(
mainPropIdString
);
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.generic.execution.argument_error"
));
mainPropId
=
-
1
;
}
if
(
mainPropMap
.
containsKey
(
mainPropIdString
)
&&
mainPropMap
.
get
(
mainPropIdString
).
containsKey
(
itemData
.
getEquipType
()))
{
mainPropId
=
mainPropMap
.
get
(
mainPropIdString
).
get
(
itemData
.
getEquipType
());
}
if
(
mainPropId
==
-
1
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.execution.argument_error"
));
return
;
}
// Get the level from the arguments.
int
level
=
1
;
try
{
int
last
=
Integer
.
parseInt
(
args
.
get
(
args
.
size
()-
1
));
...
...
@@ -62,9 +170,13 @@ public final class GiveArtifactCommand implements CommandHandler {
}
catch
(
NumberFormatException
ignored
)
{
// Could be a stat,times string so no need to panic
}
List
<
Integer
>
appendPropIdList
=
new
ArrayList
<>();
// Get substats.
ArrayList
<
Integer
>
appendPropIdList
=
new
ArrayList
<>();
try
{
// Every remaining argument is a substat.
args
.
forEach
(
it
->
{
// The substat syntax permits specifying a number of rolls for the given
// substat. Split the string into stat and number if that is the case here.
String
[]
arr
;
int
n
=
1
;
if
((
arr
=
it
.
split
(
","
)).
length
==
2
)
{
...
...
@@ -74,13 +186,19 @@ public final class GiveArtifactCommand implements CommandHandler {
n
=
200
;
}
}
appendPropIdList
.
addAll
(
Collections
.
nCopies
(
n
,
Integer
.
parseInt
(
it
)));
// Determine the substat ID.
int
appendPropId
=
getAppendPropId
(
it
,
itemData
);
// Add the current substat.
appendPropIdList
.
addAll
(
Collections
.
nCopies
(
n
,
appendPropId
));
});
}
catch
(
Exception
ignored
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.execution.argument_error"
));
return
;
}
// Create item for the artifact.
GameItem
item
=
new
GameItem
(
itemData
);
item
.
setLevel
(
level
);
item
.
setMainPropId
(
mainPropId
);
...
...
src/main/java/emu/grasscutter/command/commands/UnlockTowerCommand.java
0 → 100644
View file @
0bfa1fa0
package
emu.grasscutter.command.commands
;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.tower.TowerLevelRecord
;
import
java.util.List
;
import
static
emu
.
grasscutter
.
utils
.
Language
.
translate
;
@Command
(
label
=
"unlocktower"
,
usage
=
"unlocktower"
,
aliases
=
{
"ut"
},
description
=
"Unlock all levels of tower"
,
permission
=
"player.tower"
)
public
class
UnlockTowerCommand
implements
CommandHandler
{
@Override
public
void
execute
(
Player
sender
,
Player
targetPlayer
,
List
<
String
>
args
)
{
unlockFloor
(
sender
,
sender
.
getServer
().
getTowerScheduleManager
()
.
getCurrentTowerScheduleData
().
getEntranceFloorId
());
unlockFloor
(
sender
,
sender
.
getServer
().
getTowerScheduleManager
()
.
getScheduleFloors
());
CommandHandler
.
sendMessage
(
sender
,
translate
(
"commands.tower.unlock_done"
));
}
public
void
unlockFloor
(
Player
player
,
List
<
Integer
>
floors
){
floors
.
stream
()
.
filter
(
id
->
!
player
.
getTowerManager
().
getRecordMap
().
containsKey
(
id
))
.
forEach
(
id
->
player
.
getTowerManager
().
getRecordMap
().
put
(
id
,
new
TowerLevelRecord
(
id
)));
}
}
src/main/java/emu/grasscutter/data/GameData.java
View file @
0bfa1fa0
...
...
@@ -9,6 +9,8 @@ import java.util.Map;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
import
emu.grasscutter.data.custom.AbilityModifier
;
import
emu.grasscutter.data.custom.AbilityModifierEntry
;
import
emu.grasscutter.data.custom.OpenConfigEntry
;
import
emu.grasscutter.data.custom.ScenePointEntry
;
import
emu.grasscutter.data.def.*
;
...
...
@@ -22,6 +24,7 @@ public class GameData {
// BinOutputs
private
static
final
Int2ObjectMap
<
String
>
abilityHashes
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Map
<
String
,
AbilityEmbryoEntry
>
abilityEmbryos
=
new
HashMap
<>();
private
static
final
Map
<
String
,
AbilityModifierEntry
>
abilityModifiers
=
new
HashMap
<>();
private
static
final
Map
<
String
,
OpenConfigEntry
>
openConfigEntries
=
new
HashMap
<>();
private
static
final
Map
<
String
,
ScenePointEntry
>
scenePointEntries
=
new
HashMap
<>();
...
...
@@ -70,6 +73,7 @@ public class GameData {
private
static
final
Int2ObjectMap
<
RewardPreviewData
>
rewardPreviewDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
TowerFloorData
>
towerFloorDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
TowerLevelData
>
towerLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
TowerScheduleData
>
towerScheduleDataMap
=
new
Int2ObjectOpenHashMap
<>();
// Cache
private
static
Map
<
Integer
,
List
<
Integer
>>
fetters
=
new
HashMap
<>();
...
...
@@ -101,6 +105,10 @@ public class GameData {
return
abilityEmbryos
;
}
public
static
Map
<
String
,
AbilityModifierEntry
>
getAbilityModifiers
()
{
return
abilityModifiers
;
}
public
static
Map
<
String
,
OpenConfigEntry
>
getOpenConfigEntries
()
{
return
openConfigEntries
;
}
...
...
@@ -320,4 +328,7 @@ public class GameData {
public
static
Int2ObjectMap
<
TowerLevelData
>
getTowerLevelDataMap
(){
return
towerLevelDataMap
;
}
public
static
Int2ObjectMap
<
TowerScheduleData
>
getTowerScheduleDataMap
(){
return
towerScheduleDataMap
;
}
}
src/main/java/emu/grasscutter/data/ResourceLoader.java
View file @
0bfa1fa0
...
...
@@ -18,6 +18,11 @@ import emu.grasscutter.Grasscutter;
import
emu.grasscutter.data.common.PointData
;
import
emu.grasscutter.data.common.ScenePointConfig
;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
import
emu.grasscutter.data.custom.AbilityModifier
;
import
emu.grasscutter.data.custom.AbilityModifier.AbilityConfigData
;
import
emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction
;
import
emu.grasscutter.data.custom.AbilityModifier.AbilityModifierActionType
;
import
emu.grasscutter.data.custom.AbilityModifierEntry
;
import
emu.grasscutter.data.custom.OpenConfigEntry
;
import
emu.grasscutter.data.custom.ScenePointEntry
;
import
emu.grasscutter.game.world.SpawnDataEntry
;
...
...
@@ -47,6 +52,7 @@ public class ResourceLoader {
// Load ability lists
loadAbilityEmbryos
();
loadOpenConfig
();
loadAbilityModifiers
();
// Load resources
loadResources
();
// Process into depots
...
...
@@ -244,6 +250,69 @@ public class ResourceLoader {
}
}
private
static
void
loadAbilityModifiers
()
{
// Load from BinOutput
File
folder
=
new
File
(
Utils
.
toFilePath
(
Grasscutter
.
getConfig
().
RESOURCE_FOLDER
+
"BinOutput/Ability/Temp/AvatarAbilities/"
));
File
[]
files
=
folder
.
listFiles
();
if
(
files
==
null
)
{
Grasscutter
.
getLogger
().
error
(
"Error loading ability modifiers: no files found in "
+
folder
.
getAbsolutePath
());
return
;
}
for
(
File
file
:
files
)
{
List
<
AbilityConfigData
>
abilityConfigList
=
null
;
try
(
FileReader
fileReader
=
new
FileReader
(
file
))
{
abilityConfigList
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
AbilityConfigData
.
class
).
getType
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
continue
;
}
for
(
AbilityConfigData
data
:
abilityConfigList
)
{
if
(
data
.
Default
.
modifiers
==
null
||
data
.
Default
.
modifiers
.
size
()
==
0
)
{
continue
;
}
AbilityModifierEntry
modifierEntry
=
new
AbilityModifierEntry
(
data
.
Default
.
abilityName
);
for
(
Entry
<
String
,
AbilityModifier
>
entry
:
data
.
Default
.
modifiers
.
entrySet
())
{
AbilityModifier
modifier
=
entry
.
getValue
();
// Stare.
if
(
modifier
.
onAdded
!=
null
)
{
for
(
AbilityModifierAction
action
:
modifier
.
onAdded
)
{
if
(
action
.
$type
.
contains
(
"HealHP"
))
{
action
.
type
=
AbilityModifierActionType
.
HealHP
;
modifierEntry
.
getOnAdded
().
add
(
action
);
}
}
}
if
(
modifier
.
onThinkInterval
!=
null
)
{
for
(
AbilityModifierAction
action
:
modifier
.
onThinkInterval
)
{
if
(
action
.
$type
.
contains
(
"HealHP"
))
{
action
.
type
=
AbilityModifierActionType
.
HealHP
;
modifierEntry
.
getOnThinkInterval
().
add
(
action
);
}
}
}
if
(
modifier
.
onRemoved
!=
null
)
{
for
(
AbilityModifierAction
action
:
modifier
.
onRemoved
)
{
if
(
action
.
$type
.
contains
(
"HealHP"
))
{
action
.
type
=
AbilityModifierActionType
.
HealHP
;
modifierEntry
.
getOnRemoved
().
add
(
action
);
}
}
}
}
GameData
.
getAbilityModifiers
().
put
(
modifierEntry
.
getName
(),
modifierEntry
);
}
}
}
private
static
void
loadSpawnData
()
{
// Read from cached file if exists
File
spawnDataEntries
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"Spawns.json"
);
...
...
src/main/java/emu/grasscutter/data/custom/AbilityModifier.java
0 → 100644
View file @
0bfa1fa0
package
emu.grasscutter.data.custom
;
import
java.util.Map
;
public
class
AbilityModifier
{
public
AbilityModifierAction
[]
onAdded
;
public
AbilityModifierAction
[]
onThinkInterval
;
public
AbilityModifierAction
[]
onRemoved
;
public
static
class
AbilityConfigData
{
public
AbilityData
Default
;
}
public
static
class
AbilityData
{
public
String
abilityName
;
public
Map
<
String
,
AbilityModifier
>
modifiers
;
}
public
static
class
AbilityModifierAction
{
public
String
$type
;
public
AbilityModifierActionType
type
;
public
String
target
;
public
AbilityModifierValue
amount
;
public
AbilityModifierValue
amountByTargetCurrentHPRatio
;
}
public
static
class
AbilityModifierValue
{
public
boolean
isFormula
;
public
boolean
isDynamic
;
public
String
dynamicKey
;
}
public
enum
AbilityModifierActionType
{
HealHP
,
ApplyModifier
,
LoseHP
;
}
}
src/main/java/emu/grasscutter/data/custom/AbilityModifierEntry.java
0 → 100644
View file @
0bfa1fa0
package
emu.grasscutter.data.custom
;
import
java.util.ArrayList
;
import
java.util.List
;
import
emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction
;
public
class
AbilityModifierEntry
{
private
String
name
;
// Custom value
public
List
<
AbilityModifierAction
>
onModifierAdded
;
public
List
<
AbilityModifierAction
>
onThinkInterval
;
public
List
<
AbilityModifierAction
>
onRemoved
;
public
AbilityModifierEntry
(
String
name
)
{
this
.
name
=
name
;
this
.
onModifierAdded
=
new
ArrayList
<>();
this
.
onThinkInterval
=
new
ArrayList
<>();
this
.
onRemoved
=
new
ArrayList
<>();
}
public
String
getName
()
{
return
name
;
}
public
List
<
AbilityModifierAction
>
getOnAdded
()
{
return
onModifierAdded
;
}
public
List
<
AbilityModifierAction
>
getOnThinkInterval
()
{
return
onThinkInterval
;
}
public
List
<
AbilityModifierAction
>
getOnRemoved
()
{
return
onRemoved
;
}
}
src/main/java/emu/grasscutter/data/def/TowerScheduleData.java
0 → 100644
View file @
0bfa1fa0
package
emu.grasscutter.data.def
;
import
emu.grasscutter.data.GameResource
;
import
emu.grasscutter.data.ResourceType
;
import
java.util.List
;
@ResourceType
(
name
=
"TowerScheduleExcelConfigData.json"
)
public
class
TowerScheduleData
extends
GameResource
{
private
int
ScheduleId
;
private
List
<
Integer
>
EntranceFloorId
;
private
List
<
ScheduleDetail
>
Schedules
;
private
int
MonthlyLevelConfigId
;
@Override
public
int
getId
()
{
return
ScheduleId
;
}
@Override
public
void
onLoad
()
{
super
.
onLoad
();
this
.
Schedules
=
this
.
Schedules
.
stream
()
.
filter
(
item
->
item
.
getFloorList
().
size
()
>
0
)
.
toList
();
}
public
int
getScheduleId
()
{
return
ScheduleId
;
}
public
void
setScheduleId
(
int
scheduleId
)
{
ScheduleId
=
scheduleId
;
}
public
List
<
Integer
>
getEntranceFloorId
()
{
return
EntranceFloorId
;
}
public
void
setEntranceFloorId
(
List
<
Integer
>
entranceFloorId
)
{
EntranceFloorId
=
entranceFloorId
;
}
public
List
<
ScheduleDetail
>
getSchedules
()
{
return
Schedules
;
}
public
void
setSchedules
(
List
<
ScheduleDetail
>
schedules
)
{
Schedules
=
schedules
;
}
public
int
getMonthlyLevelConfigId
()
{
return
MonthlyLevelConfigId
;
}
public
void
setMonthlyLevelConfigId
(
int
monthlyLevelConfigId
)
{
MonthlyLevelConfigId
=
monthlyLevelConfigId
;
}
public
static
class
ScheduleDetail
{
private
List
<
Integer
>
FloorList
;
public
List
<
Integer
>
getFloorList
()
{
return
FloorList
;
}
public
void
setFloorList
(
List
<
Integer
>
floorList
)
{
FloorList
=
floorList
;
}
}
}
src/main/java/emu/grasscutter/game/ability/AbilityManager.java
0 → 100644
View file @
0bfa1fa0
package
emu.grasscutter.game.ability
;
import
com.google.protobuf.InvalidProtocolBufferException
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.custom.AbilityModifier
;
import
emu.grasscutter.data.custom.AbilityModifier.AbilityModifierAction
;
import
emu.grasscutter.data.custom.AbilityModifier.AbilityModifierActionType
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.custom.AbilityModifierEntry
;
import
emu.grasscutter.game.entity.EntityItem
;
import
emu.grasscutter.game.entity.GameEntity
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall
;
import
emu.grasscutter.net.proto.AbilityInvokeArgumentOuterClass.AbilityInvokeArgument
;
import
emu.grasscutter.net.proto.AbilityInvokeEntryHeadOuterClass.AbilityInvokeEntryHead
;
import
emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry
;
import
emu.grasscutter.net.proto.AbilityMetaModifierChangeOuterClass.AbilityMetaModifierChange
;
import
emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityMetaReInitOverrideMap
;
import
emu.grasscutter.net.proto.AbilityScalarTypeOuterClass.AbilityScalarType
;
import
emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry
;
import
emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Utils
;
public
class
AbilityManager
{
private
Player
player
;
public
AbilityManager
(
Player
player
)
{
this
.
player
=
player
;
}
public
Player
getPlayer
()
{
return
this
.
player
;
}
public
void
onAbilityInvoke
(
AbilityInvokeEntry
invoke
)
throws
Exception
{
//System.out.println(invoke.getArgumentType() + " (" + invoke.getArgumentTypeValue() + "): " + Utils.bytesToHex(invoke.toByteArray()));
switch
(
invoke
.
getArgumentType
())
{
case
ABILITY_META_OVERRIDE_PARAM:
handleOverrideParam
(
invoke
);
break
;
case
ABILITY_META_REINIT_OVERRIDEMAP:
handleReinitOverrideMap
(
invoke
);
break
;
case
ABILITY_META_MODIFIER_CHANGE:
handleModifierChange
(
invoke
);
break
;
case
ABILITY_MIXIN_COST_STAMINA:
handleMixinCostStamina
(
invoke
);
break
;
case
ABILITY_ACTION_GENERATE_ELEM_BALL:
handleGenerateElemBall
(
invoke
);
break
;
default
:
break
;
}
}
private
void
handleOverrideParam
(
AbilityInvokeEntry
invoke
)
throws
Exception
{
GameEntity
entity
=
player
.
getScene
().
getEntityById
(
invoke
.
getEntityId
());
if
(
entity
==
null
)
{
return
;
}
AbilityScalarValueEntry
entry
=
AbilityScalarValueEntry
.
parseFrom
(
invoke
.
getAbilityData
());
entity
.
getMetaOverrideMap
().
put
(
entry
.
getKey
().
getStr
(),
entry
.
getFloatValue
());
}
private
void
handleReinitOverrideMap
(
AbilityInvokeEntry
invoke
)
throws
Exception
{
GameEntity
entity
=
player
.
getScene
().
getEntityById
(
invoke
.
getEntityId
());
if
(
entity
==
null
)
{
return
;
}
AbilityMetaReInitOverrideMap
map
=
AbilityMetaReInitOverrideMap
.
parseFrom
(
invoke
.
getAbilityData
());
for
(
AbilityScalarValueEntry
entry
:
map
.
getOverrideMapList
())
{
entity
.
getMetaOverrideMap
().
put
(
entry
.
getKey
().
getStr
(),
entry
.
getFloatValue
());
}
}
private
void
handleModifierChange
(
AbilityInvokeEntry
invoke
)
throws
Exception
{
GameEntity
target
=
player
.
getScene
().
getEntityById
(
invoke
.
getEntityId
());
if
(
target
==
null
)
{
return
;
}
AbilityInvokeEntryHead
head
=
invoke
.
getHead
();
if
(
head
==
null
)
{
return
;
}
AbilityMetaModifierChange
data
=
AbilityMetaModifierChange
.
parseFrom
(
invoke
.
getAbilityData
());
if
(
data
==
null
)
{
return
;
}
GameEntity
sourceEntity
=
player
.
getScene
().
getEntityById
(
data
.
getApplyEntityId
());
if
(
sourceEntity
==
null
)
{
return
;
}
// This is not how it works but we will keep it for now since healing abilities dont work properly anyways
if
(
data
.
getAction
()
==
ModifierAction
.
ADDED
&&
data
.
getParentAbilityName
()
!=
null
)
{
// Handle add modifier here
String
modifierString
=
data
.
getParentAbilityName
().
getStr
();
AbilityModifierEntry
modifier
=
GameData
.
getAbilityModifiers
().
get
(
modifierString
);
if
(
modifier
!=
null
&&
modifier
.
getOnAdded
().
size
()
>
0
)
{
for
(
AbilityModifierAction
action
:
modifier
.
getOnAdded
())
{
invokeAction
(
action
,
target
,
sourceEntity
);
}
}
// Add to meta modifier list
target
.
getMetaModifiers
().
put
(
head
.
getInstancedModifierId
(),
modifierString
);
}
else
if
(
data
.
getAction
()
==
ModifierAction
.
REMOVED
)
{
String
modifierString
=
target
.
getMetaModifiers
().
get
(
head
.
getInstancedModifierId
());
if
(
modifierString
!=
null
)
{
// Get modifier and call on remove event
AbilityModifierEntry
modifier
=
GameData
.
getAbilityModifiers
().
get
(
modifierString
);
if
(
modifier
!=
null
&&
modifier
.
getOnRemoved
().
size
()
>
0
)
{
for
(
AbilityModifierAction
action
:
modifier
.
getOnRemoved
())
{
invokeAction
(
action
,
target
,
sourceEntity
);
}
}
// Remove from meta modifiers
target
.
getMetaModifiers
().
remove
(
head
.
getInstancedModifierId
());
}
}
}
private
void
handleMixinCostStamina
(
AbilityInvokeEntry
invoke
)
{
// Not the right way of doing this
if
(
Grasscutter
.
getConfig
().
OpenStamina
)
{
// getPlayer().getStaminaManager().updateStamina(getPlayer().getSession(), -450);
// TODO
// set flag in stamina/movement manager that specifies the player is currently using an alternate sprint
}
}
private
void
handleGenerateElemBall
(
AbilityInvokeEntry
invoke
)
throws
InvalidProtocolBufferException
{
AbilityActionGenerateElemBall
action
=
AbilityActionGenerateElemBall
.
parseFrom
(
invoke
.
getAbilityData
());
if
(
action
==
null
)
{
return
;
}
ItemData
itemData
=
GameData
.
getItemDataMap
().
get
(
2024
);
if
(
itemData
==
null
)
{
return
;
// Should never happen
}
EntityItem
energyBall
=
new
EntityItem
(
getPlayer
().
getScene
(),
getPlayer
(),
itemData
,
new
Position
(
action
.
getPos
()),
1
);
energyBall
.
getRotation
().
set
(
action
.
getRot
());
getPlayer
().
getScene
().
addEntity
(
energyBall
);
}
private
void
invokeAction
(
AbilityModifierAction
action
,
GameEntity
target
,
GameEntity
sourceEntity
)
{
switch
(
action
.
type
)
{
case
HealHP
->
{
if
(
action
.
amount
==
null
)
{
return
;
}
float
healAmount
=
0
;
if
(
action
.
amount
.
isDynamic
&&
action
.
amount
.
dynamicKey
!=
null
)
{
healAmount
=
sourceEntity
.
getMetaOverrideMap
().
getOrDefault
(
action
.
amount
.
dynamicKey
,
0
f
);
}
if
(
healAmount
>
0
)
{
target
.
heal
(
healAmount
);
}
}
case
LoseHP
->
{
if
(
action
.
amountByTargetCurrentHPRatio
==
null
)
{
return
;
}
float
damageAmount
=
0
;
if
(
action
.
amount
.
isDynamic
&&
action
.
amount
.
dynamicKey
!=
null
)
{
damageAmount
=
sourceEntity
.
getMetaOverrideMap
().
getOrDefault
(
action
.
amount
.
dynamicKey
,
0
f
);
}
if
(
damageAmount
>
0
)
{
target
.
damage
(
damageAmount
);
}
}
}
}
}
src/main/java/emu/grasscutter/game/avatar/Avatar.java
View file @
0bfa1fa0
...
...
@@ -69,6 +69,7 @@ public class Avatar {
@Transient
private
Player
owner
;
@Transient
private
AvatarData
data
;
@Transient
private
AvatarSkillDepotData
skillDepot
;
@Transient
private
long
guid
;
// Player unique id
private
int
avatarId
;
// Id of avatar
...
...
@@ -103,8 +104,8 @@ public class Avatar {
private
int
nameCardRewardId
;
private
int
nameCardId
;
@Deprecated
// Do not use. Morhpia only!
public
Avatar
()
{
// Morhpia only!
this
.
equips
=
new
Int2ObjectOpenHashMap
<>();
this
.
fightProp
=
new
Int2FloatOpenHashMap
();
this
.
extraAbilityEmbryos
=
new
HashSet
<>();
...
...
@@ -140,7 +141,7 @@ public class Avatar {
}
// Skill depot
this
.
setSkillDepot
(
getAvatarData
().
getSkillDepot
());
this
.
setSkillDepot
Data
(
getAvatarData
().
getSkillDepot
());
// Set stats
this
.
recalcStats
();
...
...
@@ -164,7 +165,8 @@ public class Avatar {
}
protected
void
setAvatarData
(
AvatarData
data
)
{
this
.
data
=
data
;
if
(
this
.
data
!=
null
)
return
;
this
.
data
=
data
;
// Used while loading this from the database
}
public
int
getOwnerId
()
{
...
...
@@ -257,9 +259,19 @@ public class Avatar {
return
skillDepotId
;
}
public
void
setSkillDepot
(
AvatarSkillDepotData
skillDepot
)
{
// Set id
public
AvatarSkillDepotData
getSkillDepot
()
{
return
skillDepot
;
}
protected
void
setSkillDepot
(
AvatarSkillDepotData
skillDepot
)
{
if
(
this
.
skillDepot
!=
null
)
return
;
this
.
skillDepot
=
skillDepot
;
// Used while loading this from the database
}
public
void
setSkillDepotData
(
AvatarSkillDepotData
skillDepot
)
{
// Set id and depot
this
.
skillDepotId
=
skillDepot
.
getId
();
this
.
skillDepot
=
skillDepot
;
// Clear, then add skills
getSkillLevelMap
().
clear
();
if
(
skillDepot
.
getEnergySkill
()
>
0
)
{
...
...
@@ -501,8 +513,8 @@ public class Avatar {
// Set energy usage
if
(
data
.
getSkillDepot
()
!=
null
&&
data
.
getSkillDepot
().
getEnergySkillData
()
!=
null
)
{
ElementType
element
=
data
.
getSkillDepot
().
getElementType
();
this
.
setFightProperty
(
element
.
getEnergyProp
erty
(),
data
.
getSkillDepot
().
getEnergySkillData
().
getCostElemVal
());
this
.
setFightProperty
((
element
.
getEnergyProp
erty
().
getId
()
%
70
)
+
1000
,
data
.
getSkillDepot
().
getEnergySkillData
().
getCostElemVal
());
this
.
setFightProperty
(
element
.
get
Max
EnergyProp
(),
data
.
getSkillDepot
().
getEnergySkillData
().
getCostElemVal
());
this
.
setFightProperty
((
element
.
get
Max
EnergyProp
().
getId
()
%
70
)
+
1000
,
data
.
getSkillDepot
().
getEnergySkillData
().
getCostElemVal
());
}
// Artifacts
...
...
src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java
View file @
0bfa1fa0
...
...
@@ -5,6 +5,7 @@ import java.util.List;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.def.AvatarData
;
import
emu.grasscutter.data.def.AvatarSkillDepotData
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.inventory.GameItem
;
...
...
@@ -139,12 +140,14 @@ public class AvatarStorage implements Iterable<Avatar> {
}
AvatarData
avatarData
=
GameData
.
getAvatarDataMap
().
get
(
avatar
.
getAvatarId
());
if
(
avatarData
==
null
)
{
AvatarSkillDepotData
skillDepot
=
GameData
.
getAvatarSkillDepotDataMap
().
get
(
avatar
.
getSkillDepotId
());
if
(
avatarData
==
null
||
skillDepot
==
null
)
{
continue
;
}
// Set ownerships
avatar
.
setAvatarData
(
avatarData
);
avatar
.
setSkillDepot
(
skillDepot
);
avatar
.
setOwner
(
getPlayer
());
// Force recalc of const boosted skills
...
...
src/main/java/emu/grasscutter/game/dungeons/TowerDungeonSettleListener.java
View file @
0bfa1fa0
...
...
@@ -12,12 +12,18 @@ public class TowerDungeonSettleListener implements DungeonSettleListener {
scene
.
setAutoCloseTime
(
Utils
.
getCurrentSeconds
()
+
1000
);
var
towerManager
=
scene
.
getPlayers
().
get
(
0
).
getTowerManager
();
towerManager
.
notifyCurLevelRecordChangeWhenDone
();
scene
.
broadcastPacket
(
new
PacketTowerFloorRecordChangeNotify
(
towerManager
.
getCurrentFloorId
()));
scene
.
broadcastPacket
(
new
PacketDungeonSettleNotify
(
scene
.
getChallenge
(),
true
,
towerManager
.
notifyCurLevelRecordChangeWhenDone
(
3
);
scene
.
broadcastPacket
(
new
PacketTowerFloorRecordChangeNotify
(
towerManager
.
getCurrentFloorId
(),
3
,
towerManager
.
canEnterScheduleFloor
()
));
scene
.
broadcastPacket
(
new
PacketDungeonSettleNotify
(
scene
.
getChallenge
(),
towerManager
.
hasNextFloor
(),
towerManager
.
hasNextLevel
(),
towerManager
.
getNextFloorId
()
towerManager
.
hasNextLevel
()
?
0
:
towerManager
.
getNextFloorId
()
));
}
...
...
src/main/java/emu/grasscutter/game/entity/EntityAvatar.java
View file @
0bfa1fa0
...
...
@@ -17,17 +17,22 @@ import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlo
import
emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo
;
import
emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo
;
import
emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair
;
import
emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason
;
import
emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityInfo
;
import
emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData
;
import
emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo
;
import
emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair
;
import
emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType
;
import
emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason
;
import
emu.grasscutter.net.proto.PropPairOuterClass.PropPair
;
import
emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType
;
import
emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo
;
import
emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo
;
import
emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo
;
import
emu.grasscutter.net.proto.VectorOuterClass.Vector
;
import
emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.ProtoHelper
;
import
emu.grasscutter.utils.Utils
;
...
...
@@ -110,6 +115,35 @@ public class EntityAvatar extends GameEntity {
this
.
killedBy
=
killerId
;
}
@Override
public
float
heal
(
float
amount
)
{
float
healed
=
super
.
heal
(
amount
);
if
(
healed
>
0
f
)
{
getScene
().
broadcastPacket
(
new
PacketEntityFightPropChangeReasonNotify
(
this
,
FightProperty
.
FIGHT_PROP_CUR_HP
,
healed
,
PropChangeReason
.
PROP_CHANGE_ABILITY
,
ChangeHpReason
.
ChangeHpAddAbility
)
);
}
return
healed
;
}
public
void
addEnergy
(
float
amount
)
{
FightProperty
curEnergyProp
=
getAvatar
().
getSkillDepot
().
getElementType
().
getCurEnergyProp
();
FightProperty
maxEnergyProp
=
getAvatar
().
getSkillDepot
().
getElementType
().
getMaxEnergyProp
();
float
curEnergy
=
this
.
getFightProperty
(
curEnergyProp
);
float
maxEnergy
=
this
.
getFightProperty
(
maxEnergyProp
);
float
newEnergy
=
Math
.
min
(
curEnergy
+
amount
,
maxEnergy
);
if
(
newEnergy
!=
curEnergy
)
{
setFightProperty
(
curEnergyProp
,
newEnergy
);
getScene
().
broadcastPacket
(
new
PacketAvatarFightPropUpdateNotify
(
getAvatar
(),
curEnergyProp
));
getScene
().
broadcastPacket
(
new
PacketEntityFightPropChangeReasonNotify
(
this
,
curEnergyProp
,
newEnergy
,
PropChangeReason
.
PROP_CHANGE_ENERGY_BALL
));
}
}
public
SceneAvatarInfo
getSceneAvatarInfo
()
{
SceneAvatarInfo
.
Builder
avatarInfo
=
SceneAvatarInfo
.
newBuilder
()
.
setUid
(
this
.
getPlayer
().
getUid
())
...
...
src/main/java/emu/grasscutter/game/entity/GameEntity.java
View file @
0bfa1fa0
package
emu.grasscutter.game.entity
;
import
java.util.HashMap
;
import
java.util.Map
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.LifeState
;
import
emu.grasscutter.game.world.Scene
;
...
...
@@ -9,8 +12,11 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import
emu.grasscutter.net.proto.MotionStateOuterClass.MotionState
;
import
emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo
;
import
emu.grasscutter.net.proto.VectorOuterClass.Vector
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.utils.Position
;
import
it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
abstract
class
GameEntity
{
protected
int
id
;
...
...
@@ -25,6 +31,10 @@ public abstract class GameEntity {
private
int
lastMoveSceneTimeMs
;
private
int
lastMoveReliableSeq
;
// Abilities
private
Map
<
String
,
Float
>
metaOverrideMap
;
private
Int2ObjectMap
<
String
>
metaModifiers
;
public
GameEntity
(
Scene
scene
)
{
this
.
scene
=
scene
;
this
.
moveState
=
MotionState
.
MOTION_NONE
;
...
...
@@ -54,6 +64,20 @@ public abstract class GameEntity {
return
isAlive
()
?
LifeState
.
LIFE_ALIVE
:
LifeState
.
LIFE_DEAD
;
}
public
Map
<
String
,
Float
>
getMetaOverrideMap
()
{
if
(
this
.
metaOverrideMap
==
null
)
{
this
.
metaOverrideMap
=
new
HashMap
<>();
}
return
this
.
metaOverrideMap
;
}
public
Int2ObjectMap
<
String
>
getMetaModifiers
()
{
if
(
this
.
metaModifiers
==
null
)
{
this
.
metaModifiers
=
new
Int2ObjectOpenHashMap
<>();
}
return
this
.
metaModifiers
;
}
public
abstract
Int2FloatOpenHashMap
getFightProperties
();
public
abstract
Position
getPosition
();
...
...
@@ -146,4 +170,53 @@ public abstract class GameEntity {
public
void
setSpawnEntry
(
SpawnDataEntry
spawnEntry
)
{
this
.
spawnEntry
=
spawnEntry
;
}
public
float
heal
(
float
amount
)
{
if
(
this
.
getFightProperties
()
==
null
)
{
return
0
f
;
}
float
curHp
=
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
);
float
maxHp
=
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
);
if
(
curHp
>=
maxHp
)
{
return
0
f
;
}
float
healed
=
Math
.
min
(
maxHp
-
curHp
,
amount
);
this
.
addFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
healed
);
getScene
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
this
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
return
healed
;
}
public
void
damage
(
float
amount
)
{
damage
(
amount
,
0
);
}
public
void
damage
(
float
amount
,
int
killerId
)
{
// Sanity check
if
(
getFightProperties
()
==
null
)
{
return
;
}
// Lose hp
addFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
-
amount
);
// Check if dead
boolean
isDead
=
false
;
if
(
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
)
<=
0
f
)
{
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
0
f
);
isDead
=
true
;
}
// Packets
this
.
getScene
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
this
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
// Check if dead
if
(
isDead
)
{
getScene
().
killEntity
(
this
,
0
);
}
}
}
src/main/java/emu/grasscutter/game/inventory/Inventory.java
View file @
0bfa1fa0
...
...
@@ -172,6 +172,9 @@ public class Inventory implements Iterable<GameItem> {
// Handle
this
.
addVirtualItem
(
item
.
getItemId
(),
item
.
getCount
());
return
item
;
}
else
if
(
item
.
getItemData
().
getMaterialType
()
==
MaterialType
.
MATERIAL_ADSORBATE
)
{
player
.
getTeamManager
().
addEnergyToTeam
(
item
);
return
null
;
}
else
if
(
item
.
getItemData
().
getMaterialType
()
==
MaterialType
.
MATERIAL_AVATAR
)
{
// Get avatar id
int
avatarId
=
(
item
.
getItemId
()
%
1000
)
+
10000000
;
...
...
src/main/java/emu/grasscutter/game/player/InvokeHandler.java
View file @
0bfa1fa0
...
...
@@ -30,7 +30,7 @@ public class InvokeHandler<T> {
}
public
synchronized
void
update
(
Player
player
)
{
if
(
player
.
getWorld
()
==
null
)
{
if
(
player
.
getWorld
()
==
null
||
player
.
getScene
()
==
null
)
{
this
.
entryListForwardAll
.
clear
();
this
.
entryListForwardAllExceptCur
.
clear
();
this
.
entryListForwardHost
.
clear
();
...
...
src/main/java/emu/grasscutter/game/player/Player.java
View file @
0bfa1fa0
...
...
@@ -8,6 +8,7 @@ import emu.grasscutter.data.def.PlayerLevelData;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.CoopRequest
;
import
emu.grasscutter.game.ability.AbilityManager
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.avatar.AvatarProfileData
;
import
emu.grasscutter.game.avatar.AvatarStorage
;
...
...
@@ -89,6 +90,7 @@ public class Player {
@Transient
private
FriendsList
friendsList
;
@Transient
private
MailHandler
mailHandler
;
@Transient
private
MessageHandler
messageHandler
;
@Transient
private
AbilityManager
abilityManager
;
@Transient
private
SotSManager
sotsManager
;
...
...
@@ -142,6 +144,7 @@ public class Player {
this
.
friendsList
=
new
FriendsList
(
this
);
this
.
mailHandler
=
new
MailHandler
(
this
);
this
.
towerManager
=
new
TowerManager
(
this
);
this
.
abilityManager
=
new
AbilityManager
(
this
);
this
.
pos
=
new
Position
();
this
.
rotation
=
new
Position
();
this
.
properties
=
new
HashMap
<>();
...
...
@@ -1025,6 +1028,10 @@ public class Player {
public
SotSManager
getSotSManager
()
{
return
sotsManager
;
}
public
AbilityManager
getAbilityManager
()
{
return
abilityManager
;
}
public
synchronized
void
onTick
()
{
// Check ping
if
(
this
.
getLastPingTime
()
>
System
.
currentTimeMillis
()
+
60000
)
{
...
...
Prev
1
2
3
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