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
bee654c6
Commit
bee654c6
authored
Apr 18, 2022
by
Melledy
Browse files
Implement support for multiple scenes in a world
parent
eaba8bc1
Changes
30
Show whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/commands/PlayerCommands.java
View file @
bee654c6
...
@@ -170,12 +170,12 @@ public class PlayerCommands {
...
@@ -170,12 +170,12 @@ public class PlayerCommands {
float
range
=
(
5
f
+
(.
1
f
*
count
));
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityItem
entity
=
new
EntityItem
(
player
.
get
World
(),
player
,
itemData
,
pos
,
1
);
EntityItem
entity
=
new
EntityItem
(
player
.
get
Scene
(),
player
,
itemData
,
pos
,
1
);
player
.
get
World
().
addEntity
(
entity
);
player
.
get
Scene
().
addEntity
(
entity
);
}
}
}
else
{
}
else
{
EntityItem
entity
=
new
EntityItem
(
player
.
get
World
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
count
);
EntityItem
entity
=
new
EntityItem
(
player
.
get
Scene
(),
player
,
itemData
,
player
.
getPos
().
clone
().
addY
(
3
f
),
count
);
player
.
get
World
().
addEntity
(
entity
);
player
.
get
Scene
().
addEntity
(
entity
);
}
}
}
}
}
}
...
@@ -216,8 +216,8 @@ public class PlayerCommands {
...
@@ -216,8 +216,8 @@ public class PlayerCommands {
float
range
=
(
5
f
+
(.
1
f
*
count
));
float
range
=
(
5
f
+
(.
1
f
*
count
));
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
Position
pos
=
player
.
getPos
().
clone
().
addX
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
)).
addY
(
3
f
).
addZ
((
float
)
(
Math
.
random
()
*
range
)
-
(
range
/
2
));
EntityMonster
entity
=
new
EntityMonster
(
player
.
get
World
(),
monsterData
,
pos
,
level
);
EntityMonster
entity
=
new
EntityMonster
(
player
.
get
Scene
(),
monsterData
,
pos
,
level
);
player
.
get
World
().
addEntity
(
entity
);
player
.
get
Scene
().
addEntity
(
entity
);
}
}
}
}
}
}
...
@@ -227,12 +227,12 @@ public class PlayerCommands {
...
@@ -227,12 +227,12 @@ public class PlayerCommands {
@Override
@Override
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
public
void
execute
(
GenshinPlayer
player
,
String
raw
)
{
List
<
GenshinEntity
>
toRemove
=
new
LinkedList
<>();
List
<
GenshinEntity
>
toRemove
=
new
LinkedList
<>();
for
(
GenshinEntity
entity
:
player
.
get
World
().
getEntities
().
values
())
{
for
(
GenshinEntity
entity
:
player
.
get
Scene
().
getEntities
().
values
())
{
if
(
entity
instanceof
EntityMonster
)
{
if
(
entity
instanceof
EntityMonster
)
{
toRemove
.
add
(
entity
);
toRemove
.
add
(
entity
);
}
}
}
}
toRemove
.
forEach
(
e
->
player
.
get
World
().
killEntity
(
e
,
0
));
toRemove
.
forEach
(
e
->
player
.
get
Scene
().
killEntity
(
e
,
0
));
}
}
}
}
...
@@ -286,7 +286,7 @@ public class PlayerCommands {
...
@@ -286,7 +286,7 @@ public class PlayerCommands {
}
}
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
hp
);
entity
.
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
hp
);
entity
.
get
World
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
entity
.
get
Scene
().
broadcastPacket
(
new
PacketEntityFightPropUpdateNotify
(
entity
,
FightProperty
.
FIGHT_PROP_CUR_HP
));
}
}
}
}
...
...
src/main/java/emu/grasscutter/game/GenshinPlayer.java
View file @
bee654c6
...
@@ -83,6 +83,7 @@ public class GenshinPlayer {
...
@@ -83,6 +83,7 @@ public class GenshinPlayer {
@Transient
private
long
nextGuid
=
0
;
@Transient
private
long
nextGuid
=
0
;
@Transient
private
int
peerId
;
@Transient
private
int
peerId
;
@Transient
private
World
world
;
@Transient
private
World
world
;
@Transient
private
GenshinScene
scene
;
@Transient
private
GameSession
session
;
@Transient
private
GameSession
session
;
@Transient
private
AvatarStorage
avatars
;
@Transient
private
AvatarStorage
avatars
;
@Transient
private
Inventory
inventory
;
@Transient
private
Inventory
inventory
;
...
@@ -206,6 +207,14 @@ public class GenshinPlayer {
...
@@ -206,6 +207,14 @@ public class GenshinPlayer {
this
.
world
=
world
;
this
.
world
=
world
;
}
}
public
GenshinScene
getScene
()
{
return
scene
;
}
public
void
setScene
(
GenshinScene
scene
)
{
this
.
scene
=
scene
;
}
public
int
getGmLevel
()
{
public
int
getGmLevel
()
{
return
1
;
return
1
;
}
}
...
@@ -560,14 +569,14 @@ public class GenshinPlayer {
...
@@ -560,14 +569,14 @@ public class GenshinPlayer {
}
}
public
void
interactWith
(
int
gadgetEntityId
)
{
public
void
interactWith
(
int
gadgetEntityId
)
{
GenshinEntity
entity
=
get
World
().
getEntityById
(
gadgetEntityId
);
GenshinEntity
entity
=
get
Scene
().
getEntityById
(
gadgetEntityId
);
if
(
entity
==
null
)
{
if
(
entity
==
null
)
{
return
;
return
;
}
}
// Delete
// Delete
entity
.
get
World
().
removeEntity
(
entity
);
entity
.
get
Scene
().
removeEntity
(
entity
);
// Handle
// Handle
if
(
entity
instanceof
EntityItem
)
{
if
(
entity
instanceof
EntityItem
)
{
...
...
src/main/java/emu/grasscutter/game/GenshinScene.java
0 → 100644
View file @
bee654c6
package
emu.grasscutter.game
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.List
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.entity.EntityClientGadget
;
import
emu.grasscutter.game.entity.EntityGadget
;
import
emu.grasscutter.game.entity.GenshinEntity
;
import
emu.grasscutter.game.props.ClimateType
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.LifeState
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult
;
import
emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify
;
import
emu.grasscutter.server.packet.send.PacketSceneEntityDisappearNotify
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
class
GenshinScene
{
private
final
World
world
;
private
final
List
<
GenshinPlayer
>
players
;
private
final
Int2ObjectMap
<
GenshinEntity
>
entities
;
private
final
int
id
;
private
int
time
;
private
ClimateType
climate
;
public
GenshinScene
(
World
world
,
int
sceneId
)
{
this
.
world
=
world
;
this
.
players
=
Collections
.
synchronizedList
(
new
ArrayList
<>());
this
.
entities
=
new
Int2ObjectOpenHashMap
<>();
this
.
id
=
sceneId
;
this
.
time
=
8
*
60
;
this
.
climate
=
ClimateType
.
CLIMATE_SUNNY
;
}
public
int
getId
()
{
return
id
;
}
public
World
getWorld
()
{
return
world
;
}
public
List
<
GenshinPlayer
>
getPlayers
()
{
return
players
;
}
public
int
getPlayerCount
()
{
return
this
.
getPlayers
().
size
();
}
public
Int2ObjectMap
<
GenshinEntity
>
getEntities
()
{
return
entities
;
}
public
GenshinEntity
getEntityById
(
int
id
)
{
return
this
.
entities
.
get
(
id
);
}
public
int
getTime
()
{
return
time
;
}
public
void
changeTime
(
int
time
)
{
this
.
time
=
time
%
1440
;
}
public
ClimateType
getClimate
()
{
return
climate
;
}
public
void
setClimate
(
ClimateType
climate
)
{
this
.
climate
=
climate
;
}
public
boolean
isInScene
(
GenshinEntity
entity
)
{
return
this
.
entities
.
containsKey
(
entity
.
getId
());
}
public
void
addPlayer
(
GenshinPlayer
player
)
{
// Check if player already in
if
(
getPlayers
().
contains
(
player
))
{
return
;
}
// Remove player from prev scene
if
(
player
.
getScene
()
!=
null
)
{
player
.
getScene
().
removePlayer
(
player
);
}
// Add
getPlayers
().
add
(
player
);
player
.
setSceneId
(
this
.
getId
());
player
.
setScene
(
this
);
this
.
setupPlayerAvatars
(
player
);
}
public
void
removePlayer
(
GenshinPlayer
player
)
{
getPlayers
().
remove
(
player
);
player
.
setScene
(
null
);
// Remove player avatars
this
.
removePlayerAvatars
(
player
);
// Remove player gadgets
for
(
EntityGadget
gadget
:
player
.
getTeamManager
().
getGadgets
())
{
this
.
removeEntity
(
gadget
);
}
}
private
void
setupPlayerAvatars
(
GenshinPlayer
player
)
{
// Clear entities from old team
player
.
getTeamManager
().
getActiveTeam
().
clear
();
// Add new entities for player
TeamInfo
teamInfo
=
player
.
getTeamManager
().
getCurrentTeamInfo
();
for
(
int
avatarId
:
teamInfo
.
getAvatars
())
{
EntityAvatar
entity
=
new
EntityAvatar
(
player
.
getScene
(),
player
.
getAvatars
().
getAvatarById
(
avatarId
));
player
.
getTeamManager
().
getActiveTeam
().
add
(
entity
);
}
// Limit character index in case its out of bounds
if
(
player
.
getTeamManager
().
getCurrentCharacterIndex
()
>=
player
.
getTeamManager
().
getActiveTeam
().
size
()
||
player
.
getTeamManager
().
getCurrentCharacterIndex
()
<
0
)
{
player
.
getTeamManager
().
setCurrentCharacterIndex
(
player
.
getTeamManager
().
getCurrentCharacterIndex
()
-
1
);
}
}
private
void
removePlayerAvatars
(
GenshinPlayer
player
)
{
Iterator
<
EntityAvatar
>
it
=
player
.
getTeamManager
().
getActiveTeam
().
iterator
();
while
(
it
.
hasNext
())
{
this
.
removeEntity
(
it
.
next
(),
VisionType
.
VisionRemove
);
it
.
remove
();
}
}
public
void
spawnPlayer
(
GenshinPlayer
player
)
{
if
(
this
.
isInScene
(
player
.
getTeamManager
().
getCurrentAvatarEntity
()))
{
return
;
}
if
(
player
.
getTeamManager
().
getCurrentAvatarEntity
().
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
)
<=
0
f
)
{
player
.
getTeamManager
().
getCurrentAvatarEntity
().
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
1
f
);
}
this
.
addEntity
(
player
.
getTeamManager
().
getCurrentAvatarEntity
());
}
private
void
addEntityDirectly
(
GenshinEntity
entity
)
{
getEntities
().
put
(
entity
.
getId
(),
entity
);
}
public
synchronized
void
addEntity
(
GenshinEntity
entity
)
{
this
.
addEntityDirectly
(
entity
);
this
.
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
entity
));
}
public
synchronized
void
addEntities
(
Collection
<
GenshinEntity
>
entities
)
{
for
(
GenshinEntity
entity
:
entities
)
{
this
.
addEntityDirectly
(
entity
);
}
this
.
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
entities
,
VisionType
.
VisionBorn
));
}
private
GenshinEntity
removeEntityDirectly
(
GenshinEntity
entity
)
{
return
getEntities
().
remove
(
entity
.
getId
());
}
public
void
removeEntity
(
GenshinEntity
entity
)
{
this
.
removeEntity
(
entity
,
VisionType
.
VisionDie
);
}
public
synchronized
void
removeEntity
(
GenshinEntity
entity
,
VisionType
visionType
)
{
GenshinEntity
removed
=
this
.
removeEntityDirectly
(
entity
);
if
(
removed
!=
null
)
{
this
.
broadcastPacket
(
new
PacketSceneEntityDisappearNotify
(
removed
,
visionType
));
}
}
public
synchronized
void
replaceEntity
(
EntityAvatar
oldEntity
,
EntityAvatar
newEntity
)
{
this
.
removeEntityDirectly
(
oldEntity
);
this
.
addEntityDirectly
(
newEntity
);
this
.
broadcastPacket
(
new
PacketSceneEntityDisappearNotify
(
oldEntity
,
VisionType
.
VisionReplace
));
this
.
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
newEntity
,
VisionType
.
VisionReplace
,
oldEntity
.
getId
()));
}
public
void
showOtherEntities
(
GenshinPlayer
player
)
{
List
<
GenshinEntity
>
entities
=
new
LinkedList
<>();
GenshinEntity
currentEntity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
for
(
GenshinEntity
entity
:
this
.
getEntities
().
values
())
{
if
(
entity
==
currentEntity
)
{
continue
;
}
entities
.
add
(
entity
);
}
player
.
sendPacket
(
new
PacketSceneEntityAppearNotify
(
entities
,
VisionType
.
VisionMeet
));
}
public
void
handleAttack
(
AttackResult
result
)
{
//GenshinEntity attacker = getEntityById(result.getAttackerId());
GenshinEntity
target
=
getEntityById
(
result
.
getDefenseId
());
if
(
target
==
null
)
{
return
;
}
// Godmode check
if
(
target
instanceof
EntityAvatar
)
{
if
(((
EntityAvatar
)
target
).
getPlayer
().
hasGodmode
())
{
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
(
GenshinEntity
target
,
int
attackerId
)
{
// Packet
this
.
broadcastPacket
(
new
PacketLifeStateChangeNotify
(
attackerId
,
target
,
LifeState
.
LIFE_DEAD
));
this
.
removeEntity
(
target
);
// Death event
target
.
onDeath
(
attackerId
);
}
// Gadgets
public
void
onPlayerCreateGadget
(
EntityClientGadget
gadget
)
{
// Directly add
this
.
addEntityDirectly
(
gadget
);
// Add to owner's gadget list
gadget
.
getOwner
().
getTeamManager
().
getGadgets
().
add
(
gadget
);
// Optimization
if
(
this
.
getPlayerCount
()
==
1
&&
this
.
getPlayers
().
get
(
0
)
==
gadget
.
getOwner
())
{
return
;
}
this
.
broadcastPacketToOthers
(
gadget
.
getOwner
(),
new
PacketSceneEntityAppearNotify
(
gadget
));
}
public
void
onPlayerDestroyGadget
(
int
entityId
)
{
GenshinEntity
entity
=
getEntities
().
get
(
entityId
);
if
(
entity
==
null
||
!(
entity
instanceof
EntityClientGadget
))
{
return
;
}
// Get and remove entity
EntityClientGadget
gadget
=
(
EntityClientGadget
)
entity
;
this
.
removeEntityDirectly
(
gadget
);
// Remove from owner's gadget list
gadget
.
getOwner
().
getTeamManager
().
getGadgets
().
remove
(
gadget
);
// Optimization
if
(
this
.
getPlayerCount
()
==
1
&&
this
.
getPlayers
().
get
(
0
)
==
gadget
.
getOwner
())
{
return
;
}
this
.
broadcastPacketToOthers
(
gadget
.
getOwner
(),
new
PacketSceneEntityDisappearNotify
(
gadget
,
VisionType
.
VisionDie
));
}
// Broadcasting
public
void
broadcastPacket
(
GenshinPacket
packet
)
{
// Send to all players - might have to check if player has been sent data packets
for
(
GenshinPlayer
player
:
this
.
getPlayers
())
{
player
.
getSession
().
send
(
packet
);
}
}
public
void
broadcastPacketToOthers
(
GenshinPlayer
excludedPlayer
,
GenshinPacket
packet
)
{
// Optimization
if
(
this
.
getPlayerCount
()
==
1
&&
this
.
getPlayers
().
get
(
0
)
==
excludedPlayer
)
{
return
;
}
// Send to all players - might have to check if player has been sent data packets
for
(
GenshinPlayer
player
:
this
.
getPlayers
())
{
if
(
player
==
excludedPlayer
)
{
continue
;
}
// Send
player
.
getSession
().
send
(
packet
);
}
}
}
src/main/java/emu/grasscutter/game/InvokeHandler.java
View file @
bee654c6
...
@@ -46,12 +46,12 @@ public class InvokeHandler<T> {
...
@@ -46,12 +46,12 @@ public class InvokeHandler<T> {
try
{
try
{
if
(
entryListForwardAll
.
size
()
>
0
)
{
if
(
entryListForwardAll
.
size
()
>
0
)
{
GenshinPacket
packet
=
packetClass
.
getDeclaredConstructor
(
List
.
class
).
newInstance
(
this
.
entryListForwardAll
);
GenshinPacket
packet
=
packetClass
.
getDeclaredConstructor
(
List
.
class
).
newInstance
(
this
.
entryListForwardAll
);
player
.
get
World
().
broadcastPacket
(
packet
);
player
.
get
Scene
().
broadcastPacket
(
packet
);
this
.
entryListForwardAll
.
clear
();
this
.
entryListForwardAll
.
clear
();
}
}
if
(
entryListForwardAllExceptCur
.
size
()
>
0
)
{
if
(
entryListForwardAllExceptCur
.
size
()
>
0
)
{
GenshinPacket
packet
=
packetClass
.
getDeclaredConstructor
(
List
.
class
).
newInstance
(
this
.
entryListForwardAllExceptCur
);
GenshinPacket
packet
=
packetClass
.
getDeclaredConstructor
(
List
.
class
).
newInstance
(
this
.
entryListForwardAllExceptCur
);
player
.
get
World
().
broadcastPacketToOthers
(
player
,
packet
);
player
.
get
Scene
().
broadcastPacketToOthers
(
player
,
packet
);
this
.
entryListForwardAllExceptCur
.
clear
();
this
.
entryListForwardAllExceptCur
.
clear
();
}
}
if
(
entryListForwardHost
.
size
()
>
0
)
{
if
(
entryListForwardHost
.
size
()
>
0
)
{
...
...
src/main/java/emu/grasscutter/game/TeamManager.java
View file @
bee654c6
...
@@ -158,7 +158,7 @@ public class TeamManager {
...
@@ -158,7 +158,7 @@ public class TeamManager {
}
}
public
boolean
isSpawned
()
{
public
boolean
isSpawned
()
{
return
getPlayer
().
getWorld
()
!=
null
&&
getPlayer
().
get
World
().
getEntities
().
containsKey
(
getCurrentAvatarEntity
().
getId
());
return
getPlayer
().
getWorld
()
!=
null
&&
getPlayer
().
get
Scene
().
getEntities
().
containsKey
(
getCurrentAvatarEntity
().
getId
());
}
}
public
int
getMaxTeamSize
()
{
public
int
getMaxTeamSize
()
{
...
@@ -233,7 +233,7 @@ public class TeamManager {
...
@@ -233,7 +233,7 @@ public class TeamManager {
prevSelectedAvatarIndex
=
i
;
prevSelectedAvatarIndex
=
i
;
}
}
}
else
{
}
else
{
entity
=
new
EntityAvatar
(
getPlayer
().
get
World
(),
getPlayer
().
getAvatars
().
getAvatarById
(
avatarId
));
entity
=
new
EntityAvatar
(
getPlayer
().
get
Scene
(),
getPlayer
().
getAvatars
().
getAvatarById
(
avatarId
));
}
}
this
.
getActiveTeam
().
add
(
entity
);
this
.
getActiveTeam
().
add
(
entity
);
...
@@ -241,7 +241,7 @@ public class TeamManager {
...
@@ -241,7 +241,7 @@ public class TeamManager {
// Unload removed entities
// Unload removed entities
for
(
EntityAvatar
entity
:
existingAvatars
.
values
())
{
for
(
EntityAvatar
entity
:
existingAvatars
.
values
())
{
getPlayer
().
get
World
().
removeEntity
(
entity
);
getPlayer
().
get
Scene
().
removeEntity
(
entity
);
entity
.
getAvatar
().
save
();
entity
.
getAvatar
().
save
();
}
}
...
@@ -256,7 +256,7 @@ public class TeamManager {
...
@@ -256,7 +256,7 @@ public class TeamManager {
updateTeamResonances
();
updateTeamResonances
();
// Packets
// Packets
getPlayer
().
get
World
().
broadcastPacket
(
new
PacketSceneTeamUpdateNotify
(
getPlayer
()));
getPlayer
().
get
Scene
().
broadcastPacket
(
new
PacketSceneTeamUpdateNotify
(
getPlayer
()));
// Run callback
// Run callback
if
(
responsePacket
!=
null
)
{
if
(
responsePacket
!=
null
)
{
...
@@ -266,7 +266,7 @@ public class TeamManager {
...
@@ -266,7 +266,7 @@ public class TeamManager {
// Check if character changed
// Check if character changed
if
(
currentEntity
!=
getCurrentAvatarEntity
())
{
if
(
currentEntity
!=
getCurrentAvatarEntity
())
{
// Remove and Add
// Remove and Add
get
World
().
replaceEntity
(
currentEntity
,
getCurrentAvatarEntity
());
get
Player
().
getScene
().
replaceEntity
(
currentEntity
,
getCurrentAvatarEntity
());
}
}
}
}
...
@@ -396,7 +396,7 @@ public class TeamManager {
...
@@ -396,7 +396,7 @@ public class TeamManager {
oldEntity
.
setMotionState
(
MotionState
.
MotionStandby
);
oldEntity
.
setMotionState
(
MotionState
.
MotionStandby
);
// Remove and Add
// Remove and Add
get
World
().
replaceEntity
(
oldEntity
,
newEntity
);
get
Player
().
getScene
().
replaceEntity
(
oldEntity
,
newEntity
);
getPlayer
().
sendPacket
(
new
PacketChangeAvatarRsp
(
guid
));
getPlayer
().
sendPacket
(
new
PacketChangeAvatarRsp
(
guid
));
}
}
...
@@ -426,7 +426,7 @@ public class TeamManager {
...
@@ -426,7 +426,7 @@ public class TeamManager {
}
else
{
}
else
{
// Set index and spawn replacement member
// Set index and spawn replacement member
this
.
setCurrentCharacterIndex
(
replaceIndex
);
this
.
setCurrentCharacterIndex
(
replaceIndex
);
get
World
().
addEntity
(
replacement
);
get
Player
().
getScene
().
addEntity
(
replacement
);
}
}
// Response packet
// Response packet
...
...
src/main/java/emu/grasscutter/game/World.java
View file @
bee654c6
...
@@ -33,24 +33,21 @@ import emu.grasscutter.server.packet.send.PacketSyncScenePlayTeamEntityNotify;
...
@@ -33,24 +33,21 @@ import emu.grasscutter.server.packet.send.PacketSyncScenePlayTeamEntityNotify;
import
emu.grasscutter.server.packet.send.PacketSyncTeamEntityNotify
;
import
emu.grasscutter.server.packet.send.PacketSyncTeamEntityNotify
;
import
emu.grasscutter.server.packet.send.PacketWorldPlayerInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketWorldPlayerInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify
;
import
emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify
;
import
emu.grasscutter.utils.Position
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
class
World
implements
Iterable
<
GenshinPlayer
>
{
public
class
World
implements
Iterable
<
GenshinPlayer
>
{
private
final
GenshinPlayer
owner
;
private
final
GenshinPlayer
owner
;
private
final
List
<
GenshinPlayer
>
players
;
private
final
List
<
GenshinPlayer
>
players
;
private
final
Int2ObjectMap
<
GenshinScene
>
scenes
;
private
int
levelEntityId
;
private
int
levelEntityId
;
private
int
nextEntityId
=
0
;
private
int
nextEntityId
=
0
;
private
int
nextPeerId
=
0
;
private
int
nextPeerId
=
0
;
private
final
Int2ObjectMap
<
GenshinEntity
>
entities
;
private
int
worldLevel
;
private
int
worldLevel
;
private
int
sceneId
;
private
int
time
;
private
ClimateType
climate
;
private
boolean
isMultiplayer
;
private
boolean
isMultiplayer
;
private
boolean
isDungeon
;
public
World
(
GenshinPlayer
player
)
{
public
World
(
GenshinPlayer
player
)
{
this
(
player
,
false
);
this
(
player
,
false
);
...
@@ -59,11 +56,9 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -59,11 +56,9 @@ public class World implements Iterable<GenshinPlayer> {
public
World
(
GenshinPlayer
player
,
boolean
isMultiplayer
)
{
public
World
(
GenshinPlayer
player
,
boolean
isMultiplayer
)
{
this
.
owner
=
player
;
this
.
owner
=
player
;
this
.
players
=
Collections
.
synchronizedList
(
new
ArrayList
<>());
this
.
players
=
Collections
.
synchronizedList
(
new
ArrayList
<>());
this
.
entities
=
new
Int2ObjectOpenHashMap
<>();
this
.
scenes
=
new
Int2ObjectOpenHashMap
<>();
this
.
levelEntityId
=
getNextEntityId
(
EntityIdType
.
MPLEVEL
);
this
.
levelEntityId
=
getNextEntityId
(
EntityIdType
.
MPLEVEL
);
this
.
sceneId
=
player
.
getSceneId
();
this
.
time
=
8
*
60
;
this
.
climate
=
ClimateType
.
CLIMATE_SUNNY
;
this
.
worldLevel
=
player
.
getWorldLevel
();
this
.
worldLevel
=
player
.
getWorldLevel
();
this
.
isMultiplayer
=
isMultiplayer
;
this
.
isMultiplayer
=
isMultiplayer
;
}
}
...
@@ -87,22 +82,6 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -87,22 +82,6 @@ public class World implements Iterable<GenshinPlayer> {
return
++
this
.
nextPeerId
;
return
++
this
.
nextPeerId
;
}
}
public
int
getSceneId
()
{
return
sceneId
;
}
public
void
setSceneId
(
int
sceneId
)
{
this
.
sceneId
=
sceneId
;
}
public
int
getTime
()
{
return
time
;
}
public
void
changeTime
(
int
time
)
{
this
.
time
=
time
%
1440
;
}
public
int
getWorldLevel
()
{
public
int
getWorldLevel
()
{
return
worldLevel
;
return
worldLevel
;
}
}
...
@@ -111,46 +90,30 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -111,46 +90,30 @@ public class World implements Iterable<GenshinPlayer> {
this
.
worldLevel
=
worldLevel
;
this
.
worldLevel
=
worldLevel
;
}
}
public
ClimateType
getClimate
()
{
return
climate
;
}
public
void
setClimate
(
ClimateType
climate
)
{
this
.
climate
=
climate
;
}
public
List
<
GenshinPlayer
>
getPlayers
()
{
public
List
<
GenshinPlayer
>
getPlayers
()
{
return
players
;
return
players
;
}
}
public
int
getPlayerCount
()
{
public
Int2ObjectMap
<
GenshinScene
>
getScenes
()
{
return
getPlayers
().
size
()
;
return
this
.
scenes
;
}
}
public
Int2ObjectMap
<
GenshinEntity
>
getEntities
(
)
{
public
GenshinScene
getSceneById
(
int
sceneId
)
{
return
this
.
entities
;
return
getScenes
().
computeIfAbsent
(
sceneId
,
id
->
new
GenshinScene
(
this
,
id
))
;
}
}
public
boolean
isInWorld
(
GenshinEntity
entity
)
{
public
int
getPlayerCount
(
)
{
return
this
.
entities
.
containsKey
(
entity
.
getId
()
);
return
getPlayers
().
size
(
);
}
}
public
boolean
isMultiplayer
()
{
public
boolean
isMultiplayer
()
{
return
isMultiplayer
;
return
isMultiplayer
;
}
}
public
boolean
isDungeon
()
{
return
isDungeon
;
}
public
int
getNextEntityId
(
EntityIdType
idType
)
{
public
int
getNextEntityId
(
EntityIdType
idType
)
{
return
(
idType
.
getId
()
<<
24
)
+
++
this
.
nextEntityId
;
return
(
idType
.
getId
()
<<
24
)
+
++
this
.
nextEntityId
;
}
}
public
GenshinEntity
getEntityById
(
int
id
)
{
return
this
.
entities
.
get
(
id
);
}
public
synchronized
void
addPlayer
(
GenshinPlayer
player
)
{
public
synchronized
void
addPlayer
(
GenshinPlayer
player
)
{
// Check if player already in
// Check if player already in
if
(
getPlayers
().
contains
(
player
))
{
if
(
getPlayers
().
contains
(
player
))
{
...
@@ -166,11 +129,18 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -166,11 +129,18 @@ public class World implements Iterable<GenshinPlayer> {
player
.
setWorld
(
this
);
player
.
setWorld
(
this
);
getPlayers
().
add
(
player
);
getPlayers
().
add
(
player
);
// Set player variables
player
.
setPeerId
(
this
.
getNextPeerId
());
player
.
setPeerId
(
this
.
getNextPeerId
());
player
.
getTeamManager
().
setEntityId
(
getNextEntityId
(
EntityIdType
.
TEAM
));
player
.
getTeamManager
().
setEntityId
(
getNextEntityId
(
EntityIdType
.
TEAM
));
// Setup team avatars
// Copy main team to mp team
this
.
setupPlayerAvatars
(
player
);
if
(
this
.
isMultiplayer
())
{
player
.
getTeamManager
().
getMpTeam
().
copyFrom
(
player
.
getTeamManager
().
getCurrentSinglePlayerTeamInfo
(),
player
.
getTeamManager
().
getMaxTeamSize
());
}
// Add to scene
GenshinScene
scene
=
this
.
getSceneById
(
player
.
getSceneId
());
scene
.
addPlayer
(
player
);
// Info packet for other players
// Info packet for other players
if
(
this
.
getPlayers
().
size
()
>
1
)
{
if
(
this
.
getPlayers
().
size
()
>
1
)
{
...
@@ -191,18 +161,15 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -191,18 +161,15 @@ public class World implements Iterable<GenshinPlayer> {
getPlayers
().
remove
(
player
);
getPlayers
().
remove
(
player
);
player
.
setWorld
(
null
);
player
.
setWorld
(
null
);
this
.
removePlayerAvatars
(
player
);
// Remove from scene
GenshinScene
scene
=
this
.
getSceneById
(
player
.
getSceneId
());
scene
.
removePlayer
(
player
);
// Info packet for other players
// Info packet for other players
if
(
this
.
getPlayers
().
size
()
>
0
)
{
if
(
this
.
getPlayers
().
size
()
>
0
)
{
this
.
updatePlayerInfos
(
player
);
this
.
updatePlayerInfos
(
player
);
}
}
// Remove player gadgets
for
(
EntityGadget
gadget
:
player
.
getTeamManager
().
getGadgets
())
{
this
.
removeEntity
(
gadget
);
}
// Disband world if host leaves
// Disband world if host leaves
if
(
getHost
()
==
player
)
{
if
(
getHost
()
==
player
)
{
List
<
GenshinPlayer
>
kicked
=
new
ArrayList
<>(
this
.
getPlayers
());
List
<
GenshinPlayer
>
kicked
=
new
ArrayList
<>(
this
.
getPlayers
());
...
@@ -210,9 +177,22 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -210,9 +177,22 @@ public class World implements Iterable<GenshinPlayer> {
World
world
=
new
World
(
victim
);
World
world
=
new
World
(
victim
);
world
.
addPlayer
(
victim
);
world
.
addPlayer
(
victim
);
victim
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
victim
,
EnterType
.
EnterSelf
,
EnterReason
.
TeamKick
,
victim
.
getWorld
().
getSceneId
(),
victim
.
getPos
()));
victim
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
victim
,
EnterType
.
EnterSelf
,
EnterReason
.
TeamKick
,
victim
.
getSceneId
(),
victim
.
getPos
()));
}
}
}
}
}
public
void
transferPlayerToScene
(
GenshinPlayer
player
,
int
sceneId
,
Position
pos
)
{
if
(
player
.
getScene
()
!=
null
)
{
player
.
getScene
().
removePlayer
(
player
);
}
GenshinScene
scene
=
this
.
getSceneById
(
sceneId
);
scene
.
addPlayer
(
player
);
player
.
getPos
().
set
(
pos
);
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
EnterType
.
EnterSelf
,
EnterReason
.
TransPoint
,
sceneId
,
pos
));
}
}
private
void
updatePlayerInfos
(
GenshinPlayer
paramPlayer
)
{
private
void
updatePlayerInfos
(
GenshinPlayer
paramPlayer
)
{
...
@@ -239,185 +219,6 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -239,185 +219,6 @@ public class World implements Iterable<GenshinPlayer> {
}
}
}
}
private
void
addEntityDirectly
(
GenshinEntity
entity
)
{
getEntities
().
put
(
entity
.
getId
(),
entity
);
}
public
synchronized
void
addEntity
(
GenshinEntity
entity
)
{
this
.
addEntityDirectly
(
entity
);
this
.
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
entity
));
}
public
synchronized
void
addEntities
(
Collection
<
GenshinEntity
>
entities
)
{
for
(
GenshinEntity
entity
:
entities
)
{
this
.
addEntityDirectly
(
entity
);
}
this
.
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
entities
,
VisionType
.
VisionBorn
));
}
private
GenshinEntity
removeEntityDirectly
(
GenshinEntity
entity
)
{
return
getEntities
().
remove
(
entity
.
getId
());
}
public
void
removeEntity
(
GenshinEntity
entity
)
{
this
.
removeEntity
(
entity
,
VisionType
.
VisionDie
);
}
public
synchronized
void
removeEntity
(
GenshinEntity
entity
,
VisionType
visionType
)
{
GenshinEntity
removed
=
this
.
removeEntityDirectly
(
entity
);
if
(
removed
!=
null
)
{
this
.
broadcastPacket
(
new
PacketSceneEntityDisappearNotify
(
removed
,
visionType
));
}
}
public
synchronized
void
replaceEntity
(
EntityAvatar
oldEntity
,
EntityAvatar
newEntity
)
{
this
.
removeEntityDirectly
(
oldEntity
);
this
.
addEntityDirectly
(
newEntity
);
this
.
broadcastPacket
(
new
PacketSceneEntityDisappearNotify
(
oldEntity
,
VisionType
.
VisionReplace
));
this
.
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
newEntity
,
VisionType
.
VisionReplace
,
oldEntity
.
getId
()));
}
private
void
setupPlayerAvatars
(
GenshinPlayer
player
)
{
// Copy main team to mp team
if
(
this
.
isMultiplayer
())
{
player
.
getTeamManager
().
getMpTeam
().
copyFrom
(
player
.
getTeamManager
().
getCurrentSinglePlayerTeamInfo
(),
player
.
getTeamManager
().
getMaxTeamSize
());
}
// Clear entities from old team
player
.
getTeamManager
().
getActiveTeam
().
clear
();
// Add new entities for player
TeamInfo
teamInfo
=
player
.
getTeamManager
().
getCurrentTeamInfo
();
for
(
int
avatarId
:
teamInfo
.
getAvatars
())
{
EntityAvatar
entity
=
new
EntityAvatar
(
this
,
player
.
getAvatars
().
getAvatarById
(
avatarId
));
player
.
getTeamManager
().
getActiveTeam
().
add
(
entity
);
}
// Limit character index in case its out of bounds
if
(
player
.
getTeamManager
().
getCurrentCharacterIndex
()
>=
player
.
getTeamManager
().
getActiveTeam
().
size
()
||
player
.
getTeamManager
().
getCurrentCharacterIndex
()
<
0
)
{
player
.
getTeamManager
().
setCurrentCharacterIndex
(
player
.
getTeamManager
().
getCurrentCharacterIndex
()
-
1
);
}
}
private
void
removePlayerAvatars
(
GenshinPlayer
player
)
{
Iterator
<
EntityAvatar
>
it
=
player
.
getTeamManager
().
getActiveTeam
().
iterator
();
while
(
it
.
hasNext
())
{
this
.
removeEntity
(
it
.
next
(),
VisionType
.
VisionRemove
);
it
.
remove
();
}
}
public
void
spawnPlayer
(
GenshinPlayer
player
)
{
if
(
isInWorld
(
player
.
getTeamManager
().
getCurrentAvatarEntity
()))
{
return
;
}
if
(
player
.
getTeamManager
().
getCurrentAvatarEntity
().
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
)
<=
0
f
)
{
player
.
getTeamManager
().
getCurrentAvatarEntity
().
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
1
f
);
}
this
.
addEntity
(
player
.
getTeamManager
().
getCurrentAvatarEntity
());
}
public
void
showOtherEntities
(
GenshinPlayer
player
)
{
List
<
GenshinEntity
>
entities
=
new
LinkedList
<>();
GenshinEntity
currentEntity
=
player
.
getTeamManager
().
getCurrentAvatarEntity
();
for
(
GenshinEntity
entity
:
this
.
getEntities
().
values
())
{
if
(
entity
==
currentEntity
)
{
continue
;
}
entities
.
add
(
entity
);
}
player
.
sendPacket
(
new
PacketSceneEntityAppearNotify
(
entities
,
VisionType
.
VisionMeet
));
}
public
void
handleAttack
(
AttackResult
result
)
{
//GenshinEntity attacker = getEntityById(result.getAttackerId());
GenshinEntity
target
=
getEntityById
(
result
.
getDefenseId
());
if
(
target
==
null
)
{
return
;
}
// Godmode check
if
(
target
instanceof
EntityAvatar
)
{
if
(((
EntityAvatar
)
target
).
getPlayer
().
hasGodmode
())
{
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
(
GenshinEntity
target
,
int
attackerId
)
{
// Packet
this
.
broadcastPacket
(
new
PacketLifeStateChangeNotify
(
attackerId
,
target
,
LifeState
.
LIFE_DEAD
));
this
.
removeEntity
(
target
);
// Death event
target
.
onDeath
(
attackerId
);
}
// Gadgets
public
void
onPlayerCreateGadget
(
EntityClientGadget
gadget
)
{
// Directly add
this
.
addEntityDirectly
(
gadget
);
// Add to owner's gadget list
gadget
.
getOwner
().
getTeamManager
().
getGadgets
().
add
(
gadget
);
// Optimization
if
(
this
.
getPlayerCount
()
==
1
&&
this
.
getPlayers
().
get
(
0
)
==
gadget
.
getOwner
())
{
return
;
}
this
.
broadcastPacketToOthers
(
gadget
.
getOwner
(),
new
PacketSceneEntityAppearNotify
(
gadget
));
}
public
void
onPlayerDestroyGadget
(
int
entityId
)
{
GenshinEntity
entity
=
getEntities
().
get
(
entityId
);
if
(
entity
==
null
||
!(
entity
instanceof
EntityClientGadget
))
{
return
;
}
// Get and remove entity
EntityClientGadget
gadget
=
(
EntityClientGadget
)
entity
;
this
.
removeEntityDirectly
(
gadget
);
// Remove from owner's gadget list
gadget
.
getOwner
().
getTeamManager
().
getGadgets
().
remove
(
gadget
);
// Optimization
if
(
this
.
getPlayerCount
()
==
1
&&
this
.
getPlayers
().
get
(
0
)
==
gadget
.
getOwner
())
{
return
;
}
this
.
broadcastPacketToOthers
(
gadget
.
getOwner
(),
new
PacketSceneEntityDisappearNotify
(
gadget
,
VisionType
.
VisionDie
));
}
// Broadcasting
public
void
broadcastPacket
(
GenshinPacket
packet
)
{
public
void
broadcastPacket
(
GenshinPacket
packet
)
{
// Send to all players - might have to check if player has been sent data packets
// Send to all players - might have to check if player has been sent data packets
for
(
GenshinPlayer
player
:
this
.
getPlayers
())
{
for
(
GenshinPlayer
player
:
this
.
getPlayers
())
{
...
@@ -425,21 +226,6 @@ public class World implements Iterable<GenshinPlayer> {
...
@@ -425,21 +226,6 @@ public class World implements Iterable<GenshinPlayer> {
}
}
}
}
public
void
broadcastPacketToOthers
(
GenshinPlayer
excludedPlayer
,
GenshinPacket
packet
)
{
// Optimization
if
(
this
.
getPlayerCount
()
==
1
&&
this
.
getPlayers
().
get
(
0
)
==
excludedPlayer
)
{
return
;
}
// Send to all players - might have to check if player has been sent data packets
for
(
GenshinPlayer
player
:
this
.
getPlayers
())
{
if
(
player
==
excludedPlayer
)
{
continue
;
}
// Send
player
.
getSession
().
send
(
packet
);
}
}
public
void
close
()
{
public
void
close
()
{
}
}
...
...
src/main/java/emu/grasscutter/game/avatar/AvatarStorage.java
View file @
bee654c6
...
@@ -122,7 +122,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
...
@@ -122,7 +122,7 @@ public class AvatarStorage implements Iterable<GenshinAvatar> {
entity
=
new
EntityAvatar
(
avatar
);
entity
=
new
EntityAvatar
(
avatar
);
getPlayer
().
sendPacket
(
new
PacketAvatarChangeCostumeNotify
(
entity
));
getPlayer
().
sendPacket
(
new
PacketAvatarChangeCostumeNotify
(
entity
));
}
else
{
}
else
{
getPlayer
().
get
World
().
broadcastPacket
(
new
PacketAvatarChangeCostumeNotify
(
entity
));
getPlayer
().
get
Scene
().
broadcastPacket
(
new
PacketAvatarChangeCostumeNotify
(
entity
));
}
}
// Done
// Done
...
...
src/main/java/emu/grasscutter/game/entity/EntityAvatar.java
View file @
bee654c6
...
@@ -5,6 +5,7 @@ import emu.grasscutter.data.GenshinData;
...
@@ -5,6 +5,7 @@ import emu.grasscutter.data.GenshinData;
import
emu.grasscutter.data.def.AvatarData
;
import
emu.grasscutter.data.def.AvatarData
;
import
emu.grasscutter.data.def.AvatarSkillDepotData
;
import
emu.grasscutter.data.def.AvatarSkillDepotData
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinScene
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.avatar.GenshinAvatar
;
import
emu.grasscutter.game.avatar.GenshinAvatar
;
import
emu.grasscutter.game.inventory.EquipType
;
import
emu.grasscutter.game.inventory.EquipType
;
...
@@ -39,14 +40,14 @@ public class EntityAvatar extends GenshinEntity {
...
@@ -39,14 +40,14 @@ public class EntityAvatar extends GenshinEntity {
private
PlayerDieType
killedType
;
private
PlayerDieType
killedType
;
private
int
killedBy
;
private
int
killedBy
;
public
EntityAvatar
(
World
world
,
GenshinAvatar
avatar
)
{
public
EntityAvatar
(
GenshinScene
scene
,
GenshinAvatar
avatar
)
{
super
(
world
);
super
(
scene
);
this
.
avatar
=
avatar
;
this
.
avatar
=
avatar
;
this
.
id
=
w
orld
.
getNextEntityId
(
EntityIdType
.
AVATAR
);
this
.
id
=
getScene
().
getW
orld
()
.
getNextEntityId
(
EntityIdType
.
AVATAR
);
GenshinItem
weapon
=
this
.
getAvatar
().
getWeapon
();
GenshinItem
weapon
=
this
.
getAvatar
().
getWeapon
();
if
(
weapon
!=
null
)
{
if
(
weapon
!=
null
)
{
weapon
.
setWeaponEntityId
(
w
orld
.
getNextEntityId
(
EntityIdType
.
WEAPON
));
weapon
.
setWeaponEntityId
(
getScene
().
getW
orld
()
.
getNextEntityId
(
EntityIdType
.
WEAPON
));
}
}
}
}
...
@@ -152,7 +153,7 @@ public class EntityAvatar extends GenshinEntity {
...
@@ -152,7 +153,7 @@ public class EntityAvatar extends GenshinEntity {
.
setLastMoveReliableSeq
(
this
.
getLastMoveReliableSeq
())
.
setLastMoveReliableSeq
(
this
.
getLastMoveReliableSeq
())
.
setLifeState
(
this
.
getLifeState
().
getValue
());
.
setLifeState
(
this
.
getLifeState
().
getValue
());
if
(
this
.
get
World
()
!=
null
)
{
if
(
this
.
get
Scene
()
!=
null
)
{
entityInfo
.
setMotionInfo
(
this
.
getMotionInfo
());
entityInfo
.
setMotionInfo
(
this
.
getMotionInfo
());
}
}
...
...
src/main/java/emu/grasscutter/game/entity/EntityClientGadget.java
View file @
bee654c6
package
emu.grasscutter.game.entity
;
package
emu.grasscutter.game.entity
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinScene
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo
;
import
emu.grasscutter.net.proto.AbilitySyncStateInfoOuterClass.AbilitySyncStateInfo
;
...
@@ -34,8 +35,8 @@ public class EntityClientGadget extends EntityGadget {
...
@@ -34,8 +35,8 @@ public class EntityClientGadget extends EntityGadget {
private
int
targetEntityId
;
private
int
targetEntityId
;
private
boolean
asyncLoad
;
private
boolean
asyncLoad
;
public
EntityClientGadget
(
World
world
,
GenshinPlayer
player
,
EvtCreateGadgetNotify
notify
)
{
public
EntityClientGadget
(
GenshinScene
scene
,
GenshinPlayer
player
,
EvtCreateGadgetNotify
notify
)
{
super
(
world
);
super
(
scene
);
this
.
owner
=
player
;
this
.
owner
=
player
;
this
.
id
=
notify
.
getEntityId
();
this
.
id
=
notify
.
getEntityId
();
this
.
pos
=
new
Position
(
notify
.
getInitPos
());
this
.
pos
=
new
Position
(
notify
.
getInitPos
());
...
...
src/main/java/emu/grasscutter/game/entity/EntityGadget.java
View file @
bee654c6
package
emu.grasscutter.game.entity
;
package
emu.grasscutter.game.entity
;
import
emu.grasscutter.game.GenshinScene
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.World
;
public
abstract
class
EntityGadget
extends
GenshinEntity
{
public
abstract
class
EntityGadget
extends
GenshinEntity
{
public
EntityGadget
(
World
world
)
{
public
EntityGadget
(
GenshinScene
scene
)
{
super
(
world
);
super
(
scene
);
}
}
public
abstract
int
getGadgetId
();
public
abstract
int
getGadgetId
();
...
...
src/main/java/emu/grasscutter/game/entity/EntityItem.java
View file @
bee654c6
...
@@ -2,6 +2,7 @@ package emu.grasscutter.game.entity;
...
@@ -2,6 +2,7 @@ package emu.grasscutter.game.entity;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.GenshinScene
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.props.EntityIdType
;
import
emu.grasscutter.game.props.EntityIdType
;
...
@@ -30,9 +31,9 @@ public class EntityItem extends EntityGadget {
...
@@ -30,9 +31,9 @@ public class EntityItem extends EntityGadget {
private
final
GenshinItem
item
;
private
final
GenshinItem
item
;
private
final
long
guid
;
private
final
long
guid
;
public
EntityItem
(
World
world
,
GenshinPlayer
player
,
ItemData
itemData
,
Position
pos
,
int
count
)
{
public
EntityItem
(
GenshinScene
scene
,
GenshinPlayer
player
,
ItemData
itemData
,
Position
pos
,
int
count
)
{
super
(
world
);
super
(
scene
);
this
.
id
=
w
orld
.
getNextEntityId
(
EntityIdType
.
GADGET
);
this
.
id
=
getScene
().
getW
orld
()
.
getNextEntityId
(
EntityIdType
.
GADGET
);
this
.
pos
=
new
Position
(
pos
);
this
.
pos
=
new
Position
(
pos
);
this
.
rot
=
new
Position
();
this
.
rot
=
new
Position
();
this
.
guid
=
player
.
getNextGuid
();
this
.
guid
=
player
.
getNextGuid
();
...
...
src/main/java/emu/grasscutter/game/entity/EntityMonster.java
View file @
bee654c6
...
@@ -4,6 +4,7 @@ import emu.grasscutter.data.GenshinData;
...
@@ -4,6 +4,7 @@ import emu.grasscutter.data.GenshinData;
import
emu.grasscutter.data.common.PropGrowCurve
;
import
emu.grasscutter.data.common.PropGrowCurve
;
import
emu.grasscutter.data.def.MonsterCurveData
;
import
emu.grasscutter.data.def.MonsterCurveData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.game.GenshinScene
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.props.EntityIdType
;
import
emu.grasscutter.game.props.EntityIdType
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.FightProperty
;
...
@@ -36,9 +37,9 @@ public class EntityMonster extends GenshinEntity {
...
@@ -36,9 +37,9 @@ public class EntityMonster extends GenshinEntity {
private
final
int
level
;
private
final
int
level
;
private
int
weaponEntityId
;
private
int
weaponEntityId
;
public
EntityMonster
(
World
world
,
MonsterData
monsterData
,
Position
pos
,
int
level
)
{
public
EntityMonster
(
GenshinScene
scene
,
MonsterData
monsterData
,
Position
pos
,
int
level
)
{
super
(
world
);
super
(
scene
);
this
.
id
=
w
orld
.
getNextEntityId
(
EntityIdType
.
MONSTER
);
this
.
id
=
getW
orld
()
.
getNextEntityId
(
EntityIdType
.
MONSTER
);
this
.
monsterData
=
monsterData
;
this
.
monsterData
=
monsterData
;
this
.
fightProp
=
new
Int2FloatOpenHashMap
();
this
.
fightProp
=
new
Int2FloatOpenHashMap
();
this
.
pos
=
new
Position
(
pos
);
this
.
pos
=
new
Position
(
pos
);
...
@@ -48,7 +49,7 @@ public class EntityMonster extends GenshinEntity {
...
@@ -48,7 +49,7 @@ public class EntityMonster extends GenshinEntity {
// Monster weapon
// Monster weapon
if
(
getMonsterWeaponId
()
>
0
)
{
if
(
getMonsterWeaponId
()
>
0
)
{
this
.
weaponEntityId
=
w
orld
.
getNextEntityId
(
EntityIdType
.
WEAPON
);
this
.
weaponEntityId
=
getW
orld
()
.
getNextEntityId
(
EntityIdType
.
WEAPON
);
}
}
this
.
recalcStats
();
this
.
recalcStats
();
...
...
src/main/java/emu/grasscutter/game/entity/GenshinEntity.java
View file @
bee654c6
package
emu.grasscutter.game.entity
;
package
emu.grasscutter.game.entity
;
import
emu.grasscutter.game.GenshinScene
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.LifeState
;
import
emu.grasscutter.game.props.LifeState
;
...
@@ -12,14 +13,14 @@ import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
...
@@ -12,14 +13,14 @@ import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public
abstract
class
GenshinEntity
{
public
abstract
class
GenshinEntity
{
protected
int
id
;
protected
int
id
;
private
final
World
world
;
private
final
GenshinScene
scene
;
private
MotionState
moveState
;
private
MotionState
moveState
;
private
int
lastMoveSceneTimeMs
;
private
int
lastMoveSceneTimeMs
;
private
int
lastMoveReliableSeq
;
private
int
lastMoveReliableSeq
;
public
GenshinEntity
(
World
world
)
{
public
GenshinEntity
(
GenshinScene
scene
)
{
this
.
world
=
world
;
this
.
scene
=
scene
;
this
.
moveState
=
MotionState
.
MotionNone
;
this
.
moveState
=
MotionState
.
MotionNone
;
}
}
...
@@ -28,7 +29,11 @@ public abstract class GenshinEntity {
...
@@ -28,7 +29,11 @@ public abstract class GenshinEntity {
}
}
public
World
getWorld
()
{
public
World
getWorld
()
{
return
world
;
return
this
.
getScene
().
getWorld
();
}
public
GenshinScene
getScene
()
{
return
this
.
scene
;
}
}
public
boolean
isAlive
()
{
public
boolean
isAlive
()
{
...
...
src/main/java/emu/grasscutter/game/managers/MultiplayerManager.java
View file @
bee654c6
...
@@ -35,10 +35,12 @@ public class MultiplayerManager {
...
@@ -35,10 +35,12 @@ public class MultiplayerManager {
return
;
return
;
}
}
/*
if (target.getWorld().isDungeon()) {
if (target.getWorld().isDungeon()) {
player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpReason.SceneCannotEnter));
player.sendPacket(new PacketPlayerApplyEnterMpResultNotify(targetUid, "", false, PlayerApplyEnterMpReason.SceneCannotEnter));
return;
return;
}
}
*/
// Get request
// Get request
CoopRequest
request
=
target
.
getCoopRequests
().
get
(
player
.
getId
());
CoopRequest
request
=
target
.
getCoopRequests
().
get
(
player
.
getId
());
...
@@ -90,14 +92,14 @@ public class MultiplayerManager {
...
@@ -90,14 +92,14 @@ public class MultiplayerManager {
world
.
addPlayer
(
player
);
world
.
addPlayer
(
player
);
// Rejoin packet
// Rejoin packet
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
player
,
EnterType
.
EnterSelf
,
EnterReason
.
HostFromSingleToMp
,
player
.
get
World
().
get
Scene
Id
(),
player
.
getPos
()));
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
player
,
EnterType
.
EnterSelf
,
EnterReason
.
HostFromSingleToMp
,
player
.
get
Scene
().
getId
(),
player
.
getPos
()));
}
}
// Make requester join
// Make requester join
player
.
getWorld
().
addPlayer
(
requester
);
player
.
getWorld
().
addPlayer
(
requester
);
// Packet
// Packet
requester
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
requester
,
player
,
EnterType
.
EnterOther
,
EnterReason
.
TeamJoin
,
player
.
get
World
().
get
Scene
Id
(),
player
.
getPos
()));
requester
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
requester
,
player
,
EnterType
.
EnterOther
,
EnterReason
.
TeamJoin
,
player
.
get
Scene
().
getId
(),
player
.
getPos
()));
requester
.
getPos
().
set
(
player
.
getPos
());
requester
.
getPos
().
set
(
player
.
getPos
());
requester
.
getRotation
().
set
(
player
.
getRotation
());
requester
.
getRotation
().
set
(
player
.
getRotation
());
}
}
...
@@ -120,7 +122,7 @@ public class MultiplayerManager {
...
@@ -120,7 +122,7 @@ public class MultiplayerManager {
world
.
addPlayer
(
player
);
world
.
addPlayer
(
player
);
// Packet
// Packet
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
EnterType
.
EnterSelf
,
EnterReason
.
TeamBack
,
player
.
get
World
().
get
Scene
Id
(),
player
.
getPos
()));
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
EnterType
.
EnterSelf
,
EnterReason
.
TeamBack
,
player
.
get
Scene
().
getId
(),
player
.
getPos
()));
return
true
;
return
true
;
}
}
...
@@ -147,7 +149,7 @@ public class MultiplayerManager {
...
@@ -147,7 +149,7 @@ public class MultiplayerManager {
World
world
=
new
World
(
victim
);
World
world
=
new
World
(
victim
);
world
.
addPlayer
(
victim
);
world
.
addPlayer
(
victim
);
victim
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
victim
,
EnterType
.
EnterSelf
,
EnterReason
.
TeamKick
,
victim
.
get
World
().
get
Scene
Id
(),
victim
.
getPos
()));
victim
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
victim
,
EnterType
.
EnterSelf
,
EnterReason
.
TeamKick
,
victim
.
get
Scene
().
getId
(),
victim
.
getPos
()));
return
true
;
return
true
;
}
}
}
}
src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java
View file @
bee654c6
...
@@ -958,6 +958,7 @@ public class PacketOpcodes {
...
@@ -958,6 +958,7 @@ public class PacketOpcodes {
public
static
final
int
SceneTimeNotify
=
229
;
public
static
final
int
SceneTimeNotify
=
229
;
public
static
final
int
SceneTransToPointReq
=
256
;
public
static
final
int
SceneTransToPointReq
=
256
;
public
static
final
int
SceneTransToPointRsp
=
283
;
public
static
final
int
SceneTransToPointRsp
=
283
;
public
static
final
int
SceneUnlockInfoNotify
=
3386
;
public
static
final
int
SceneWeatherForcastReq
=
3167
;
public
static
final
int
SceneWeatherForcastReq
=
3167
;
public
static
final
int
SceneWeatherForcastRsp
=
3023
;
public
static
final
int
SceneWeatherForcastRsp
=
3023
;
public
static
final
int
SeaLampCoinNotify
=
2028
;
public
static
final
int
SeaLampCoinNotify
=
2028
;
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerChangeGameTimeReq.java
View file @
bee654c6
...
@@ -14,8 +14,8 @@ public class HandlerChangeGameTimeReq extends PacketHandler {
...
@@ -14,8 +14,8 @@ public class HandlerChangeGameTimeReq extends PacketHandler {
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
ChangeGameTimeReq
req
=
ChangeGameTimeReq
.
parseFrom
(
payload
);
ChangeGameTimeReq
req
=
ChangeGameTimeReq
.
parseFrom
(
payload
);
session
.
getPlayer
().
get
World
().
changeTime
(
req
.
getGameTime
());
session
.
getPlayer
().
get
Scene
().
changeTime
(
req
.
getGameTime
());
session
.
getPlayer
().
sendPacket
(
new
PacketChangeGameTimeRsp
(
session
.
getPlayer
()
.
getWorld
()
));
session
.
getPlayer
().
sendPacket
(
new
PacketChangeGameTimeRsp
(
session
.
getPlayer
()));
}
}
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java
View file @
bee654c6
...
@@ -22,12 +22,12 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
...
@@ -22,12 +22,12 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
case
CombatEvtBeingHit:
case
CombatEvtBeingHit:
// Handle damage
// Handle damage
EvtBeingHitInfo
hitInfo
=
EvtBeingHitInfo
.
parseFrom
(
entry
.
getCombatData
());
EvtBeingHitInfo
hitInfo
=
EvtBeingHitInfo
.
parseFrom
(
entry
.
getCombatData
());
session
.
getPlayer
().
get
World
().
handleAttack
(
hitInfo
.
getAttackResult
());
session
.
getPlayer
().
get
Scene
().
handleAttack
(
hitInfo
.
getAttackResult
());
break
;
break
;
case
EntityMove:
case
EntityMove:
// Handle movement
// Handle movement
EntityMoveInfo
moveInfo
=
EntityMoveInfo
.
parseFrom
(
entry
.
getCombatData
());
EntityMoveInfo
moveInfo
=
EntityMoveInfo
.
parseFrom
(
entry
.
getCombatData
());
GenshinEntity
entity
=
session
.
getPlayer
().
get
World
().
getEntityById
(
moveInfo
.
getEntityId
());
GenshinEntity
entity
=
session
.
getPlayer
().
get
Scene
().
getEntityById
(
moveInfo
.
getEntityId
());
if
(
entity
!=
null
)
{
if
(
entity
!=
null
)
{
entity
.
getPosition
().
set
(
moveInfo
.
getMotionInfo
().
getPos
());
entity
.
getPosition
().
set
(
moveInfo
.
getMotionInfo
().
getPos
());
entity
.
getRotation
().
set
(
moveInfo
.
getMotionInfo
().
getRot
());
entity
.
getRotation
().
set
(
moveInfo
.
getMotionInfo
().
getRot
());
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterSceneDoneReq.java
View file @
bee654c6
...
@@ -24,10 +24,10 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
...
@@ -24,10 +24,10 @@ public class HandlerEnterSceneDoneReq extends PacketHandler {
session
.
send
(
new
PacketPlayerTimeNotify
(
session
.
getPlayer
()));
// Probably not the right place
session
.
send
(
new
PacketPlayerTimeNotify
(
session
.
getPlayer
()));
// Probably not the right place
// Spawn player in world
// Spawn player in world
session
.
getPlayer
().
get
World
().
spawnPlayer
(
session
.
getPlayer
());
session
.
getPlayer
().
get
Scene
().
spawnPlayer
(
session
.
getPlayer
());
// Spawn other entites already in world
// Spawn other entites already in world
session
.
getPlayer
().
get
World
().
showOtherEntities
(
session
.
getPlayer
());
session
.
getPlayer
().
get
Scene
().
showOtherEntities
(
session
.
getPlayer
());
// Locations
// Locations
session
.
send
(
new
PacketWorldPlayerLocationNotify
(
session
.
getPlayer
().
getWorld
()));
session
.
send
(
new
PacketWorldPlayerLocationNotify
(
session
.
getPlayer
().
getWorld
()));
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerEntityAiSyncNotify.java
View file @
bee654c6
...
@@ -15,7 +15,7 @@ public class HandlerEntityAiSyncNotify extends PacketHandler {
...
@@ -15,7 +15,7 @@ public class HandlerEntityAiSyncNotify extends PacketHandler {
EntityAiSyncNotify
notify
=
EntityAiSyncNotify
.
parseFrom
(
payload
);
EntityAiSyncNotify
notify
=
EntityAiSyncNotify
.
parseFrom
(
payload
);
if
(
notify
.
getLocalAvatarAlertedMonsterListCount
()
>
0
)
{
if
(
notify
.
getLocalAvatarAlertedMonsterListCount
()
>
0
)
{
session
.
getPlayer
().
get
World
().
broadcastPacket
(
new
PacketEntityAiSyncNotify
(
notify
));
session
.
getPlayer
().
get
Scene
().
broadcastPacket
(
new
PacketEntityAiSyncNotify
(
notify
));
}
}
}
}
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtCreateGadgetNotify.java
View file @
bee654c6
...
@@ -20,13 +20,13 @@ public class HandlerEvtCreateGadgetNotify extends PacketHandler {
...
@@ -20,13 +20,13 @@ public class HandlerEvtCreateGadgetNotify extends PacketHandler {
}
}
// Sanity check - dont add duplicate entities
// Sanity check - dont add duplicate entities
if
(
session
.
getPlayer
().
get
World
().
getEntityById
(
notify
.
getEntityId
())
!=
null
)
{
if
(
session
.
getPlayer
().
get
Scene
().
getEntityById
(
notify
.
getEntityId
())
!=
null
)
{
return
;
return
;
}
}
// Create entity and summon in world
// Create entity and summon in world
EntityClientGadget
gadget
=
new
EntityClientGadget
(
session
.
getPlayer
().
get
World
(),
session
.
getPlayer
(),
notify
);
EntityClientGadget
gadget
=
new
EntityClientGadget
(
session
.
getPlayer
().
get
Scene
(),
session
.
getPlayer
(),
notify
);
session
.
getPlayer
().
get
World
().
onPlayerCreateGadget
(
gadget
);
session
.
getPlayer
().
get
Scene
().
onPlayerCreateGadget
(
gadget
);
}
}
}
}
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