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
d05b3207
Commit
d05b3207
authored
Aug 04, 2022
by
Magix
Committed by
GitHub
Aug 04, 2022
Browse files
Add more events
Merge pull request #1516 from Grasscutters/more-events
parents
9a104f6f
a3e0f7f5
Changes
23
Show whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java
View file @
d05b3207
...
...
@@ -3,7 +3,7 @@ package emu.grasscutter.command.commands;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.
utils.Position
;
import
emu.grasscutter.
server.event.player.PlayerTeleportEvent.TeleportType
;
import
java.util.List
;
...
...
@@ -22,9 +22,8 @@ public final class TeleportAllCommand implements CommandHandler {
for
(
Player
player
:
targetPlayer
.
getWorld
().
getPlayers
())
{
if
(
player
.
equals
(
targetPlayer
))
continue
;
Position
pos
=
targetPlayer
.
getPosition
();
player
.
getWorld
().
transferPlayerToScene
(
player
,
targetPlayer
.
getSceneId
(),
pos
);
player
.
getWorld
().
transferPlayerToScene
(
player
,
targetPlayer
.
getSceneId
(),
TeleportType
.
COMMAND
,
targetPlayer
.
getPosition
()
);
}
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.teleportAll.success"
));
...
...
src/main/java/emu/grasscutter/command/commands/TeleportCommand.java
View file @
d05b3207
...
...
@@ -3,6 +3,7 @@ package emu.grasscutter.command.commands;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType
;
import
emu.grasscutter.utils.Position
;
import
java.util.List
;
...
...
@@ -40,20 +41,21 @@ public final class TeleportCommand implements CommandHandler {
}
// Fallthrough
case
3
:
try
{
x
=
parseRelative
(
args
.
get
(
0
),
x
);
y
=
parseRelative
(
args
.
get
(
1
),
y
);
z
=
parseRelative
(
args
.
get
(
2
),
z
);
x
=
this
.
parseRelative
(
args
.
get
(
0
),
x
);
y
=
this
.
parseRelative
(
args
.
get
(
1
),
y
);
z
=
this
.
parseRelative
(
args
.
get
(
2
),
z
);
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.teleport.invalid_position"
));
}
break
;
default
:
sendUsageMessage
(
sender
);
this
.
sendUsageMessage
(
sender
);
return
;
}
Position
target_pos
=
new
Position
(
x
,
y
,
z
);
boolean
result
=
targetPlayer
.
getWorld
().
transferPlayerToScene
(
targetPlayer
,
sceneId
,
target_pos
);
boolean
result
=
targetPlayer
.
getWorld
().
transferPlayerToScene
(
targetPlayer
,
sceneId
,
TeleportType
.
COMMAND
,
target_pos
);
if
(!
result
)
{
CommandHandler
.
sendMessage
(
sender
,
translate
(
sender
,
"commands.teleport.exists_error"
));
}
else
{
...
...
src/main/java/emu/grasscutter/game/entity/EntityAvatar.java
View file @
d05b3207
...
...
@@ -30,6 +30,7 @@ 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.event.player.PlayerMoveEvent
;
import
emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
...
...
@@ -108,12 +109,16 @@ public class EntityAvatar extends GameEntity {
@Override
public
void
onDeath
(
int
killerId
)
{
super
.
onDeath
(
killerId
);
// Invoke super class's onDeath() method.
this
.
killedType
=
PlayerDieType
.
PLAYER_DIE_TYPE_KILL_BY_MONSTER
;
this
.
killedBy
=
killerId
;
clearEnergy
(
ChangeEnergyReason
.
CHANGE_ENERGY_REASON_NONE
);
}
public
void
onDeath
(
PlayerDieType
dieType
,
int
killerId
)
{
super
.
onDeath
(
killerId
);
// Invoke super class's onDeath() method.
this
.
killedType
=
dieType
;
this
.
killedBy
=
killerId
;
clearEnergy
(
ChangeEnergyReason
.
CHANGE_ENERGY_REASON_NONE
);
...
...
@@ -314,4 +319,21 @@ public class EntityAvatar extends GameEntity {
//
return
abilityControlBlock
.
build
();
}
/**
* Move this entity to a new position.
* Additionally invoke player move event.
* @param newPosition The new position.
* @param rotation The new rotation.
*/
@Override
public
void
move
(
Position
newPosition
,
Position
rotation
)
{
// Invoke player move event.
PlayerMoveEvent
event
=
new
PlayerMoveEvent
(
this
.
getPlayer
(),
PlayerMoveEvent
.
MoveType
.
PLAYER
,
this
.
getPosition
(),
newPosition
);
event
.
call
();
// Set position and rotation.
super
.
move
(
event
.
getDestination
(),
rotation
);
}
}
src/main/java/emu/grasscutter/game/entity/EntityBaseGadget.java
View file @
d05b3207
...
...
@@ -13,6 +13,6 @@ public abstract class EntityBaseGadget extends GameEntity {
@Override
public
void
onDeath
(
int
killerId
)
{
super
.
onDeath
(
killerId
);
// Invoke super class's onDeath() method.
}
}
src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java
View file @
d05b3207
...
...
@@ -3,7 +3,6 @@ package emu.grasscutter.game.entity;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.game.world.Scene
;
import
emu.grasscutter.game.world.World
;
import
emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo
;
import
emu.grasscutter.net.proto.AnimatorParameterValueInfoPairOuterClass.AnimatorParameterValueInfoPair
;
import
emu.grasscutter.net.proto.ClientGadgetInfoOuterClass
;
...
...
@@ -11,7 +10,6 @@ import emu.grasscutter.net.proto.EntityAuthorityInfoOuterClass.EntityAuthorityIn
import
emu.grasscutter.net.proto.EntityClientDataOuterClass.EntityClientData
;
import
emu.grasscutter.net.proto.EntityRendererChangedInfoOuterClass.EntityRendererChangedInfo
;
import
emu.grasscutter.net.proto.EvtCreateGadgetNotifyOuterClass.EvtCreateGadgetNotify
;
import
emu.grasscutter.net.proto.GadgetClientParamOuterClass.GadgetClientParam
;
import
emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo
;
import
emu.grasscutter.net.proto.PropPairOuterClass.PropPair
;
import
emu.grasscutter.net.proto.ProtEntityTypeOuterClass.ProtEntityType
;
...
...
@@ -95,7 +93,7 @@ public class EntityClientGadget extends EntityBaseGadget {
@Override
public
void
onDeath
(
int
killerId
)
{
super
.
onDeath
(
killerId
);
// Invoke super class's onDeath() method.
}
@Override
...
...
src/main/java/emu/grasscutter/game/entity/EntityGadget.java
View file @
d05b3207
...
...
@@ -175,6 +175,8 @@ public class EntityGadget extends EntityBaseGadget {
@Override
public
void
onDeath
(
int
killerId
)
{
super
.
onDeath
(
killerId
);
// Invoke super class's onDeath() method.
if
(
this
.
getSpawnEntry
()
!=
null
)
{
this
.
getScene
().
getDeadSpawnedEntities
().
add
(
getSpawnEntry
());
}
...
...
src/main/java/emu/grasscutter/game/entity/EntityMonster.java
View file @
d05b3207
...
...
@@ -158,6 +158,8 @@ public class EntityMonster extends GameEntity {
@Override
public
void
onDeath
(
int
killerId
)
{
super
.
onDeath
(
killerId
);
// Invoke super class's onDeath() method.
if
(
this
.
getSpawnEntry
()
!=
null
)
{
this
.
getScene
().
getDeadSpawnedEntities
().
add
(
getSpawnEntry
());
}
...
...
src/main/java/emu/grasscutter/game/entity/GameEntity.java
View file @
d05b3207
...
...
@@ -15,6 +15,7 @@ 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.event.entity.EntityDeathEvent
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.utils.Position
;
import
it.unimi.dsi.fastutil.ints.Int2FloatMap
;
...
...
@@ -230,6 +231,17 @@ public abstract class GameEntity {
}
}
/**
* Move this entity to a new position.
* @param position The new position.
* @param rotation The new rotation.
*/
public
void
move
(
Position
position
,
Position
rotation
)
{
// Set the position and rotation.
this
.
getPosition
().
set
(
position
);
this
.
getRotation
().
set
(
rotation
);
}
/**
* Called when a player interacts with this entity
* @param player Player that is interacting with this entity
...
...
@@ -251,7 +263,9 @@ public abstract class GameEntity {
* @param killerId Entity id of the entity that killed this entity
*/
public
void
onDeath
(
int
killerId
)
{
// Invoke entity death event.
EntityDeathEvent
event
=
new
EntityDeathEvent
(
this
,
killerId
);
event
.
call
();
}
public
abstract
SceneEntityInfo
toProto
();
...
...
src/main/java/emu/grasscutter/game/managers/energy/EnergyManager.java
View file @
d05b3207
...
...
@@ -28,7 +28,6 @@ import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo;
import
emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.utils.Position
;
import
it.unimi.dsi.fastutil.ints.Int2IntMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
...
...
@@ -42,15 +41,14 @@ import java.util.Optional;
import
java.util.concurrent.ThreadLocalRandom
;
import
static
emu
.
grasscutter
.
config
.
Configuration
.
GAME_OPTIONS
;
import
static
java
.
util
.
Map
.
entry
;
import
com.google.gson.reflect.TypeToken
;
import
com.google.protobuf.InvalidProtocolBufferException
;
public
class
EnergyManager
extends
BasePlayerManager
{
private
final
Map
<
EntityAvatar
,
Integer
>
avatarNormalProbabilities
;
// energyUsage for each player
private
B
oolean
energyUsage
;
private
b
oolean
energyUsage
;
// Should energy usage be enabled for this player?
private
final
static
Int2ObjectMap
<
List
<
EnergyDropInfo
>>
energyDropData
=
new
Int2ObjectOpenHashMap
<>();
private
final
static
Int2ObjectMap
<
List
<
SkillParticleGenerationInfo
>>
skillParticleGenerationData
=
new
Int2ObjectOpenHashMap
<>();
...
...
@@ -90,9 +88,9 @@ public class EnergyManager extends BasePlayerManager {
}
}
/**
********
Particle creation for elemental skills.
*********
*/
/**
*
Particle creation for elemental skills.
*/
private
int
getBallCountForAvatar
(
int
avatarId
)
{
// We default to two particles.
int
count
=
2
;
...
...
@@ -120,12 +118,12 @@ public class EnergyManager extends BasePlayerManager {
}
private
int
getBallIdForElement
(
ElementType
element
)
{
// If we have no element, we default to an elementless particle.
// If we have no element, we default to an element
-
less particle.
if
(
element
==
null
)
{
return
2024
;
}
// Otherwise, we determin the particle's ID based on the element.
// Otherwise, we determin
e
the particle's ID based on the element.
return
switch
(
element
)
{
case
Fire
->
2017
;
case
Water
->
2018
;
...
...
@@ -156,7 +154,7 @@ public class EnergyManager extends BasePlayerManager {
int
amount
=
2
;
// Try to get the casting avatar from the player's party.
Optional
<
EntityAvatar
>
avatarEntity
=
getCastingAvatarEntityForEnergy
(
invoke
.
getEntityId
());
Optional
<
EntityAvatar
>
avatarEntity
=
this
.
getCastingAvatarEntityForEnergy
(
invoke
.
getEntityId
());
// Bug: invokes twice sometimes, Ayato, Keqing
// ToDo: deal with press, hold difference. deal with charge(Beidou, Yunjin)
...
...
@@ -174,20 +172,21 @@ public class EnergyManager extends BasePlayerManager {
// particles we have to generate.
if
(
skillDepotData
!=
null
)
{
ElementType
element
=
skillDepotData
.
getElementType
();
itemId
=
getBallIdForElement
(
element
);
itemId
=
this
.
getBallIdForElement
(
element
);
}
}
}
// Generate the particles.
for
(
int
i
=
0
;
i
<
amount
;
i
++)
{
generateElemBall
(
itemId
,
new
Position
(
action
.
getPos
()),
1
);
this
.
generateElemBall
(
itemId
,
new
Position
(
action
.
getPos
()),
1
);
}
}
/**********
Pickup of elemental particles and orbs.
**********/
/**
* Pickup of elemental particles and orbs.
* @param elemBall The elemental particle or orb.
*/
public
void
handlePickupElemBall
(
GameItem
elemBall
)
{
// Check if the item is indeed an energy particle/orb.
if
(
elemBall
.
getItemId
()
<
2001
||
elemBall
.
getItemId
()
>
2024
)
{
...
...
@@ -242,9 +241,10 @@ public class EnergyManager extends BasePlayerManager {
}
}
/**********
Energy generation for NAs/CAs.
**********/
/**
* Energy generation for NAs/CAs.
* @param avatar The avatar.
*/
private
void
generateEnergyForNormalAndCharged
(
EntityAvatar
avatar
)
{
// This logic is based on the descriptions given in
// https://genshin-impact.fandom.com/wiki/Energy#Energy_Generated_by_Normal_Attacks
...
...
@@ -290,11 +290,10 @@ public class EnergyManager extends BasePlayerManager {
// Make sure the target is an actual enemy.
GameEntity
targetEntity
=
this
.
player
.
getScene
().
getEntityById
(
attackRes
.
getDefenseId
());
if
(!(
targetEntity
instanceof
EntityMonster
))
{
if
(!(
targetEntity
instanceof
EntityMonster
targetMonster
))
{
return
;
}
EntityMonster
targetMonster
=
(
EntityMonster
)
targetEntity
;
MonsterType
targetType
=
targetMonster
.
getMonsterData
().
getType
();
if
(
targetType
!=
MonsterType
.
MONSTER_ORDINARY
&&
targetType
!=
MonsterType
.
MONSTER_BOSS
)
{
return
;
...
...
@@ -319,10 +318,10 @@ public class EnergyManager extends BasePlayerManager {
this
.
generateEnergyForNormalAndCharged
(
attackerEntity
.
get
());
}
/*
* Energy logic related to using skills.
*/
/**********
Energy logic related to using skills.
**********/
private
void
handleBurstCast
(
Avatar
avatar
,
int
skillId
)
{
// Don't do anything if energy usage is disabled.
if
(!
GAME_OPTIONS
.
energyUsage
||
!
this
.
energyUsage
)
{
...
...
@@ -351,9 +350,10 @@ public class EnergyManager extends BasePlayerManager {
this
.
handleBurstCast
(
avatar
,
skillId
);
}
/**********
Monster energy drops.
**********/
/*
* Monster energy drops.
*/
private
void
generateElemBallDrops
(
EntityMonster
monster
,
int
dropId
)
{
// Generate all drops specified for the given drop id.
if
(!
energyDropData
.
containsKey
(
dropId
))
{
...
...
@@ -365,6 +365,7 @@ public class EnergyManager extends BasePlayerManager {
this
.
generateElemBall
(
info
.
getBallId
(),
monster
.
getPosition
(),
info
.
getCount
());
}
}
public
void
handleMonsterEnergyDrop
(
EntityMonster
monster
,
float
hpBeforeDamage
,
float
hpAfterDamage
)
{
// Make sure this is actually a monster.
// Note that some wildlife also has that type, like boars or birds.
...
...
@@ -373,7 +374,7 @@ public class EnergyManager extends BasePlayerManager {
return
;
}
// Calculate the HP tresholds for before and after the damage was taken.
// Calculate the HP t
h
resholds for before and after the damage was taken.
float
maxHp
=
monster
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
);
float
thresholdBefore
=
hpBeforeDamage
/
maxHp
;
float
thresholdAfter
=
hpAfterDamage
/
maxHp
;
...
...
@@ -386,19 +387,20 @@ public class EnergyManager extends BasePlayerManager {
float
threshold
=
drop
.
getHpPercent
()
/
100.0f
;
if
(
threshold
<
thresholdBefore
&&
threshold
>=
thresholdAfter
)
{
generateElemBallDrops
(
monster
,
drop
.
getDropId
());
this
.
generateElemBallDrops
(
monster
,
drop
.
getDropId
());
}
}
// Handle kill drops.
if
(
hpAfterDamage
<=
0
&&
monster
.
getMonsterData
().
getKillDropId
()
!=
0
)
{
generateElemBallDrops
(
monster
,
monster
.
getMonsterData
().
getKillDropId
());
this
.
generateElemBallDrops
(
monster
,
monster
.
getMonsterData
().
getKillDropId
());
}
}
/**********
Utility.
**********/
/*
* Utilities.
*/
private
void
generateElemBall
(
int
ballId
,
Position
position
,
int
count
)
{
// Generate a particle/orb with the specified parameters.
ItemData
itemData
=
GameData
.
getItemDataMap
().
get
(
ballId
);
...
...
@@ -417,7 +419,7 @@ public class EnergyManager extends BasePlayerManager {
// that cast the skill.
// Try to get the invoking entity from the scene.
GameEntity
entity
=
player
.
getScene
().
getEntityById
(
invokeEntityId
);
GameEntity
entity
=
this
.
player
.
getScene
().
getEntityById
(
invokeEntityId
);
// Determine the ID of the entity that originally cast this skill. If the scene entity is null,
// or not an `EntityClientGadget`, we assume that we are directly looking at the casting avatar
...
...
@@ -430,20 +432,20 @@ public class EnergyManager extends BasePlayerManager {
:
((
EntityClientGadget
)
entity
).
getOriginalOwnerEntityId
();
// Finally, find the avatar entity in the player's team.
return
player
.
getTeamManager
().
getActiveTeam
()
return
this
.
player
.
getTeamManager
().
getActiveTeam
()
.
stream
()
.
filter
(
character
->
character
.
getId
()
==
avatarEntityId
)
.
findFirst
();
}
public
B
oolean
getEnergyUsage
()
{
return
energyUsage
;
public
b
oolean
getEnergyUsage
()
{
return
this
.
energyUsage
;
}
public
void
setEnergyUsage
(
B
oolean
energyUsage
)
{
public
void
setEnergyUsage
(
b
oolean
energyUsage
)
{
this
.
energyUsage
=
energyUsage
;
if
(!
energyUsage
)
{
// Refill team energy if usage is disabled
for
(
EntityAvatar
entityAvatar
:
player
.
getTeamManager
().
getActiveTeam
())
{
for
(
EntityAvatar
entityAvatar
:
this
.
player
.
getTeamManager
().
getActiveTeam
())
{
entityAvatar
.
addEnergy
(
1000
,
PropChangeReason
.
PROP_CHANGE_REASON_GM
,
true
);
}
}
...
...
src/main/java/emu/grasscutter/game/managers/mapmark/MapMarksManager.java
View file @
d05b3207
...
...
@@ -5,11 +5,11 @@ import emu.grasscutter.game.player.Player;
import
emu.grasscutter.net.proto.MapMarkPointTypeOuterClass.MapMarkPointType
;
import
emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq
;
import
emu.grasscutter.net.proto.MarkMapReqOuterClass.MarkMapReq.Operation
;
import
emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType
;
import
emu.grasscutter.server.packet.send.PacketMarkMapRsp
;
import
emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify
;
import
emu.grasscutter.utils.Position
;
import
java.util.HashMap
;
import
java.util.Map
;
public
class
MapMarksManager
extends
BasePlayerManager
{
...
...
@@ -20,7 +20,7 @@ public class MapMarksManager extends BasePlayerManager {
}
public
Map
<
String
,
MapMark
>
getMapMarks
()
{
return
getPlayer
().
getMapMarks
();
return
this
.
getPlayer
().
getMapMarks
();
}
public
void
handleMapMarkReq
(
MarkMapReq
req
)
{
...
...
@@ -30,26 +30,26 @@ public class MapMarksManager extends BasePlayerManager {
MapMark
createMark
=
new
MapMark
(
req
.
getMark
());
// keep teleporting functionality on fishhook mark.
if
(
createMark
.
getMapMarkPointType
()
==
MapMarkPointType
.
MAP_MARK_POINT_TYPE_FISH_POOL
)
{
teleport
(
player
,
createMark
);
this
.
teleport
(
player
,
createMark
);
return
;
}
addMapMark
(
createMark
);
this
.
addMapMark
(
createMark
);
}
case
OPERATION_MOD
->
{
MapMark
oldMark
=
new
MapMark
(
req
.
getOld
());
removeMapMark
(
oldMark
.
getPosition
());
this
.
removeMapMark
(
oldMark
.
getPosition
());
MapMark
newMark
=
new
MapMark
(
req
.
getMark
());
addMapMark
(
newMark
);
this
.
addMapMark
(
newMark
);
}
case
OPERATION_DEL
->
{
MapMark
deleteMark
=
new
MapMark
(
req
.
getMark
());
removeMapMark
(
deleteMark
.
getPosition
());
this
.
removeMapMark
(
deleteMark
.
getPosition
());
}
}
if
(
op
!=
Operation
.
OPERATION_GET
)
{
save
();
this
.
save
();
}
player
.
getSession
().
send
(
new
PacketMarkMapRsp
(
getMapMarks
()));
player
.
getSession
().
send
(
new
PacketMarkMapRsp
(
this
.
getMapMarks
()));
}
public
String
getMapMarkKey
(
Position
position
)
{
...
...
@@ -57,27 +57,25 @@ public class MapMarksManager extends BasePlayerManager {
}
public
void
removeMapMark
(
Position
position
)
{
getMapMarks
().
remove
(
getMapMarkKey
(
position
));
this
.
getMapMarks
().
remove
(
this
.
getMapMarkKey
(
position
));
}
public
void
addMapMark
(
MapMark
mapMark
)
{
if
(
getMapMarks
().
size
()
<
mapMarkMaxCount
)
{
getMapMarks
().
put
(
getMapMarkKey
(
mapMark
.
getPosition
()),
mapMark
);
if
(
this
.
getMapMarks
().
size
()
<
mapMarkMaxCount
)
{
this
.
getMapMarks
().
put
(
this
.
getMapMarkKey
(
mapMark
.
getPosition
()),
mapMark
);
}
}
private
void
teleport
(
Player
player
,
MapMark
mapMark
)
{
float
y
;
try
{
y
=
(
f
loat
)
Integer
.
parse
In
t
(
mapMark
.
getName
());
y
=
F
loat
.
parse
Floa
t
(
mapMark
.
getName
());
}
catch
(
Exception
e
)
{
y
=
300
;
}
Position
pos
=
mapMark
.
getPosition
();
player
.
getPosition
().
set
(
pos
.
getX
(),
y
,
pos
.
getZ
());
if
(
mapMark
.
getSceneId
()
!=
player
.
getSceneId
())
{
player
.
getWorld
().
transferPlayerToScene
(
player
,
mapMark
.
getSceneId
(),
player
.
getPosition
());
}
player
.
getWorld
().
transferPlayerToScene
(
player
,
mapMark
.
getSceneId
(),
TeleportType
.
MAP
,
new
Position
(
pos
.
getX
(),
y
,
pos
.
getZ
()));
player
.
getScene
().
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
player
));
}
}
src/main/java/emu/grasscutter/game/player/TeamManager.java
View file @
d05b3207
...
...
@@ -20,6 +20,7 @@ import emu.grasscutter.net.packet.PacketOpcodes;
import
emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType
;
import
emu.grasscutter.net.proto.MotionStateOuterClass.MotionState
;
import
emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType
;
import
emu.grasscutter.server.event.player.PlayerTeamDeathEvent
;
import
emu.grasscutter.server.packet.send.PacketAvatarDieAnimationEndRsp
;
import
emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify
;
...
...
@@ -76,7 +77,7 @@ public class TeamManager extends BasePlayerDataManager {
}
public
World
getWorld
()
{
return
getPlayer
().
getWorld
();
return
this
.
getPlayer
().
getWorld
();
}
public
Map
<
Integer
,
TeamInfo
>
getTeams
()
{
...
...
@@ -123,7 +124,7 @@ public class TeamManager extends BasePlayerDataManager {
}
public
long
getCurrentCharacterGuid
()
{
return
getCurrentAvatarEntity
().
getAvatar
().
getGuid
();
return
this
.
getCurrentAvatarEntity
().
getAvatar
().
getGuid
();
}
public
TeamInfo
getCurrentTeamInfo
()
{
...
...
@@ -166,20 +167,20 @@ public class TeamManager extends BasePlayerDataManager {
}
public
EntityAvatar
getCurrentAvatarEntity
()
{
return
getActiveTeam
().
get
(
currentCharacterIndex
);
return
this
.
getActiveTeam
().
get
(
currentCharacterIndex
);
}
public
boolean
isSpawned
()
{
return
getPlayer
().
getScene
()
!=
null
&&
getPlayer
().
getScene
().
getEntities
().
containsKey
(
getCurrentAvatarEntity
().
getId
());
return
this
.
getPlayer
().
getScene
()
!=
null
&&
this
.
getPlayer
().
getScene
().
getEntities
().
containsKey
(
this
.
getCurrentAvatarEntity
().
getId
());
}
public
int
getMaxTeamSize
()
{
if
(
getPlayer
().
isInMultiplayer
())
{
if
(
this
.
getPlayer
().
isInMultiplayer
())
{
int
max
=
GAME_OPTIONS
.
avatarLimits
.
multiplayerTeam
;
if
(
getPlayer
().
getWorld
().
getHost
()
==
this
.
getPlayer
())
{
return
Math
.
max
(
1
,
(
int
)
Math
.
ceil
(
max
/
(
double
)
getWorld
().
getPlayerCount
()));
if
(
this
.
getPlayer
().
getWorld
().
getHost
()
==
this
.
getPlayer
())
{
return
Math
.
max
(
1
,
(
int
)
Math
.
ceil
(
max
/
(
double
)
this
.
getWorld
().
getPlayerCount
()));
}
return
Math
.
max
(
1
,
(
int
)
Math
.
floor
(
max
/
(
double
)
getWorld
().
getPlayerCount
()));
return
Math
.
max
(
1
,
(
int
)
Math
.
floor
(
max
/
(
double
)
this
.
getWorld
().
getPlayerCount
()));
}
return
GAME_OPTIONS
.
avatarLimits
.
singlePlayerTeam
;
...
...
@@ -191,14 +192,14 @@ public class TeamManager extends BasePlayerDataManager {
* Returns true if there is space to add the number of avatars to the team.
*/
public
boolean
canAddAvatarsToTeam
(
TeamInfo
team
,
int
avatars
)
{
return
team
.
size
()
+
avatars
<=
getMaxTeamSize
();
return
team
.
size
()
+
avatars
<=
this
.
getMaxTeamSize
();
}
/**
* Returns true if there is space to add to the team.
*/
public
boolean
canAddAvatarToTeam
(
TeamInfo
team
)
{
return
canAddAvatarsToTeam
(
team
,
1
);
return
this
.
canAddAvatarsToTeam
(
team
,
1
);
}
/**
...
...
@@ -209,7 +210,7 @@ public class TeamManager extends BasePlayerDataManager {
if
(
this
.
useTemporarilyTeamIndex
!=
-
1
)
{
return
false
;
}
return
canAddAvatarsToTeam
(
this
.
getCurrentTeamInfo
(),
avatars
);
return
this
.
canAddAvatarsToTeam
(
this
.
getCurrentTeamInfo
(),
avatars
);
}
/**
...
...
@@ -217,7 +218,7 @@ public class TeamManager extends BasePlayerDataManager {
* If the current team is temporary, returns false.
*/
public
boolean
canAddAvatarToCurrentTeam
()
{
return
canAddAvatarsToCurrentTeam
(
1
);
return
this
.
canAddAvatarsToCurrentTeam
(
1
);
}
/**
...
...
@@ -226,7 +227,7 @@ public class TeamManager extends BasePlayerDataManager {
* If some can not be added, returns false and does not add any.
*/
public
boolean
addAvatarsToTeam
(
TeamInfo
team
,
Collection
<
Avatar
>
avatars
)
{
if
(!
canAddAvatarsToTeam
(
team
,
avatars
.
size
()))
{
if
(!
this
.
canAddAvatarsToTeam
(
team
,
avatars
.
size
()))
{
return
false
;
}
...
...
@@ -237,20 +238,20 @@ public class TeamManager extends BasePlayerDataManager {
if
(
this
.
getPlayer
().
isInMultiplayer
())
{
if
(
team
.
equals
(
this
.
getMpTeam
()))
{
// MP team Packet
this
.
updateTeamEntities
(
new
PacketChangeMpTeamAvatarRsp
(
getPlayer
(),
team
));
this
.
updateTeamEntities
(
new
PacketChangeMpTeamAvatarRsp
(
this
.
getPlayer
(),
team
));
}
}
else
{
// SP team update packet
getPlayer
().
sendPacket
(
new
PacketAvatarTeamUpdateNotify
(
getPlayer
()));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarTeamUpdateNotify
(
this
.
getPlayer
()));
int
teamId
=
this
.
getTeamId
(
team
);
if
(
teamId
!=
-
1
)
{
// This is one of the player's teams
// Update entites
if
(
teamId
==
this
.
getCurrentTeamId
())
{
this
.
updateTeamEntities
(
new
PacketSetUpAvatarTeamRsp
(
getPlayer
(),
teamId
,
team
));
this
.
updateTeamEntities
(
new
PacketSetUpAvatarTeamRsp
(
this
.
getPlayer
(),
teamId
,
team
));
}
else
{
getPlayer
().
sendPacket
(
new
PacketSetUpAvatarTeamRsp
(
getPlayer
(),
teamId
,
team
));
this
.
getPlayer
().
sendPacket
(
new
PacketSetUpAvatarTeamRsp
(
this
.
getPlayer
(),
teamId
,
team
));
}
}
}
...
...
@@ -263,7 +264,7 @@ public class TeamManager extends BasePlayerDataManager {
* Returns true if successful.
*/
public
boolean
addAvatarToTeam
(
TeamInfo
team
,
Avatar
avatar
)
{
return
addAvatarsToTeam
(
team
,
Collections
.
singleton
(
avatar
));
return
this
.
addAvatarsToTeam
(
team
,
Collections
.
singleton
(
avatar
));
}
/**
...
...
@@ -276,7 +277,7 @@ public class TeamManager extends BasePlayerDataManager {
if
(
this
.
useTemporarilyTeamIndex
!=
-
1
)
{
return
false
;
}
return
addAvatarsToTeam
(
this
.
getCurrentTeamInfo
(),
avatars
);
return
this
.
addAvatarsToTeam
(
this
.
getCurrentTeamInfo
(),
avatars
);
}
/**
...
...
@@ -285,7 +286,7 @@ public class TeamManager extends BasePlayerDataManager {
* Returns true if successful.
*/
public
boolean
addAvatarToCurrentTeam
(
Avatar
avatar
)
{
return
addAvatarsToCurrentTeam
(
Collections
.
singleton
(
avatar
));
return
this
.
addAvatarsToCurrentTeam
(
Collections
.
singleton
(
avatar
));
}
private
void
updateTeamResonances
()
{
...
...
@@ -294,7 +295,7 @@ public class TeamManager extends BasePlayerDataManager {
this
.
getTeamResonances
().
clear
();
this
.
getTeamResonancesConfig
().
clear
();
for
(
EntityAvatar
entity
:
getActiveTeam
())
{
for
(
EntityAvatar
entity
:
this
.
getActiveTeam
())
{
AvatarSkillDepotData
skillData
=
entity
.
getAvatar
().
getAvatarData
().
getSkillDepot
();
if
(
skillData
!=
null
)
{
map
.
addTo
(
skillData
.
getElementType
().
getValue
(),
1
);
...
...
@@ -329,7 +330,7 @@ public class TeamManager extends BasePlayerDataManager {
Int2ObjectMap
<
EntityAvatar
>
existingAvatars
=
new
Int2ObjectOpenHashMap
<>();
int
prevSelectedAvatarIndex
=
-
1
;
for
(
EntityAvatar
entity
:
getActiveTeam
())
{
for
(
EntityAvatar
entity
:
this
.
getActiveTeam
())
{
existingAvatars
.
put
(
entity
.
getAvatar
().
getAvatarId
(),
entity
);
}
...
...
@@ -348,7 +349,7 @@ public class TeamManager extends BasePlayerDataManager {
prevSelectedAvatarIndex
=
i
;
}
}
else
{
entity
=
new
EntityAvatar
(
getPlayer
().
getScene
(),
getPlayer
().
getAvatars
().
getAvatarById
(
avatarId
));
entity
=
new
EntityAvatar
(
this
.
getPlayer
().
getScene
(),
this
.
getPlayer
().
getAvatars
().
getAvatarById
(
avatarId
));
}
this
.
getActiveTeam
().
add
(
entity
);
...
...
@@ -356,7 +357,7 @@ public class TeamManager extends BasePlayerDataManager {
// Unload removed entities
for
(
EntityAvatar
entity
:
existingAvatars
.
values
())
{
getPlayer
().
getScene
().
removeEntity
(
entity
);
this
.
getPlayer
().
getScene
().
removeEntity
(
entity
);
entity
.
getAvatar
().
save
();
}
...
...
@@ -368,33 +369,33 @@ public class TeamManager extends BasePlayerDataManager {
this
.
currentCharacterIndex
=
prevSelectedAvatarIndex
;
// Update team resonances
updateTeamResonances
();
this
.
updateTeamResonances
();
// Packets
getPlayer
().
getWorld
().
broadcastPacket
(
new
PacketSceneTeamUpdateNotify
(
getPlayer
()));
this
.
getPlayer
().
getWorld
().
broadcastPacket
(
new
PacketSceneTeamUpdateNotify
(
this
.
getPlayer
()));
// Skill charges packet - Yes, this is official server behavior as of 2.6.0
for
(
EntityAvatar
entity
:
getActiveTeam
())
{
for
(
EntityAvatar
entity
:
this
.
getActiveTeam
())
{
if
(
entity
.
getAvatar
().
getSkillExtraChargeMap
().
size
()
>
0
)
{
getPlayer
().
sendPacket
(
new
PacketAvatarSkillInfoNotify
(
entity
.
getAvatar
()));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarSkillInfoNotify
(
entity
.
getAvatar
()));
}
}
// Run callback
if
(
responsePacket
!=
null
)
{
getPlayer
().
sendPacket
(
responsePacket
);
this
.
getPlayer
().
sendPacket
(
responsePacket
);
}
// Check if character changed
if
(
currentEntity
!=
getCurrentAvatarEntity
())
{
if
(
currentEntity
!=
this
.
getCurrentAvatarEntity
())
{
// Remove and Add
getPlayer
().
getScene
().
replaceEntity
(
currentEntity
,
getCurrentAvatarEntity
());
this
.
getPlayer
().
getScene
().
replaceEntity
(
currentEntity
,
this
.
getCurrentAvatarEntity
());
}
}
public
synchronized
void
setupAvatarTeam
(
int
teamId
,
List
<
Long
>
list
)
{
// Sanity checks
if
(
list
.
size
()
==
0
||
list
.
size
()
>
getMaxTeamSize
()
||
getPlayer
().
isInMultiplayer
())
{
if
(
list
.
size
()
==
0
||
list
.
size
()
>
this
.
getMaxTeamSize
()
||
this
.
getPlayer
().
isInMultiplayer
())
{
return
;
}
...
...
@@ -407,7 +408,7 @@ public class TeamManager extends BasePlayerDataManager {
// Set team data
LinkedHashSet
<
Avatar
>
newTeam
=
new
LinkedHashSet
<>();
for
(
Long
aLong
:
list
)
{
Avatar
avatar
=
getPlayer
().
getAvatars
().
getAvatarByGuid
(
aLong
);
Avatar
avatar
=
this
.
getPlayer
().
getAvatars
().
getAvatarByGuid
(
aLong
);
if
(
avatar
==
null
||
newTeam
.
contains
(
avatar
))
{
// Should never happen
return
;
...
...
@@ -422,7 +423,7 @@ public class TeamManager extends BasePlayerDataManager {
public
void
setupMpTeam
(
List
<
Long
>
list
)
{
// Sanity checks
if
(
list
.
size
()
==
0
||
list
.
size
()
>
getMaxTeamSize
()
||
!
getPlayer
().
isInMultiplayer
())
{
if
(
list
.
size
()
==
0
||
list
.
size
()
>
this
.
getMaxTeamSize
()
||
!
this
.
getPlayer
().
isInMultiplayer
())
{
return
;
}
...
...
@@ -431,7 +432,7 @@ public class TeamManager extends BasePlayerDataManager {
// Set team data
LinkedHashSet
<
Avatar
>
newTeam
=
new
LinkedHashSet
<>();
for
(
Long
aLong
:
list
)
{
Avatar
avatar
=
getPlayer
().
getAvatars
().
getAvatarByGuid
(
aLong
);
Avatar
avatar
=
this
.
getPlayer
().
getAvatars
().
getAvatarByGuid
(
aLong
);
if
(
avatar
==
null
||
newTeam
.
contains
(
avatar
))
{
// Should never happen
return
;
...
...
@@ -447,14 +448,14 @@ public class TeamManager extends BasePlayerDataManager {
public
void
setupTemporaryTeam
(
List
<
List
<
Long
>>
guidList
)
{
this
.
temporaryTeam
=
guidList
.
stream
().
map
(
list
->
{
// Sanity checks
if
(
list
.
size
()
==
0
||
list
.
size
()
>
getMaxTeamSize
())
{
if
(
list
.
size
()
==
0
||
list
.
size
()
>
this
.
getMaxTeamSize
())
{
return
null
;
}
// Set team data
LinkedHashSet
<
Avatar
>
newTeam
=
new
LinkedHashSet
<>();
for
(
Long
aLong
:
list
)
{
Avatar
avatar
=
getPlayer
().
getAvatars
().
getAvatarByGuid
(
aLong
);
Avatar
avatar
=
this
.
getPlayer
().
getAvatars
().
getAvatarByGuid
(
aLong
);
if
(
avatar
==
null
||
newTeam
.
contains
(
avatar
))
{
// Should never happen
return
null
;
...
...
@@ -474,7 +475,7 @@ public class TeamManager extends BasePlayerDataManager {
public
void
useTemporaryTeam
(
int
index
)
{
this
.
useTemporarilyTeamIndex
=
index
;
updateTeamEntities
(
null
);
this
.
updateTeamEntities
(
null
);
}
public
void
cleanTemporaryTeam
()
{
...
...
@@ -485,11 +486,11 @@ public class TeamManager extends BasePlayerDataManager {
this
.
useTemporarilyTeamIndex
=
-
1
;
this
.
temporaryTeam
=
null
;
updateTeamEntities
(
null
);
this
.
updateTeamEntities
(
null
);
}
public
synchronized
void
setCurrentTeam
(
int
teamId
)
{
//
if
(
getPlayer
().
isInMultiplayer
())
{
if
(
this
.
getPlayer
().
isInMultiplayer
())
{
return
;
}
...
...
@@ -514,7 +515,7 @@ public class TeamManager extends BasePlayerDataManager {
teamInfo
.
setName
(
teamName
);
// Packet
getPlayer
().
sendPacket
(
new
PacketChangeTeamNameRsp
(
teamId
,
teamName
));
this
.
getPlayer
().
sendPacket
(
new
PacketChangeTeamNameRsp
(
teamId
,
teamName
));
}
public
synchronized
void
changeAvatar
(
long
guid
)
{
...
...
@@ -526,10 +527,10 @@ public class TeamManager extends BasePlayerDataManager {
EntityAvatar
newEntity
=
null
;
int
index
=
-
1
;
for
(
int
i
=
0
;
i
<
getActiveTeam
().
size
();
i
++)
{
if
(
guid
==
getActiveTeam
().
get
(
i
).
getAvatar
().
getGuid
())
{
for
(
int
i
=
0
;
i
<
this
.
getActiveTeam
().
size
();
i
++)
{
if
(
guid
==
this
.
getActiveTeam
().
get
(
i
).
getAvatar
().
getGuid
())
{
index
=
i
;
newEntity
=
getActiveTeam
().
get
(
i
);
newEntity
=
this
.
getActiveTeam
().
get
(
i
);
}
}
...
...
@@ -544,8 +545,8 @@ public class TeamManager extends BasePlayerDataManager {
oldEntity
.
setMotionState
(
MotionState
.
MOTION_STATE_STANDBY
);
// Remove and Add
getPlayer
().
getScene
().
replaceEntity
(
oldEntity
,
newEntity
);
getPlayer
().
sendPacket
(
new
PacketChangeAvatarRsp
(
guid
));
this
.
getPlayer
().
getScene
().
replaceEntity
(
oldEntity
,
newEntity
);
this
.
getPlayer
().
sendPacket
(
new
PacketChangeAvatarRsp
(
guid
));
}
public
void
onAvatarDie
(
long
dieGuid
)
{
...
...
@@ -562,7 +563,7 @@ public class TeamManager extends BasePlayerDataManager {
// Died in water. Do not replace
// The official server has skipped this notify and will just respawn the team immediately after the animation.
// TODO: Perhaps find a way to get vanilla experience?
getPlayer
().
sendPacket
(
new
PacketWorldPlayerDieNotify
(
dieType
,
killedBy
));
this
.
getPlayer
().
sendPacket
(
new
PacketWorldPlayerDieNotify
(
dieType
,
killedBy
));
}
else
{
// Replacement avatar
EntityAvatar
replacement
=
null
;
...
...
@@ -579,20 +580,24 @@ public class TeamManager extends BasePlayerDataManager {
if
(
replacement
==
null
)
{
// No more living team members...
getPlayer
().
sendPacket
(
new
PacketWorldPlayerDieNotify
(
dieType
,
killedBy
));
this
.
getPlayer
().
sendPacket
(
new
PacketWorldPlayerDieNotify
(
dieType
,
killedBy
));
// Invoke player team death event.
PlayerTeamDeathEvent
event
=
new
PlayerTeamDeathEvent
(
this
.
getPlayer
(),
this
.
getActiveTeam
().
get
(
this
.
getCurrentCharacterIndex
()));
event
.
call
();
}
else
{
// Set index and spawn replacement member
this
.
setCurrentCharacterIndex
(
replaceIndex
);
getPlayer
().
getScene
().
addEntity
(
replacement
);
this
.
getPlayer
().
getScene
().
addEntity
(
replacement
);
}
}
// Response packet
getPlayer
().
sendPacket
(
new
PacketAvatarDieAnimationEndRsp
(
deadAvatar
.
getId
(),
0
));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarDieAnimationEndRsp
(
deadAvatar
.
getId
(),
0
));
}
public
boolean
reviveAvatar
(
Avatar
avatar
)
{
for
(
EntityAvatar
entity
:
getActiveTeam
())
{
for
(
EntityAvatar
entity
:
this
.
getActiveTeam
())
{
if
(
entity
.
getAvatar
()
==
avatar
)
{
if
(
entity
.
isAlive
())
{
return
false
;
...
...
@@ -602,8 +607,8 @@ public class TeamManager extends BasePlayerDataManager {
FightProperty
.
FIGHT_PROP_CUR_HP
,
entity
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
)
*
.
1
f
);
getPlayer
().
sendPacket
(
new
PacketAvatarFightPropUpdateNotify
(
entity
.
getAvatar
(),
FightProperty
.
FIGHT_PROP_CUR_HP
));
getPlayer
().
sendPacket
(
new
PacketAvatarLifeStateChangeNotify
(
entity
.
getAvatar
()));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarFightPropUpdateNotify
(
entity
.
getAvatar
(),
FightProperty
.
FIGHT_PROP_CUR_HP
));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarLifeStateChangeNotify
(
entity
.
getAvatar
()));
return
true
;
}
}
...
...
@@ -612,7 +617,7 @@ public class TeamManager extends BasePlayerDataManager {
}
public
boolean
healAvatar
(
Avatar
avatar
,
int
healRate
,
int
healAmount
)
{
for
(
EntityAvatar
entity
:
getActiveTeam
())
{
for
(
EntityAvatar
entity
:
this
.
getActiveTeam
())
{
if
(
entity
.
getAvatar
()
==
avatar
)
{
if
(!
entity
.
isAlive
())
{
return
false
;
...
...
@@ -627,8 +632,8 @@ public class TeamManager extends BasePlayerDataManager {
entity
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
)
)
);
getPlayer
().
sendPacket
(
new
PacketAvatarFightPropUpdateNotify
(
entity
.
getAvatar
(),
FightProperty
.
FIGHT_PROP_CUR_HP
));
getPlayer
().
sendPacket
(
new
PacketAvatarLifeStateChangeNotify
(
entity
.
getAvatar
()));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarFightPropUpdateNotify
(
entity
.
getAvatar
(),
FightProperty
.
FIGHT_PROP_CUR_HP
));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarLifeStateChangeNotify
(
entity
.
getAvatar
()));
return
true
;
}
}
...
...
@@ -646,29 +651,29 @@ public class TeamManager extends BasePlayerDataManager {
player
.
getStaminaManager
().
stopSustainedStaminaHandler
();
// prevent drowning immediately after respawn
// Revive all team members
for
(
EntityAvatar
entity
:
getActiveTeam
())
{
for
(
EntityAvatar
entity
:
this
.
getActiveTeam
())
{
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
entity
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
)
*
.
4
f
);
getPlayer
().
sendPacket
(
new
PacketAvatarFightPropUpdateNotify
(
entity
.
getAvatar
(),
FightProperty
.
FIGHT_PROP_CUR_HP
));
getPlayer
().
sendPacket
(
new
PacketAvatarLifeStateChangeNotify
(
entity
.
getAvatar
()));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarFightPropUpdateNotify
(
entity
.
getAvatar
(),
FightProperty
.
FIGHT_PROP_CUR_HP
));
this
.
getPlayer
().
sendPacket
(
new
PacketAvatarLifeStateChangeNotify
(
entity
.
getAvatar
()));
}
// Teleport player
getPlayer
().
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
getPlayer
(),
EnterType
.
ENTER_TYPE_SELF
,
EnterReason
.
Revival
,
3
,
GameConstants
.
START_POSITION
));
this
.
getPlayer
().
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
this
.
getPlayer
(),
EnterType
.
ENTER_TYPE_SELF
,
EnterReason
.
Revival
,
3
,
GameConstants
.
START_POSITION
));
// Set player position
player
.
setSceneId
(
3
);
player
.
getPosition
().
set
(
GameConstants
.
START_POSITION
);
// Packets
getPlayer
().
sendPacket
(
new
BasePacket
(
PacketOpcodes
.
WorldPlayerReviveRsp
));
this
.
getPlayer
().
sendPacket
(
new
BasePacket
(
PacketOpcodes
.
WorldPlayerReviveRsp
));
}
public
void
saveAvatars
()
{
// Save all avatars from active team
for
(
EntityAvatar
entity
:
getActiveTeam
())
{
for
(
EntityAvatar
entity
:
this
.
getActiveTeam
())
{
entity
.
getAvatar
().
save
();
}
}
...
...
src/main/java/emu/grasscutter/game/systems/InventorySystem.java
View file @
d05b3207
...
...
@@ -30,6 +30,7 @@ import emu.grasscutter.game.shop.ShopChestBatchUseTable;
import
emu.grasscutter.game.shop.ShopChestTable
;
import
emu.grasscutter.net.proto.ItemParamOuterClass.ItemParam
;
import
emu.grasscutter.net.proto.MaterialInfoOuterClass.MaterialInfo
;
import
emu.grasscutter.server.event.player.PlayerUseFoodEvent
;
import
emu.grasscutter.server.game.BaseGameSystem
;
import
emu.grasscutter.server.game.GameServer
;
import
emu.grasscutter.server.packet.send.*
;
...
...
@@ -812,37 +813,48 @@ public class InventorySystem extends BaseGameSystem {
int
used
=
0
;
boolean
useSuccess
=
false
;
ItemData
itemData
=
useItem
.
getItemData
();
// Use
switch
(
useItem
.
getI
temData
()
.
getMaterialType
())
{
switch
(
i
temData
.
getMaterialType
())
{
case
MATERIAL_FOOD:
if
(
useItem
.
getI
temData
()
.
getUseTarget
()
==
ItemUseTarget
.
ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR
)
{
if
(
i
temData
.
getUseTarget
()
==
ItemUseTarget
.
ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR
)
{
if
(
target
==
null
)
{
break
;
}
// Invoke player use food event.
PlayerUseFoodEvent
event
=
new
PlayerUseFoodEvent
(
player
,
itemData
,
target
.
getAsEntity
());
// Call the event.
event
.
call
();
if
(!
event
.
isCanceled
())
{
used
=
player
.
getTeamManager
().
reviveAvatar
(
target
)
?
1
:
0
;
}
}
else
{
used
=
1
;
}
break
;
case
MATERIAL_NOTICE_ADD_HP:
if
(
useItem
.
getI
temData
()
.
getUseTarget
()
==
ItemUseTarget
.
ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR
)
{
if
(
i
temData
.
getUseTarget
()
==
ItemUseTarget
.
ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR
)
{
if
(
target
==
null
)
{
break
;
}
int
[]
SatiationParams
=
useItem
.
getItemData
().
getSatiationParams
();
// Invoke player use food event.
PlayerUseFoodEvent
event
=
new
PlayerUseFoodEvent
(
player
,
itemData
,
target
.
getAsEntity
());
// Call the event.
event
.
call
();
if
(!
event
.
isCanceled
())
{
int
[]
SatiationParams
=
itemData
.
getSatiationParams
();
used
=
player
.
getTeamManager
().
healAvatar
(
target
,
SatiationParams
[
0
],
SatiationParams
[
1
])
?
1
:
0
;
}
}
break
;
case
MATERIAL_CONSUME:
// Make sure we have usage data for this material.
if
(
useItem
.
getI
temData
()
.
getItemUse
()
==
null
)
{
if
(
i
temData
.
getItemUse
()
==
null
)
{
break
;
}
ItemUseOp
useOp
=
useItem
.
getI
temData
()
.
getItemUse
().
get
(
0
).
getUseOp
();
ItemUseOp
useOp
=
i
temData
.
getItemUse
().
get
(
0
).
getUseOp
();
// Unlock item based on use operation
useSuccess
=
switch
(
useOp
)
{
...
...
@@ -854,7 +866,7 @@ public class InventorySystem extends BaseGameSystem {
break
;
case
MATERIAL_FURNITURE_FORMULA:
case
MATERIAL_FURNITURE_SUITE_FORMULA:
if
(
useItem
.
getI
temData
()
.
getItemUse
()
==
null
)
{
if
(
i
temData
.
getItemUse
()
==
null
)
{
break
;
}
useSuccess
=
player
.
getFurnitureManager
().
unlockFurnitureOrSuite
(
useItem
);
...
...
@@ -862,7 +874,7 @@ public class InventorySystem extends BaseGameSystem {
break
;
case
MATERIAL_CONSUME_BATCH_USE:
// Make sure we have usage data for this material.
if
(
useItem
.
getI
temData
()
.
getItemUse
()
==
null
)
{
if
(
i
temData
.
getItemUse
()
==
null
)
{
break
;
}
...
...
@@ -889,11 +901,11 @@ public class InventorySystem extends BaseGameSystem {
}
for
(
ItemParamData
itemParamData
:
shopChestTable
.
getContainsItem
())
{
ItemData
itemData
=
GameData
.
getItemDataMap
().
get
(
itemParamData
.
getId
());
if
(
itemData
==
null
)
{
ItemData
containedItem
=
GameData
.
getItemDataMap
().
get
(
itemParamData
.
getId
());
if
(
containedItem
==
null
)
{
continue
;
}
rewardItemList
.
add
(
new
GameItem
(
itemData
,
itemParamData
.
getCount
()));
rewardItemList
.
add
(
new
GameItem
(
containedItem
,
itemParamData
.
getCount
()));
}
if
(!
rewardItemList
.
isEmpty
())
{
...
...
@@ -919,12 +931,12 @@ public class InventorySystem extends BaseGameSystem {
}
int
optionItemId
=
shopChestBatchUseTable
.
getOptionItem
().
get
(
optionId
-
1
);
ItemData
itemData
=
GameData
.
getItemDataMap
().
get
(
optionItemId
);
if
(
itemData
==
null
)
{
ItemData
optionItem
=
GameData
.
getItemDataMap
().
get
(
optionItemId
);
if
(
optionItem
==
null
)
{
break
;
}
player
.
getInventory
().
addItem
(
new
GameItem
(
itemData
,
count
),
ActionReason
.
Shop
);
player
.
getInventory
().
addItem
(
new
GameItem
(
optionItem
,
count
),
ActionReason
.
Shop
);
used
=
count
;
break
;
...
...
@@ -944,7 +956,7 @@ public class InventorySystem extends BaseGameSystem {
// we return the item to make UseItemRsp a success.
if
(
used
>
0
)
{
// Handle use params, mainly server buffs
for
(
ItemUseData
useData
:
useItem
.
getI
temData
()
.
getItemUse
())
{
for
(
ItemUseData
useData
:
i
temData
.
getItemUse
())
{
switch
(
useData
.
getUseOp
())
{
case
ITEM_USE_ADD_SERVER_BUFF
->
{
int
buffId
=
Integer
.
parseInt
(
useData
.
getUseParam
()[
0
]);
...
...
src/main/java/emu/grasscutter/game/world/World.java
View file @
d05b3207
...
...
@@ -17,6 +17,8 @@ import emu.grasscutter.data.excels.SceneData;
import
emu.grasscutter.net.packet.BasePacket
;
import
emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType
;
import
emu.grasscutter.scripts.data.SceneConfig
;
import
emu.grasscutter.server.event.player.PlayerTeleportEvent
;
import
emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType
;
import
emu.grasscutter.server.game.GameServer
;
import
emu.grasscutter.server.packet.send.PacketDelTeamEntityNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify
;
...
...
@@ -53,7 +55,7 @@ public class World implements Iterable<Player> {
this
.
players
=
Collections
.
synchronizedList
(
new
ArrayList
<>());
this
.
scenes
=
Int2ObjectMaps
.
synchronize
(
new
Int2ObjectOpenHashMap
<>());
this
.
levelEntityId
=
getNextEntityId
(
EntityIdType
.
MPLEVEL
);
this
.
levelEntityId
=
this
.
getNextEntityId
(
EntityIdType
.
MPLEVEL
);
this
.
worldLevel
=
player
.
getWorldLevel
();
this
.
isMultiplayer
=
isMultiplayer
;
...
...
@@ -101,7 +103,7 @@ public class World implements Iterable<Player> {
public
Scene
getSceneById
(
int
sceneId
)
{
// Get scene normally
Scene
scene
=
getScenes
().
get
(
sceneId
);
Scene
scene
=
this
.
getScenes
().
get
(
sceneId
);
if
(
scene
!=
null
)
{
return
scene
;
}
...
...
@@ -118,7 +120,7 @@ public class World implements Iterable<Player> {
}
public
int
getPlayerCount
()
{
return
getPlayers
().
size
();
return
this
.
getPlayers
().
size
();
}
public
boolean
isMultiplayer
()
{
...
...
@@ -131,7 +133,7 @@ public class World implements Iterable<Player> {
public
synchronized
void
addPlayer
(
Player
player
)
{
// Check if player already in
if
(
getPlayers
().
contains
(
player
))
{
if
(
this
.
getPlayers
().
contains
(
player
))
{
return
;
}
...
...
@@ -142,11 +144,11 @@ public class World implements Iterable<Player> {
// Register
player
.
setWorld
(
this
);
getPlayers
().
add
(
player
);
this
.
getPlayers
().
add
(
player
);
// Set player variables
player
.
setPeerId
(
this
.
getNextPeerId
());
player
.
getTeamManager
().
setEntityId
(
getNextEntityId
(
EntityIdType
.
TEAM
));
player
.
getTeamManager
().
setEntityId
(
this
.
getNextEntityId
(
EntityIdType
.
TEAM
));
// Copy main team to multiplayer team
if
(
this
.
isMultiplayer
())
{
...
...
@@ -169,12 +171,12 @@ public class World implements Iterable<Player> {
player
.
sendPacket
(
new
PacketDelTeamEntityNotify
(
player
.
getSceneId
(),
getPlayers
().
stream
().
map
(
p
->
p
.
getTeamManager
().
getEntityId
()).
collect
(
Collectors
.
toList
())
this
.
getPlayers
().
stream
().
map
(
p
->
p
.
getTeamManager
().
getEntityId
()).
collect
(
Collectors
.
toList
())
)
);
// Deregister
getPlayers
().
remove
(
player
);
this
.
getPlayers
().
remove
(
player
);
player
.
setWorld
(
null
);
// Remove from scene
...
...
@@ -187,7 +189,7 @@ public class World implements Iterable<Player> {
}
// Disband world if host leaves
if
(
getHost
()
==
player
)
{
if
(
this
.
getHost
()
==
player
)
{
List
<
Player
>
kicked
=
new
ArrayList
<>(
this
.
getPlayers
());
for
(
Player
victim
:
kicked
)
{
World
world
=
new
World
(
victim
);
...
...
@@ -207,14 +209,28 @@ public class World implements Iterable<Player> {
}
public
boolean
transferPlayerToScene
(
Player
player
,
int
sceneId
,
Position
pos
)
{
return
transferPlayerToScene
(
player
,
sceneId
,
null
,
pos
);
return
this
.
transferPlayerToScene
(
player
,
sceneId
,
TeleportType
.
INTERNAL
,
null
,
pos
);
}
public
boolean
transferPlayerToScene
(
Player
player
,
int
sceneId
,
TeleportType
teleportType
,
Position
pos
)
{
return
this
.
transferPlayerToScene
(
player
,
sceneId
,
teleportType
,
null
,
pos
);
}
public
boolean
transferPlayerToScene
(
Player
player
,
int
sceneId
,
DungeonData
data
)
{
return
transferPlayerToScene
(
player
,
sceneId
,
data
,
null
);
return
this
.
transferPlayerToScene
(
player
,
sceneId
,
TeleportType
.
DUNGEON
,
data
,
null
);
}
public
boolean
transferPlayerToScene
(
Player
player
,
int
sceneId
,
TeleportType
teleportType
,
DungeonData
dungeonData
,
Position
teleportTo
)
{
// Call player teleport event.
PlayerTeleportEvent
event
=
new
PlayerTeleportEvent
(
player
,
teleportType
,
player
.
getPosition
(),
teleportTo
);
// Call event & check if it was canceled.
event
.
call
();
if
(
event
.
isCanceled
())
{
return
false
;
// Teleport was canceled.
}
public
boolean
transferPlayerToScene
(
Player
player
,
int
sceneId
,
DungeonData
dungeonData
,
Position
pos
)
{
// Set the destination.
teleportTo
=
event
.
getDestination
();
if
(
GameData
.
getSceneDataMap
().
get
(
sceneId
)
==
null
)
{
return
false
;
}
...
...
@@ -224,7 +240,7 @@ public class World implements Iterable<Player> {
if
(
player
.
getScene
()
!=
null
)
{
oldScene
=
player
.
getScene
();
// Dont deregister scenes if the player is going to tp back into them
// Don
'
t deregister scenes if the player is going to tp back into them
if
(
oldScene
.
getId
()
==
sceneId
)
{
oldScene
.
setDontDestroyWhenEmpty
(
true
);
}
...
...
@@ -238,9 +254,9 @@ public class World implements Iterable<Player> {
// Dungeon
SceneConfig
config
=
newScene
.
getScriptManager
().
getConfig
();
if
(
pos
==
null
&&
config
!=
null
)
{
if
(
teleportTo
==
null
&&
config
!=
null
)
{
if
(
config
.
born_pos
!=
null
)
{
pos
=
newScene
.
getScriptManager
().
getConfig
().
born_pos
;
teleportTo
=
newScene
.
getScriptManager
().
getConfig
().
born_pos
;
}
if
(
config
.
born_rot
!=
null
)
{
player
.
getRotation
().
set
(
config
.
born_rot
);
...
...
@@ -248,11 +264,11 @@ public class World implements Iterable<Player> {
}
// Set player position
if
(
pos
==
null
)
{
pos
=
player
.
getPosition
();
if
(
teleportTo
==
null
)
{
teleportTo
=
player
.
getPosition
();
}
player
.
getPosition
().
set
(
pos
);
player
.
getPosition
().
set
(
teleportTo
);
if
(
oldScene
!=
null
)
{
newScene
.
setPrevScene
(
oldScene
.
getId
());
...
...
@@ -276,12 +292,12 @@ public class World implements Iterable<Player> {
}
// Teleport packet
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
enterType
,
enterReason
,
sceneId
,
pos
));
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
enterType
,
enterReason
,
sceneId
,
teleportTo
));
return
true
;
}
private
void
updatePlayerInfos
(
Player
paramPlayer
)
{
for
(
Player
player
:
getPlayers
())
{
for
(
Player
player
:
this
.
getPlayers
())
{
// Dont send packets if player is logging in and filter out joining player
if
(!
player
.
hasSentLoginPackets
()
||
player
==
paramPlayer
)
{
continue
;
...
...
@@ -326,6 +342,6 @@ public class World implements Iterable<Player> {
@Override
public
Iterator
<
Player
>
iterator
()
{
return
getPlayers
().
iterator
();
return
this
.
getPlayers
().
iterator
();
}
}
src/main/java/emu/grasscutter/server/event/entity/EntityDeathEvent.java
0 → 100644
View file @
d05b3207
package
emu.grasscutter.server.event.entity
;
import
emu.grasscutter.game.entity.GameEntity
;
import
emu.grasscutter.server.event.types.EntityEvent
;
import
emu.grasscutter.utils.Location
;
import
lombok.Getter
;
import
javax.annotation.Nullable
;
public
final
class
EntityDeathEvent
extends
EntityEvent
{
@Getter
private
final
Location
deathLocation
;
@Getter
@Nullable
private
final
GameEntity
killer
;
public
EntityDeathEvent
(
GameEntity
entity
,
int
killerId
)
{
super
(
entity
);
this
.
deathLocation
=
new
Location
(
entity
.
getScene
(),
entity
.
getPosition
());
this
.
killer
=
entity
.
getScene
().
getEntityById
(
killerId
);
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/event/game/CommandResponseEvent.java
deleted
100644 → 0
View file @
9a104f6f
package
emu.grasscutter.server.event.game
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.types.ServerEvent
;
/**
* @deprecated Will be removed in 1.2.3-dev or 1.3.0.
*/
@Deprecated
(
since
=
"1.2.2-dev"
,
forRemoval
=
true
)
public
final
class
CommandResponseEvent
extends
ServerEvent
{
private
String
message
;
private
Player
player
;
public
CommandResponseEvent
(
Type
type
,
Player
player
,
String
message
)
{
super
(
type
);
this
.
message
=
message
;
this
.
player
=
player
;
}
public
String
getMessage
()
{
return
message
;
}
public
Player
getPlayer
()
{
return
player
;
}
}
src/main/java/emu/grasscutter/server/event/player/PlayerMoveEvent.java
0 → 100644
View file @
d05b3207
package
emu.grasscutter.server.event.player
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.types.PlayerEvent
;
import
emu.grasscutter.utils.Position
;
/**
* TODO: Allow plugins to change the position of the player.
*/
public
final
class
PlayerMoveEvent
extends
PlayerEvent
{
private
final
MoveType
type
;
private
final
Position
from
;
private
final
Position
to
;
public
PlayerMoveEvent
(
Player
player
,
MoveType
type
,
Position
from
,
Position
to
)
{
super
(
player
);
this
.
type
=
type
;
this
.
from
=
from
;
this
.
to
=
to
;
}
public
MoveType
getMoveType
()
{
return
this
.
type
;
}
public
Position
getSource
()
{
return
this
.
from
;
}
public
Position
getDestination
()
{
return
this
.
to
;
}
public
enum
MoveType
{
/**
* The player has sent a combat invocation to move.
*/
PLAYER
,
/**
* The server has requested that the player moves.
*/
SERVER
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/event/player/PlayerTeamDeathEvent.java
0 → 100644
View file @
d05b3207
package
emu.grasscutter.server.event.player
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.types.PlayerEvent
;
import
lombok.Getter
;
/**
* This event is invoked when the ENTIRE TEAM dies.
* To listen for one player death, use {@link emu.grasscutter.server.event.entity.EntityDeathEvent}.
*/
public
final
class
PlayerTeamDeathEvent
extends
PlayerEvent
{
@Getter
private
final
EntityAvatar
selectedAvatar
;
public
PlayerTeamDeathEvent
(
Player
player
,
EntityAvatar
selectedAvatar
)
{
super
(
player
);
this
.
selectedAvatar
=
selectedAvatar
;
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/event/player/PlayerTeleportEvent.java
0 → 100644
View file @
d05b3207
package
emu.grasscutter.server.event.player
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.Cancellable
;
import
emu.grasscutter.server.event.types.PlayerEvent
;
import
emu.grasscutter.utils.Position
;
public
final
class
PlayerTeleportEvent
extends
PlayerEvent
implements
Cancellable
{
private
final
TeleportType
type
;
private
final
Position
from
;
private
Position
to
;
public
PlayerTeleportEvent
(
Player
player
,
TeleportType
type
,
Position
from
,
Position
to
)
{
super
(
player
);
this
.
type
=
type
;
this
.
from
=
from
;
this
.
to
=
to
;
}
public
TeleportType
getTeleportType
()
{
return
this
.
type
;
}
public
Position
getSource
()
{
return
this
.
from
;
}
public
Position
getDestination
()
{
return
this
.
to
;
}
public
void
setDestination
(
Position
to
)
{
this
.
to
=
to
;
}
public
enum
TeleportType
{
/**
* There is no specified reason to teleport.
*/
INTERNAL
,
/**
* The player has asked to teleport to a waypoint.
*/
WAYPOINT
,
/**
* The player has asked to teleport using the map.
*/
MAP
,
/**
* The player has asked to teleport into a dungeon.
*/
DUNGEON
,
/**
* The player has asked to teleport using the command.
*/
COMMAND
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/event/player/PlayerUseFoodEvent.java
0 → 100644
View file @
d05b3207
package
emu.grasscutter.server.event.player
;
import
emu.grasscutter.data.excels.ItemData
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.server.event.Cancellable
;
import
emu.grasscutter.server.event.types.PlayerEvent
;
import
lombok.Getter
;
import
lombok.Setter
;
/**
* This event is invoked when the player uses food on an avatar.
*/
public
final
class
PlayerUseFoodEvent
extends
PlayerEvent
implements
Cancellable
{
@Getter
@Setter
private
ItemData
foodUsed
;
@Getter
private
final
EntityAvatar
selectedAvatar
;
public
PlayerUseFoodEvent
(
Player
player
,
ItemData
foodUsed
,
EntityAvatar
selectedAvatar
)
{
super
(
player
);
this
.
foodUsed
=
foodUsed
;
this
.
selectedAvatar
=
selectedAvatar
;
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java
View file @
d05b3207
...
...
@@ -60,8 +60,7 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
new
Position
(
motionInfo
.
getRot
()),
motionState
);
event
.
call
();
entity
.
getPosition
().
set
(
motionInfo
.
getPos
());
entity
.
getRotation
().
set
(
motionInfo
.
getRot
());
entity
.
move
(
event
.
getPosition
(),
event
.
getRotation
());
entity
.
setLastMoveSceneTimeMs
(
moveInfo
.
getSceneTime
());
entity
.
setLastMoveReliableSeq
(
moveInfo
.
getReliableSeq
());
entity
.
setMotionState
(
motionState
);
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment