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
897f082b
Commit
897f082b
authored
May 08, 2022
by
Melledy
Browse files
Implement AbilityManager
parent
176f3e91
Changes
14
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/data/GameData.java
View file @
897f082b
...
@@ -9,6 +9,8 @@ import java.util.Map;
...
@@ -9,6 +9,8 @@ import java.util.Map;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
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.OpenConfigEntry
;
import
emu.grasscutter.data.custom.ScenePointEntry
;
import
emu.grasscutter.data.custom.ScenePointEntry
;
import
emu.grasscutter.data.def.*
;
import
emu.grasscutter.data.def.*
;
...
@@ -22,6 +24,7 @@ public class GameData {
...
@@ -22,6 +24,7 @@ public class GameData {
// BinOutputs
// BinOutputs
private
static
final
Int2ObjectMap
<
String
>
abilityHashes
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
String
>
abilityHashes
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Map
<
String
,
AbilityEmbryoEntry
>
abilityEmbryos
=
new
HashMap
<>();
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
,
OpenConfigEntry
>
openConfigEntries
=
new
HashMap
<>();
private
static
final
Map
<
String
,
ScenePointEntry
>
scenePointEntries
=
new
HashMap
<>();
private
static
final
Map
<
String
,
ScenePointEntry
>
scenePointEntries
=
new
HashMap
<>();
...
@@ -101,6 +104,10 @@ public class GameData {
...
@@ -101,6 +104,10 @@ public class GameData {
return
abilityEmbryos
;
return
abilityEmbryos
;
}
}
public
static
Map
<
String
,
AbilityModifierEntry
>
getAbilityModifiers
()
{
return
abilityModifiers
;
}
public
static
Map
<
String
,
OpenConfigEntry
>
getOpenConfigEntries
()
{
public
static
Map
<
String
,
OpenConfigEntry
>
getOpenConfigEntries
()
{
return
openConfigEntries
;
return
openConfigEntries
;
}
}
...
...
src/main/java/emu/grasscutter/data/ResourceLoader.java
View file @
897f082b
...
@@ -18,6 +18,11 @@ import emu.grasscutter.Grasscutter;
...
@@ -18,6 +18,11 @@ import emu.grasscutter.Grasscutter;
import
emu.grasscutter.data.common.PointData
;
import
emu.grasscutter.data.common.PointData
;
import
emu.grasscutter.data.common.ScenePointConfig
;
import
emu.grasscutter.data.common.ScenePointConfig
;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
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.OpenConfigEntry
;
import
emu.grasscutter.data.custom.ScenePointEntry
;
import
emu.grasscutter.data.custom.ScenePointEntry
;
import
emu.grasscutter.game.world.SpawnDataEntry
;
import
emu.grasscutter.game.world.SpawnDataEntry
;
...
@@ -47,6 +52,7 @@ public class ResourceLoader {
...
@@ -47,6 +52,7 @@ public class ResourceLoader {
// Load ability lists
// Load ability lists
loadAbilityEmbryos
();
loadAbilityEmbryos
();
loadOpenConfig
();
loadOpenConfig
();
loadAbilityModifiers
();
// Load resources
// Load resources
loadResources
();
loadResources
();
// Process into depots
// Process into depots
...
@@ -244,6 +250,69 @@ public class ResourceLoader {
...
@@ -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
()
{
private
static
void
loadSpawnData
()
{
// Read from cached file if exists
// Read from cached file if exists
File
spawnDataEntries
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"Spawns.json"
);
File
spawnDataEntries
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"Spawns.json"
);
...
...
src/main/java/emu/grasscutter/data/custom/AbilityModifier.java
0 → 100644
View file @
897f082b
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 @
897f082b
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/game/ability/AbilityManager.java
0 → 100644
View file @
897f082b
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.custom.AbilityModifierEntry
;
import
emu.grasscutter.game.entity.GameEntity
;
import
emu.grasscutter.game.player.Player
;
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.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
)
{
// TODO create elemental energy orbs
}
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/entity/EntityAvatar.java
View file @
897f082b
...
@@ -17,17 +17,21 @@ import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlo
...
@@ -17,17 +17,21 @@ import emu.grasscutter.net.proto.AbilityControlBlockOuterClass.AbilityControlBlo
import
emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo
;
import
emu.grasscutter.net.proto.AbilityEmbryoOuterClass.AbilityEmbryo
;
import
emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo
;
import
emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo
;
import
emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair
;
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.EntityAuthorityInfoOuterClass.EntityAuthorityInfo
;
import
emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData
;
import
emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData
;
import
emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo
;
import
emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo
;
import
emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair
;
import
emu.grasscutter.net.proto.FightPropPairOuterClass.FightPropPair
;
import
emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType
;
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.PropPairOuterClass.PropPair
;
import
emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType
;
import
emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType
;
import
emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo
;
import
emu.grasscutter.net.proto.SceneAvatarInfoOuterClass.SceneAvatarInfo
;
import
emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo
;
import
emu.grasscutter.net.proto.SceneEntityAiInfoOuterClass.SceneEntityAiInfo
;
import
emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo
;
import
emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo
;
import
emu.grasscutter.net.proto.VectorOuterClass.Vector
;
import
emu.grasscutter.net.proto.VectorOuterClass.Vector
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.ProtoHelper
;
import
emu.grasscutter.utils.ProtoHelper
;
import
emu.grasscutter.utils.Utils
;
import
emu.grasscutter.utils.Utils
;
...
@@ -110,6 +114,19 @@ public class EntityAvatar extends GameEntity {
...
@@ -110,6 +114,19 @@ public class EntityAvatar extends GameEntity {
this
.
killedBy
=
killerId
;
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
SceneAvatarInfo
getSceneAvatarInfo
()
{
public
SceneAvatarInfo
getSceneAvatarInfo
()
{
SceneAvatarInfo
.
Builder
avatarInfo
=
SceneAvatarInfo
.
newBuilder
()
SceneAvatarInfo
.
Builder
avatarInfo
=
SceneAvatarInfo
.
newBuilder
()
.
setUid
(
this
.
getPlayer
().
getUid
())
.
setUid
(
this
.
getPlayer
().
getUid
())
...
...
src/main/java/emu/grasscutter/game/entity/GameEntity.java
View file @
897f082b
package
emu.grasscutter.game.entity
;
package
emu.grasscutter.game.entity
;
import
java.util.HashMap
;
import
java.util.Map
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.LifeState
;
import
emu.grasscutter.game.props.LifeState
;
import
emu.grasscutter.game.world.Scene
;
import
emu.grasscutter.game.world.Scene
;
...
@@ -9,8 +12,11 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
...
@@ -9,8 +12,11 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import
emu.grasscutter.net.proto.MotionStateOuterClass.MotionState
;
import
emu.grasscutter.net.proto.MotionStateOuterClass.MotionState
;
import
emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo
;
import
emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo
;
import
emu.grasscutter.net.proto.VectorOuterClass.Vector
;
import
emu.grasscutter.net.proto.VectorOuterClass.Vector
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Position
;
import
it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap
;
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
{
public
abstract
class
GameEntity
{
protected
int
id
;
protected
int
id
;
...
@@ -25,6 +31,10 @@ public abstract class GameEntity {
...
@@ -25,6 +31,10 @@ public abstract class GameEntity {
private
int
lastMoveSceneTimeMs
;
private
int
lastMoveSceneTimeMs
;
private
int
lastMoveReliableSeq
;
private
int
lastMoveReliableSeq
;
// Abilities
private
Map
<
String
,
Float
>
metaOverrideMap
;
private
Int2ObjectMap
<
String
>
metaModifiers
;
public
GameEntity
(
Scene
scene
)
{
public
GameEntity
(
Scene
scene
)
{
this
.
scene
=
scene
;
this
.
scene
=
scene
;
this
.
moveState
=
MotionState
.
MOTION_NONE
;
this
.
moveState
=
MotionState
.
MOTION_NONE
;
...
@@ -54,6 +64,20 @@ public abstract class GameEntity {
...
@@ -54,6 +64,20 @@ public abstract class GameEntity {
return
isAlive
()
?
LifeState
.
LIFE_ALIVE
:
LifeState
.
LIFE_DEAD
;
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
Int2FloatOpenHashMap
getFightProperties
();
public
abstract
Position
getPosition
();
public
abstract
Position
getPosition
();
...
@@ -146,4 +170,53 @@ public abstract class GameEntity {
...
@@ -146,4 +170,53 @@ public abstract class GameEntity {
public
void
setSpawnEntry
(
SpawnDataEntry
spawnEntry
)
{
public
void
setSpawnEntry
(
SpawnDataEntry
spawnEntry
)
{
this
.
spawnEntry
=
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/player/Player.java
View file @
897f082b
...
@@ -8,6 +8,7 @@ import emu.grasscutter.data.def.PlayerLevelData;
...
@@ -8,6 +8,7 @@ import emu.grasscutter.data.def.PlayerLevelData;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.CoopRequest
;
import
emu.grasscutter.game.CoopRequest
;
import
emu.grasscutter.game.ability.AbilityManager
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.avatar.AvatarProfileData
;
import
emu.grasscutter.game.avatar.AvatarProfileData
;
import
emu.grasscutter.game.avatar.AvatarStorage
;
import
emu.grasscutter.game.avatar.AvatarStorage
;
...
@@ -89,7 +90,8 @@ public class Player {
...
@@ -89,7 +90,8 @@ public class Player {
@Transient
private
FriendsList
friendsList
;
@Transient
private
FriendsList
friendsList
;
@Transient
private
MailHandler
mailHandler
;
@Transient
private
MailHandler
mailHandler
;
@Transient
private
MessageHandler
messageHandler
;
@Transient
private
MessageHandler
messageHandler
;
@Transient
private
AbilityManager
abilityManager
;
@Transient
private
SotSManager
sotsManager
;
@Transient
private
SotSManager
sotsManager
;
private
TeamManager
teamManager
;
private
TeamManager
teamManager
;
...
@@ -142,6 +144,7 @@ public class Player {
...
@@ -142,6 +144,7 @@ public class Player {
this
.
friendsList
=
new
FriendsList
(
this
);
this
.
friendsList
=
new
FriendsList
(
this
);
this
.
mailHandler
=
new
MailHandler
(
this
);
this
.
mailHandler
=
new
MailHandler
(
this
);
this
.
towerManager
=
new
TowerManager
(
this
);
this
.
towerManager
=
new
TowerManager
(
this
);
this
.
abilityManager
=
new
AbilityManager
(
this
);
this
.
pos
=
new
Position
();
this
.
pos
=
new
Position
();
this
.
rotation
=
new
Position
();
this
.
rotation
=
new
Position
();
this
.
properties
=
new
HashMap
<>();
this
.
properties
=
new
HashMap
<>();
...
@@ -1025,6 +1028,10 @@ public class Player {
...
@@ -1025,6 +1028,10 @@ public class Player {
public
SotSManager
getSotSManager
()
{
return
sotsManager
;
}
public
SotSManager
getSotSManager
()
{
return
sotsManager
;
}
public
AbilityManager
getAbilityManager
()
{
return
abilityManager
;
}
public
synchronized
void
onTick
()
{
public
synchronized
void
onTick
()
{
// Check ping
// Check ping
if
(
this
.
getLastPingTime
()
>
System
.
currentTimeMillis
()
+
60000
)
{
if
(
this
.
getLastPingTime
()
>
System
.
currentTimeMillis
()
+
60000
)
{
...
...
src/main/java/emu/grasscutter/game/world/Scene.java
View file @
897f082b
...
@@ -385,27 +385,7 @@ public class Scene {
...
@@ -385,27 +385,7 @@ public class Scene {
}
}
// Sanity check
// Sanity check
if
(
target
.
getFightProperties
()
==
null
)
{
target
.
damage
(
result
.
getDamage
(),
result
.
getAttackerId
());
return
;
}
// Lose hp
target
.
addFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
-
result
.
getDamage
());
// Check if dead
boolean
isDead
=
false
;
if
(
target
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
)
<=
0
f
)
{
target
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
0
f
);
isDead
=
true
;
}
// Packets
this
.
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
target
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
// Check if dead
if
(
isDead
)
{
this
.
killEntity
(
target
,
result
.
getAttackerId
());
}
}
}
public
void
killEntity
(
GameEntity
target
,
int
attackerId
)
{
public
void
killEntity
(
GameEntity
target
,
int
attackerId
)
{
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerAbilityInvocationsNotify.java
View file @
897f082b
...
@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvoc
...
@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvocationsNotifyOuterClass.AbilityInvoc
import
emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry
;
import
emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.utils.Utils
;
@Opcodes
(
PacketOpcodes
.
AbilityInvocationsNotify
)
@Opcodes
(
PacketOpcodes
.
AbilityInvocationsNotify
)
public
class
HandlerAbilityInvocationsNotify
extends
PacketHandler
{
public
class
HandlerAbilityInvocationsNotify
extends
PacketHandler
{
...
@@ -15,7 +16,7 @@ public class HandlerAbilityInvocationsNotify extends PacketHandler {
...
@@ -15,7 +16,7 @@ public class HandlerAbilityInvocationsNotify extends PacketHandler {
AbilityInvocationsNotify
notif
=
AbilityInvocationsNotify
.
parseFrom
(
payload
);
AbilityInvocationsNotify
notif
=
AbilityInvocationsNotify
.
parseFrom
(
payload
);
for
(
AbilityInvokeEntry
entry
:
notif
.
getInvokesList
())
{
for
(
AbilityInvokeEntry
entry
:
notif
.
getInvokesList
())
{
//System.out.println(entry.getArgumentType() + ": " + Utils.bytesToHex(entry.getAbilityData().toByteArray())
);
session
.
getPlayer
().
getAbilityManager
().
onAbilityInvoke
(
entry
);
session
.
getPlayer
().
getAbilityInvokeHandler
().
addEntry
(
entry
.
getForwardType
(),
entry
);
session
.
getPlayer
().
getAbilityInvokeHandler
().
addEntry
(
entry
.
getForwardType
(),
entry
);
}
}
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerClientAbilityInitFinishNotify.java
View file @
897f082b
...
@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry
...
@@ -6,6 +6,7 @@ import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry
import
emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify
;
import
emu.grasscutter.net.proto.ClientAbilityInitFinishNotifyOuterClass.ClientAbilityInitFinishNotify
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.utils.Utils
;
@Opcodes
(
PacketOpcodes
.
ClientAbilityInitFinishNotify
)
@Opcodes
(
PacketOpcodes
.
ClientAbilityInitFinishNotify
)
public
class
HandlerClientAbilityInitFinishNotify
extends
PacketHandler
{
public
class
HandlerClientAbilityInitFinishNotify
extends
PacketHandler
{
...
@@ -15,6 +16,7 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
...
@@ -15,6 +16,7 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
ClientAbilityInitFinishNotify
notif
=
ClientAbilityInitFinishNotify
.
parseFrom
(
payload
);
ClientAbilityInitFinishNotify
notif
=
ClientAbilityInitFinishNotify
.
parseFrom
(
payload
);
for
(
AbilityInvokeEntry
entry
:
notif
.
getInvokesList
())
{
for
(
AbilityInvokeEntry
entry
:
notif
.
getInvokesList
())
{
session
.
getPlayer
().
getAbilityManager
().
onAbilityInvoke
(
entry
);
session
.
getPlayer
().
getClientAbilityInitFinishHandler
().
addEntry
(
entry
.
getForwardType
(),
entry
);
session
.
getPlayer
().
getClientAbilityInitFinishHandler
().
addEntry
(
entry
.
getForwardType
(),
entry
);
}
}
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java
View file @
897f082b
...
@@ -14,11 +14,6 @@ public class HandlerEvtCreateGadgetNotify extends PacketHandler {
...
@@ -14,11 +14,6 @@ public class HandlerEvtCreateGadgetNotify extends PacketHandler {
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
EvtCreateGadgetNotify
notify
=
EvtCreateGadgetNotify
.
parseFrom
(
payload
);
EvtCreateGadgetNotify
notify
=
EvtCreateGadgetNotify
.
parseFrom
(
payload
);
// Dont handle in singleplayer
if
(!
session
.
getPlayer
().
getWorld
().
isMultiplayer
())
{
return
;
}
// Sanity check - dont add duplicate entities
// Sanity check - dont add duplicate entities
if
(
session
.
getPlayer
().
getScene
().
getEntityById
(
notify
.
getEntityId
())
!=
null
)
{
if
(
session
.
getPlayer
().
getScene
().
getEntityById
(
notify
.
getEntityId
())
!=
null
)
{
return
;
return
;
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDestroyGadgetNotify.java
View file @
897f082b
...
@@ -12,11 +12,6 @@ public class HandlerEvtDestroyGadgetNotify extends PacketHandler {
...
@@ -12,11 +12,6 @@ public class HandlerEvtDestroyGadgetNotify 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
{
EvtDestroyGadgetNotify
notify
=
EvtDestroyGadgetNotify
.
parseFrom
(
payload
);
EvtDestroyGadgetNotify
notify
=
EvtDestroyGadgetNotify
.
parseFrom
(
payload
);
// Dont handle in singleplayer
if
(!
session
.
getPlayer
().
getWorld
().
isMultiplayer
())
{
return
;
}
session
.
getPlayer
().
getScene
().
onPlayerDestroyGadget
(
notify
.
getEntityId
());
session
.
getPlayer
().
getScene
().
onPlayerDestroyGadget
(
notify
.
getEntityId
());
}
}
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerSetEntityClientDataNotify.java
View file @
897f082b
...
@@ -23,7 +23,7 @@ public class HandlerSetEntityClientDataNotify extends PacketHandler {
...
@@ -23,7 +23,7 @@ public class HandlerSetEntityClientDataNotify extends PacketHandler {
BasePacket
packet
=
new
BasePacket
(
PacketOpcodes
.
SetEntityClientDataNotify
,
true
);
BasePacket
packet
=
new
BasePacket
(
PacketOpcodes
.
SetEntityClientDataNotify
,
true
);
packet
.
setData
(
notif
);
packet
.
setData
(
notif
);
session
.
getPlayer
().
getScene
().
broadcastPacket
ToOthers
(
session
.
getPlayer
(),
packet
);
session
.
getPlayer
().
getScene
().
broadcastPacket
(
packet
);
}
}
}
}
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