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
3db1a866
Commit
3db1a866
authored
Apr 26, 2022
by
Benjamin Elsdon
Browse files
Merge remote-tracking branch 'upstream/development' into dev-mail
parents
a2069c00
57c7c704
Changes
16
Expand all
Show whitespace changes
Inline
Side-by-side
build.gradle
View file @
3db1a866
...
...
@@ -37,6 +37,7 @@ dependencies {
implementation
group:
'dev.morphia.morphia'
,
name:
'morphia-core'
,
version:
'2.2.6'
implementation
group:
'org.greenrobot'
,
name:
'eventbus-java'
,
version:
'3.3.1'
implementation
group:
'org.danilopianini'
,
name:
'java-quadtree'
,
version:
'0.1.9'
}
application
{
...
...
data/Spawns.json
0 → 100644
View file @
3db1a866
This diff is collapsed.
Click to expand it.
src/main/java/emu/grasscutter/data/GenshinData.java
View file @
3db1a866
...
...
@@ -60,6 +60,7 @@ public class GenshinData {
private
static
final
Int2ObjectMap
<
FetterData
>
fetterDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
FetterCharacterCardData
>
fetterCharacterCardDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
RewardData
>
rewardDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WorldLevelData
>
worldLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
// Cache
private
static
Map
<
Integer
,
List
<
Integer
>>
fetters
=
new
HashMap
<>();
...
...
@@ -260,4 +261,8 @@ public class GenshinData {
return
fetters
;
}
public
static
Int2ObjectMap
<
WorldLevelData
>
getWorldLevelDataMap
()
{
return
worldLevelDataMap
;
}
}
src/main/java/emu/grasscutter/data/GenshinDepot.java
View file @
3db1a866
...
...
@@ -3,9 +3,14 @@ package emu.grasscutter.data;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.danilopianini.util.FlexibleQuadTree
;
import
org.danilopianini.util.SpatialIndex
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.def.ReliquaryAffixData
;
import
emu.grasscutter.data.def.ReliquaryMainPropData
;
import
emu.grasscutter.game.world.SpawnDataEntry
;
import
emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry
;
import
emu.grasscutter.utils.WeightedList
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
...
...
@@ -14,6 +19,8 @@ public class GenshinDepot {
private
static
Int2ObjectMap
<
WeightedList
<
ReliquaryMainPropData
>>
relicMainPropDepot
=
new
Int2ObjectOpenHashMap
<>();
private
static
Int2ObjectMap
<
List
<
ReliquaryAffixData
>>
relicAffixDepot
=
new
Int2ObjectOpenHashMap
<>();
private
static
Int2ObjectMap
<
SpatialIndex
<
SpawnGroupEntry
>>
spawnLists
=
new
Int2ObjectOpenHashMap
<>();
public
static
void
load
()
{
for
(
ReliquaryMainPropData
data
:
GenshinData
.
getReliquaryMainPropDataMap
().
values
())
{
if
(
data
.
getWeight
()
<=
0
||
data
.
getPropDepotId
()
<=
0
)
{
...
...
@@ -46,4 +53,12 @@ public class GenshinDepot {
public
static
List
<
ReliquaryAffixData
>
getRandomRelicAffixList
(
int
depot
)
{
return
relicAffixDepot
.
get
(
depot
);
}
public
static
Int2ObjectMap
<
SpatialIndex
<
SpawnGroupEntry
>>
getSpawnLists
()
{
return
spawnLists
;
}
public
static
SpatialIndex
<
SpawnGroupEntry
>
getSpawnListById
(
int
sceneId
)
{
return
getSpawnLists
().
computeIfAbsent
(
sceneId
,
id
->
new
FlexibleQuadTree
<>());
}
}
src/main/java/emu/grasscutter/data/ResourceLoader.java
View file @
3db1a866
...
...
@@ -19,6 +19,8 @@ import emu.grasscutter.data.common.ScenePointConfig;
import
emu.grasscutter.data.custom.AbilityEmbryoEntry
;
import
emu.grasscutter.data.custom.OpenConfigEntry
;
import
emu.grasscutter.data.custom.ScenePointEntry
;
import
emu.grasscutter.game.world.SpawnDataEntry
;
import
emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
public
class
ResourceLoader
{
...
...
@@ -49,6 +51,8 @@ public class ResourceLoader {
loadScenePoints
();
// Process into depots
GenshinDepot
.
load
();
// Load spawn data
loadSpawnData
();
// Custom - TODO move this somewhere else
try
{
GenshinData
.
getAvatarSkillDepotDataMap
().
get
(
504
).
setAbilities
(
...
...
@@ -233,6 +237,33 @@ public class ResourceLoader {
}
}
private
static
void
loadSpawnData
()
{
// Read from cached file if exists
File
spawnDataEntries
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"Spawns.json"
);
List
<
SpawnGroupEntry
>
spawnEntryList
=
null
;
if
(
spawnDataEntries
.
exists
())
{
// Load from cache
try
(
FileReader
fileReader
=
new
FileReader
(
spawnDataEntries
))
{
spawnEntryList
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
TypeToken
.
getParameterized
(
Collection
.
class
,
SpawnGroupEntry
.
class
).
getType
());
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
if
(
spawnEntryList
==
null
||
spawnEntryList
.
isEmpty
())
{
Grasscutter
.
getLogger
().
error
(
"No spawn data loaded!"
);
return
;
}
for
(
SpawnGroupEntry
entry
:
spawnEntryList
)
{
entry
.
getSpawns
().
stream
().
forEach
(
s
->
{
s
.
setGroup
(
entry
);
});
GenshinDepot
.
getSpawnListById
(
entry
.
getSceneId
()).
insert
(
entry
,
entry
.
getPos
().
getX
(),
entry
.
getPos
().
getZ
());
}
}
private
static
void
loadOpenConfig
()
{
// Read from cached file if exists
File
openConfigCache
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
+
"OpenConfig.json"
);
...
...
src/main/java/emu/grasscutter/data/def/WorldLevelData.java
0 → 100644
View file @
3db1a866
package
emu.grasscutter.data.def
;
import
emu.grasscutter.data.GenshinResource
;
import
emu.grasscutter.data.ResourceType
;
@ResourceType
(
name
=
"WorldLevelExcelConfigData.json"
)
public
class
WorldLevelData
extends
GenshinResource
{
private
int
Level
;
private
int
MonsterLevel
;
@Override
public
int
getId
()
{
return
this
.
Level
;
}
public
int
getMonsterLevel
()
{
return
MonsterLevel
;
}
@Override
public
void
onLoad
()
{
}
}
src/main/java/emu/grasscutter/game/GenshinPlayer.java
View file @
3db1a866
...
...
@@ -225,11 +225,11 @@ public class GenshinPlayer {
this
.
world
=
world
;
}
public
GenshinScene
getScene
()
{
public
synchronized
GenshinScene
getScene
()
{
return
scene
;
}
public
void
setScene
(
GenshinScene
scene
)
{
public
synchronized
void
setScene
(
GenshinScene
scene
)
{
this
.
scene
=
scene
;
}
...
...
src/main/java/emu/grasscutter/game/GenshinScene.java
View file @
3db1a866
...
...
@@ -3,19 +3,32 @@ package emu.grasscutter.game;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Set
;
import
org.danilopianini.util.SpatialIndex
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.GenshinDepot
;
import
emu.grasscutter.data.GenshinResource
;
import
emu.grasscutter.data.def.MonsterData
;
import
emu.grasscutter.data.def.SceneData
;
import
emu.grasscutter.data.def.WorldLevelData
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.entity.EntityClientGadget
;
import
emu.grasscutter.game.entity.EntityGadget
;
import
emu.grasscutter.game.entity.EntityMonster
;
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.game.props.SceneType
;
import
emu.grasscutter.game.world.SpawnDataEntry
;
import
emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult
;
import
emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType
;
...
...
@@ -23,7 +36,9 @@ 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
emu.grasscutter.utils.Utils
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMaps
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
class
GenshinScene
{
...
...
@@ -32,6 +47,10 @@ public class GenshinScene {
private
final
List
<
GenshinPlayer
>
players
;
private
final
Int2ObjectMap
<
GenshinEntity
>
entities
;
private
final
Set
<
SpawnDataEntry
>
spawnedEntities
;
private
final
Set
<
SpawnDataEntry
>
deadSpawnedEntities
;
private
boolean
dontDestroyWhenEmpty
;
private
int
time
;
private
ClimateType
climate
;
private
int
weather
;
...
...
@@ -40,10 +59,13 @@ public class GenshinScene {
this
.
world
=
world
;
this
.
sceneData
=
sceneData
;
this
.
players
=
Collections
.
synchronizedList
(
new
ArrayList
<>());
this
.
entities
=
new
Int2ObjectOpenHashMap
<>();
this
.
entities
=
Int2ObjectMaps
.
synchronize
(
new
Int2ObjectOpenHashMap
<>()
)
;
this
.
time
=
8
*
60
;
this
.
climate
=
ClimateType
.
CLIMATE_SUNNY
;
this
.
spawnedEntities
=
new
HashSet
<>();
this
.
deadSpawnedEntities
=
new
HashSet
<>();
}
public
int
getId
()
{
...
...
@@ -102,11 +124,27 @@ public class GenshinScene {
this
.
weather
=
weather
;
}
public
boolean
dontDestroyWhenEmpty
()
{
return
dontDestroyWhenEmpty
;
}
public
void
setDontDestroyWhenEmpty
(
boolean
dontDestroyWhenEmpty
)
{
this
.
dontDestroyWhenEmpty
=
dontDestroyWhenEmpty
;
}
public
Set
<
SpawnDataEntry
>
getSpawnedEntities
()
{
return
spawnedEntities
;
}
public
Set
<
SpawnDataEntry
>
getDeadSpawnedEntities
()
{
return
deadSpawnedEntities
;
}
public
boolean
isInScene
(
GenshinEntity
entity
)
{
return
this
.
entities
.
containsKey
(
entity
.
getId
());
}
public
void
addPlayer
(
GenshinPlayer
player
)
{
public
synchronized
void
addPlayer
(
GenshinPlayer
player
)
{
// Check if player already in
if
(
getPlayers
().
contains
(
player
))
{
return
;
...
...
@@ -125,7 +163,7 @@ public class GenshinScene {
this
.
setupPlayerAvatars
(
player
);
}
public
void
removePlayer
(
GenshinPlayer
player
)
{
public
synchronized
void
removePlayer
(
GenshinPlayer
player
)
{
// Remove player from scene
getPlayers
().
remove
(
player
);
player
.
setScene
(
null
);
...
...
@@ -139,7 +177,7 @@ public class GenshinScene {
}
// Deregister scene if not in use
if
(
this
.
getEntities
().
size
()
<=
0
)
{
if
(
this
.
getEntities
().
size
()
<=
0
&&
!
this
.
dontDestroyWhenEmpty
()
)
{
this
.
getWorld
().
deregisterScene
(
this
);
}
}
...
...
@@ -277,6 +315,80 @@ public class GenshinScene {
target
.
onDeath
(
attackerId
);
}
public
void
onTick
()
{
this
.
checkSpawns
();
}
// TODO - Test
public
void
checkSpawns
()
{
SpatialIndex
<
SpawnGroupEntry
>
list
=
GenshinDepot
.
getSpawnListById
(
this
.
getId
());
Set
<
SpawnDataEntry
>
visible
=
new
HashSet
<>();
for
(
GenshinPlayer
player
:
this
.
getPlayers
())
{
int
RANGE
=
100
;
Collection
<
SpawnGroupEntry
>
entries
=
list
.
query
(
new
double
[]
{
player
.
getPos
().
getX
()
-
RANGE
,
player
.
getPos
().
getZ
()
-
RANGE
},
new
double
[]
{
player
.
getPos
().
getX
()
+
RANGE
,
player
.
getPos
().
getZ
()
+
RANGE
}
);
for
(
SpawnGroupEntry
entry
:
entries
)
{
for
(
SpawnDataEntry
spawnData
:
entry
.
getSpawns
())
{
visible
.
add
(
spawnData
);
}
}
}
// World level
WorldLevelData
worldLevelData
=
GenshinData
.
getWorldLevelDataMap
().
get
(
getWorld
().
getWorldLevel
());
int
worldLevelOverride
=
0
;
if
(
worldLevelData
!=
null
)
{
worldLevelOverride
=
worldLevelData
.
getMonsterLevel
();
}
// Todo
List
<
GenshinEntity
>
toAdd
=
new
LinkedList
<>();
List
<
GenshinEntity
>
toRemove
=
new
LinkedList
<>();
for
(
SpawnDataEntry
entry
:
visible
)
{
if
(!
this
.
getSpawnedEntities
().
contains
(
entry
)
&&
!
this
.
getDeadSpawnedEntities
().
contains
(
entry
))
{
// Spawn entity
MonsterData
data
=
GenshinData
.
getMonsterDataMap
().
get
(
entry
.
getMonsterId
());
if
(
data
==
null
)
{
continue
;
}
EntityMonster
entity
=
new
EntityMonster
(
this
,
data
,
entry
.
getPos
(),
worldLevelOverride
>
0
?
worldLevelOverride
:
entry
.
getLevel
());
entity
.
getRotation
().
set
(
entry
.
getRot
());
entity
.
setGroupId
(
entry
.
getGroup
().
getGroupId
());
entity
.
setPoseId
(
entry
.
getPoseId
());
entity
.
setConfigId
(
entry
.
getConfigId
());
entity
.
setSpawnEntry
(
entry
);
toAdd
.
add
(
entity
);
// Add to spawned list
this
.
getSpawnedEntities
().
add
(
entry
);
}
}
for
(
GenshinEntity
entity
:
this
.
getEntities
().
values
())
{
if
(
entity
.
getSpawnEntry
()
!=
null
&&
!
visible
.
contains
(
entity
.
getSpawnEntry
()))
{
toRemove
.
add
(
entity
);
}
}
if
(
toAdd
.
size
()
>
0
)
{
toAdd
.
stream
().
forEach
(
this
::
addEntityDirectly
);
this
.
broadcastPacket
(
new
PacketSceneEntityAppearNotify
(
toAdd
,
VisionType
.
VisionBorn
));
}
if
(
toRemove
.
size
()
>
0
)
{
toRemove
.
stream
().
forEach
(
this
::
removeEntityDirectly
);
this
.
broadcastPacket
(
new
PacketSceneEntityDisappearNotify
(
toRemove
,
VisionType
.
VisionRemove
));
}
}
// Gadgets
public
void
onPlayerCreateGadget
(
EntityClientGadget
gadget
)
{
...
...
src/main/java/emu/grasscutter/game/World.java
View file @
3db1a866
...
...
@@ -37,6 +37,7 @@ import emu.grasscutter.server.packet.send.PacketWorldPlayerInfoNotify;
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.Int2ObjectMaps
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
public
class
World
implements
Iterable
<
GenshinPlayer
>
{
...
...
@@ -58,11 +59,13 @@ public class World implements Iterable<GenshinPlayer> {
public
World
(
GenshinPlayer
player
,
boolean
isMultiplayer
)
{
this
.
owner
=
player
;
this
.
players
=
Collections
.
synchronizedList
(
new
ArrayList
<>());
this
.
scenes
=
new
Int2ObjectOpenHashMap
<>();
this
.
scenes
=
Int2ObjectMaps
.
synchronize
(
new
Int2ObjectOpenHashMap
<>()
)
;
this
.
levelEntityId
=
getNextEntityId
(
EntityIdType
.
MPLEVEL
);
this
.
worldLevel
=
player
.
getWorldLevel
();
this
.
isMultiplayer
=
isMultiplayer
;
this
.
owner
.
getServer
().
registerWorld
(
this
);
}
public
GenshinPlayer
getHost
()
{
...
...
@@ -212,19 +215,29 @@ public class World implements Iterable<GenshinPlayer> {
return
false
;
}
Integer
oldScene
Id
=
null
;
GenshinScene
oldScene
=
null
;
if
(
player
.
getScene
()
!=
null
)
{
oldSceneId
=
player
.
getScene
().
getId
();
player
.
getScene
().
removePlayer
(
player
);
oldScene
=
player
.
getScene
();
// Dont deregister scenes if the player is going to tp back into them
if
(
oldScene
.
getId
()
==
sceneId
)
{
oldScene
.
setDontDestroyWhenEmpty
(
true
);
}
GenshinScene
scene
=
this
.
getSceneById
(
sceneId
);
scene
.
addPlayer
(
player
);
oldScene
.
removePlayer
(
player
);
}
GenshinScene
newScene
=
this
.
getSceneById
(
sceneId
);
newScene
.
addPlayer
(
player
);
player
.
getPos
().
set
(
pos
);
if
(
oldScene
!=
null
)
{
oldScene
.
setDontDestroyWhenEmpty
(
false
);
}
// Teleport packet
if
(
oldScene
Id
.
equals
(
s
cene
Id
)
)
{
if
(
oldScene
==
newS
cene
)
{
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
EnterType
.
EnterGoto
,
EnterReason
.
TransPoint
,
sceneId
,
pos
));
}
else
{
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
player
,
EnterType
.
EnterJump
,
EnterReason
.
TransPoint
,
sceneId
,
pos
));
...
...
@@ -263,6 +276,12 @@ public class World implements Iterable<GenshinPlayer> {
}
}
public
void
onTick
()
{
for
(
GenshinScene
scene
:
this
.
getScenes
().
values
())
{
scene
.
onTick
();
}
}
public
void
close
()
{
}
...
...
src/main/java/emu/grasscutter/game/entity/EntityMonster.java
View file @
3db1a866
...
...
@@ -37,6 +37,10 @@ public class EntityMonster extends GenshinEntity {
private
final
int
level
;
private
int
weaponEntityId
;
private
int
groupId
;
private
int
configId
;
private
int
poseId
;
public
EntityMonster
(
GenshinScene
scene
,
MonsterData
monsterData
,
Position
pos
,
int
level
)
{
super
(
scene
);
this
.
id
=
getWorld
().
getNextEntityId
(
EntityIdType
.
MONSTER
);
...
...
@@ -100,9 +104,35 @@ public class EntityMonster extends GenshinEntity {
return
this
.
getFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
)
>
0
f
;
}
public
int
getGroupId
()
{
return
groupId
;
}
public
void
setGroupId
(
int
groupId
)
{
this
.
groupId
=
groupId
;
}
public
int
getConfigId
()
{
return
configId
;
}
public
void
setConfigId
(
int
configId
)
{
this
.
configId
=
configId
;
}
public
int
getPoseId
()
{
return
poseId
;
}
public
void
setPoseId
(
int
poseId
)
{
this
.
poseId
=
poseId
;
}
@Override
public
void
onDeath
(
int
killerId
)
{
if
(
this
.
getSpawnEntry
()
!=
null
)
{
this
.
getScene
().
getDeadSpawnedEntities
().
add
(
getSpawnEntry
());
}
}
public
void
recalcStats
()
{
...
...
@@ -190,11 +220,11 @@ public class EntityMonster extends GenshinEntity {
SceneMonsterInfo
.
Builder
monsterInfo
=
SceneMonsterInfo
.
newBuilder
()
.
setMonsterId
(
getMonsterId
())
.
setGroupId
(
133003095
)
.
setConfigId
(
95001
)
.
setGroupId
(
this
.
getGroupId
()
)
.
setConfigId
(
this
.
getConfigId
()
)
.
addAllAffixList
(
getMonsterData
().
getAffix
())
.
setAuthorityPeerId
(
getWorld
().
getHostPeerId
())
.
setPoseId
(
0
)
.
setPoseId
(
this
.
getPoseId
()
)
.
setBlockId
(
3001
)
.
setBornType
(
MonsterBornType
.
MonsterBornDefault
)
.
setSpecialNameId
(
40
);
...
...
src/main/java/emu/grasscutter/game/entity/GenshinEntity.java
View file @
3db1a866
...
...
@@ -4,6 +4,7 @@ import emu.grasscutter.game.GenshinScene;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.game.props.LifeState
;
import
emu.grasscutter.game.world.SpawnDataEntry
;
import
emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo
;
import
emu.grasscutter.net.proto.MotionStateOuterClass.MotionState
;
import
emu.grasscutter.net.proto.SceneEntityInfoOuterClass.SceneEntityInfo
;
...
...
@@ -14,6 +15,7 @@ import it.unimi.dsi.fastutil.ints.Int2FloatOpenHashMap;
public
abstract
class
GenshinEntity
{
protected
int
id
;
private
final
GenshinScene
scene
;
private
SpawnDataEntry
spawnEntry
;
private
MotionState
moveState
;
private
int
lastMoveSceneTimeMs
;
...
...
@@ -104,4 +106,12 @@ public abstract class GenshinEntity {
return
proto
;
}
public
SpawnDataEntry
getSpawnEntry
()
{
return
spawnEntry
;
}
public
void
setSpawnEntry
(
SpawnDataEntry
spawnEntry
)
{
this
.
spawnEntry
=
spawnEntry
;
}
}
src/main/java/emu/grasscutter/game/world/SpawnDataEntry.java
0 → 100644
View file @
3db1a866
package
emu.grasscutter.game.world
;
import
java.util.ArrayList
;
import
java.util.List
;
import
emu.grasscutter.utils.Position
;
public
class
SpawnDataEntry
{
private
transient
SpawnGroupEntry
group
;
private
int
monsterId
;
private
int
configId
;
private
int
level
;
private
int
poseId
;
private
Position
pos
;
private
Position
rot
;
public
SpawnGroupEntry
getGroup
()
{
return
group
;
}
public
void
setGroup
(
SpawnGroupEntry
group
)
{
this
.
group
=
group
;
}
public
int
getMonsterId
()
{
return
monsterId
;
}
public
int
getConfigId
()
{
return
configId
;
}
public
int
getLevel
()
{
return
level
;
}
public
int
getPoseId
()
{
return
poseId
;
}
public
Position
getPos
()
{
return
pos
;
}
public
Position
getRot
()
{
return
rot
;
}
public
static
class
SpawnGroupEntry
{
private
int
sceneId
;
private
int
groupId
;
private
int
blockId
;
private
Position
pos
;
private
List
<
SpawnDataEntry
>
spawns
;
public
int
getSceneId
()
{
return
sceneId
;
}
public
int
getGroupId
()
{
return
groupId
;
}
public
int
getBlockId
()
{
return
blockId
;
}
public
void
setBlockId
(
int
blockId
)
{
this
.
blockId
=
blockId
;
}
public
Position
getPos
()
{
return
pos
;
}
public
List
<
SpawnDataEntry
>
getSpawns
()
{
return
spawns
;
}
}
}
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
3db1a866
...
...
@@ -43,6 +43,7 @@ public final class DispatchServer {
public
String
regionListBase64
;
public
HashMap
<
String
,
RegionData
>
regions
;
private
HttpServer
server
;
public
DispatchServer
()
{
this
.
regions
=
new
HashMap
<
String
,
RegionData
>();
...
...
@@ -54,6 +55,10 @@ public final class DispatchServer {
this
.
initRegion
();
}
public
HttpServer
getServer
()
{
return
server
;
}
public
InetSocketAddress
getAddress
()
{
return
address
;
}
...
...
@@ -200,7 +205,6 @@ public final class DispatchServer {
}
public
void
start
()
throws
Exception
{
HttpServer
server
;
if
(
Grasscutter
.
getConfig
().
getDispatchOptions
().
UseSSL
)
{
HttpsServer
httpsServer
=
HttpsServer
.
create
(
getAddress
(),
0
);
SSLContext
sslContext
=
SSLContext
.
getInstance
(
"TLS"
);
...
...
src/main/java/emu/grasscutter/server/game/GameServer.java
View file @
3db1a866
...
...
@@ -10,6 +10,7 @@ import emu.grasscutter.command.CommandMap;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.World
;
import
emu.grasscutter.game.dungeons.DungeonManager
;
import
emu.grasscutter.game.gacha.GachaManager
;
import
emu.grasscutter.game.managers.ChatManager
;
...
...
@@ -26,6 +27,7 @@ public final class GameServer extends MihoyoKcpServer {
private
final
GameServerPacketHandler
packetHandler
;
private
final
Map
<
Integer
,
GenshinPlayer
>
players
;
private
final
Set
<
World
>
worlds
;
private
final
ChatManager
chatManager
;
private
final
InventoryManager
inventoryManager
;
...
...
@@ -50,6 +52,7 @@ public final class GameServer extends MihoyoKcpServer {
this
.
address
=
address
;
this
.
packetHandler
=
new
GameServerPacketHandler
(
PacketHandler
.
class
);
this
.
players
=
new
ConcurrentHashMap
<>();
this
.
worlds
=
Collections
.
synchronizedSet
(
new
HashSet
<>());
this
.
chatManager
=
new
ChatManager
(
this
);
this
.
inventoryManager
=
new
InventoryManager
(
this
);
...
...
@@ -84,6 +87,10 @@ public final class GameServer extends MihoyoKcpServer {
return
players
;
}
public
Set
<
World
>
getWorlds
()
{
return
worlds
;
}
public
ChatManager
getChatManager
()
{
return
chatManager
;
}
...
...
@@ -161,6 +168,17 @@ public final class GameServer extends MihoyoKcpServer {
}
public
void
onTick
()
throws
Exception
{
Iterator
<
World
>
it
=
this
.
getWorlds
().
iterator
();
while
(
it
.
hasNext
())
{
World
world
=
it
.
next
();
if
(
world
.
getPlayerCount
()
==
0
)
{
it
.
remove
();
}
world
.
onTick
();
}
for
(
GenshinPlayer
player
:
this
.
getPlayers
().
values
())
{
player
.
onTick
();
}
...
...
@@ -168,6 +186,15 @@ public final class GameServer extends MihoyoKcpServer {
OnGameServerTick
.
post
(
new
GameServerTickEvent
());
}
public
void
registerWorld
(
World
world
)
{
this
.
getWorlds
().
add
(
world
);
}
public
void
deregisterWorld
(
World
world
)
{
// TODO Auto-generated method stub
}
@Override
public
void
onStartFinish
()
{
Grasscutter
.
getLogger
().
info
(
"Game Server started on port "
+
address
.
getPort
());
...
...
src/main/java/emu/grasscutter/server/packet/send/PacketSceneEntityDisappearNotify.java
View file @
3db1a866
package
emu.grasscutter.server.packet.send
;
import
java.util.Collection
;
import
java.util.List
;
import
emu.grasscutter.game.entity.GenshinEntity
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
...
...
@@ -18,4 +21,15 @@ public class PacketSceneEntityDisappearNotify extends GenshinPacket {
this
.
setData
(
proto
);
}
public
PacketSceneEntityDisappearNotify
(
Collection
<
GenshinEntity
>
entities
,
VisionType
disappearType
)
{
super
(
PacketOpcodes
.
SceneEntityDisappearNotify
);
SceneEntityDisappearNotify
.
Builder
proto
=
SceneEntityDisappearNotify
.
newBuilder
()
.
setDisappearType
(
disappearType
);
entities
.
forEach
(
e
->
proto
.
addEntityList
(
e
.
getId
()));
this
.
setData
(
proto
);
}
}
src/main/java/emu/grasscutter/utils/Utils.java
View file @
3db1a866
...
...
@@ -10,6 +10,7 @@ import emu.grasscutter.Grasscutter;
import
io.netty.buffer.ByteBuf
;
import
io.netty.buffer.ByteBufUtil
;
import
io.netty.buffer.Unpooled
;
import
org.slf4j.Logger
;
@SuppressWarnings
({
"UnusedReturnValue"
,
"BooleanMethodIsAlwaysInverted"
})
...
...
@@ -24,6 +25,19 @@ public final class Utils {
return
random
.
nextFloat
()
*
(
max
-
min
)
+
min
;
}
public
static
double
getDist
(
Position
pos1
,
Position
pos2
)
{
double
xs
=
pos1
.
getX
()
-
pos2
.
getX
();
xs
=
xs
*
xs
;
double
ys
=
pos1
.
getY
()
-
pos2
.
getY
();
ys
=
ys
*
ys
;
double
zs
=
pos1
.
getZ
()
-
pos2
.
getZ
();
zs
=
zs
*
zs
;
return
Math
.
sqrt
(
xs
+
zs
+
ys
);
}
public
static
int
getCurrentSeconds
()
{
return
(
int
)
(
System
.
currentTimeMillis
()
/
1000.0
);
}
...
...
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