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
12146ff0
Commit
12146ff0
authored
Jun 26, 2022
by
Akka
Committed by
Melledy
Jun 29, 2022
Browse files
implement the music game
parent
977f1ca2
Changes
32
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/data/GameData.java
View file @
12146ff0
...
...
@@ -101,6 +101,7 @@ public class GameData {
@Getter
private
static
final
Int2ObjectMap
<
ActivityData
>
activityDataMap
=
new
Int2ObjectOpenHashMap
<>();
@Getter
private
static
final
Int2ObjectMap
<
ActivityWatcherData
>
activityWatcherDataMap
=
new
Int2ObjectOpenHashMap
<>();
@Getter
private
static
final
Int2ObjectMap
<
MusicGameBasicData
>
musicGameBasicDataMap
=
new
Int2ObjectOpenHashMap
<>();
// Cache
private
static
Map
<
Integer
,
List
<
Integer
>>
fetters
=
new
HashMap
<>();
...
...
src/main/java/emu/grasscutter/data/excels/ActivityWatcherData.java
View file @
12146ff0
...
...
@@ -2,6 +2,7 @@ package emu.grasscutter.data.excels;
import
emu.grasscutter.data.GameResource
;
import
emu.grasscutter.data.ResourceType
;
import
emu.grasscutter.game.props.WatcherTriggerType
;
import
lombok.AccessLevel
;
import
lombok.Getter
;
import
lombok.experimental.FieldDefaults
;
...
...
@@ -24,6 +25,7 @@ public class ActivityWatcherData extends GameResource {
@Override
public
void
onLoad
()
{
triggerConfig
.
paramList
=
triggerConfig
.
paramList
.
stream
().
filter
(
x
->
!
x
.
isBlank
()).
toList
();
triggerConfig
.
watcherTriggerType
=
WatcherTriggerType
.
getTypeByName
(
triggerConfig
.
triggerType
);
}
@Getter
...
...
@@ -31,6 +33,8 @@ public class ActivityWatcherData extends GameResource {
public
static
class
WatcherTrigger
{
String
triggerType
;
List
<
String
>
paramList
;
transient
WatcherTriggerType
watcherTriggerType
;
}
}
src/main/java/emu/grasscutter/data/excels/MusicGameBasicData.java
0 → 100644
View file @
12146ff0
package
emu.grasscutter.data.excels
;
import
emu.grasscutter.data.GameResource
;
import
emu.grasscutter.data.ResourceType
;
import
lombok.AccessLevel
;
import
lombok.Getter
;
import
lombok.experimental.FieldDefaults
;
@ResourceType
(
name
=
"MusicGameBasicConfigData.json"
)
@Getter
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
public
class
MusicGameBasicData
extends
GameResource
{
int
id
;
int
musicID
;
int
musicLevel
;
@Override
public
int
getId
()
{
return
this
.
id
;
}
}
src/main/java/emu/grasscutter/database/DatabaseHelper.java
View file @
12146ff0
...
...
@@ -11,6 +11,7 @@ import emu.grasscutter.GameConstants;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.activity.PlayerActivityData
;
import
emu.grasscutter.game.activity.musicgame.MusicGameBeatmap
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.battlepass.BattlePassManager
;
import
emu.grasscutter.game.friends.Friendship
;
...
...
@@ -337,4 +338,13 @@ public final class DatabaseHelper {
public
static
void
savePlayerActivityData
(
PlayerActivityData
playerActivityData
)
{
DatabaseManager
.
getGameDatastore
().
save
(
playerActivityData
);
}
public
static
MusicGameBeatmap
getMusicGameBeatmap
(
long
musicShareId
)
{
return
DatabaseManager
.
getGameDatastore
().
find
(
MusicGameBeatmap
.
class
)
.
filter
(
Filters
.
eq
(
"musicShareId"
,
musicShareId
))
.
first
();
}
public
static
void
saveMusicGameBeatmap
(
MusicGameBeatmap
musicGameBeatmap
)
{
DatabaseManager
.
getGameDatastore
().
save
(
musicGameBeatmap
);
}
}
src/main/java/emu/grasscutter/database/DatabaseManager.java
View file @
12146ff0
...
...
@@ -14,6 +14,7 @@ import emu.grasscutter.Grasscutter;
import
emu.grasscutter.Grasscutter.ServerRunMode
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.activity.PlayerActivityData
;
import
emu.grasscutter.game.activity.musicgame.MusicGameBeatmap
;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.battlepass.BattlePassManager
;
import
emu.grasscutter.game.friends.Friendship
;
...
...
@@ -33,12 +34,14 @@ public final class DatabaseManager {
private
static
final
Class
<?>[]
mappedClasses
=
new
Class
<?>[]
{
DatabaseCounter
.
class
,
Account
.
class
,
Player
.
class
,
Avatar
.
class
,
GameItem
.
class
,
Friendship
.
class
,
GachaRecord
.
class
,
Mail
.
class
,
GameMainQuest
.
class
,
GameHome
.
class
,
BattlePassManager
.
class
,
PlayerActivityData
.
class
GachaRecord
.
class
,
Mail
.
class
,
GameMainQuest
.
class
,
GameHome
.
class
,
BattlePassManager
.
class
,
PlayerActivityData
.
class
,
MusicGameBeatmap
.
class
};
public
static
Datastore
getGameDatastore
()
{
return
gameDatastore
;
}
public
static
MongoDatabase
getGameDatabase
()
{
return
getGameDatastore
().
getDatabase
();
}
...
...
src/main/java/emu/grasscutter/game/activity/ActivityHandler.java
View file @
12146ff0
...
...
@@ -26,12 +26,15 @@ public abstract class ActivityHandler {
ActivityData
activityData
;
Map
<
WatcherTriggerType
,
List
<
ActivityWatcher
>>
watchersMap
=
new
HashMap
<>();
public
void
initWatchers
(
HashMap
<
String
,
ConstructorAccess
<?>>
activityWatcherTypeMap
){
abstract
public
void
onProtoBuild
(
PlayerActivityData
playerActivityData
,
ActivityInfoOuterClass
.
ActivityInfo
.
Builder
activityInfo
);
abstract
public
void
onInitPlayerActivityData
(
PlayerActivityData
playerActivityData
);
public
void
initWatchers
(
Map
<
WatcherTriggerType
,
ConstructorAccess
<?>>
activityWatcherTypeMap
){
activityData
=
GameData
.
getActivityDataMap
().
get
(
activityConfigItem
.
getActivityId
());
// add watcher to map by id
activityData
.
getWatcherDataList
().
forEach
(
watcherData
->
{
var
watcherType
=
activityWatcherTypeMap
.
get
(
watcherData
.
getTriggerConfig
().
getTriggerType
());
var
watcherType
=
activityWatcherTypeMap
.
get
(
watcherData
.
getTriggerConfig
().
get
Watcher
TriggerType
());
ActivityWatcher
watcher
;
if
(
watcherType
!=
null
){
watcher
=
(
ActivityWatcher
)
watcherType
.
newInstance
();
...
...
@@ -42,8 +45,8 @@ public abstract class ActivityHandler {
watcher
.
setWatcherId
(
watcherData
.
getId
());
watcher
.
setActivityHandler
(
this
);
watcher
.
setActivityWatcherData
(
watcherData
);
watchersMap
.
computeIfAbsent
(
WatcherTriggerType
.
getTypeByName
(
watcherData
.
getTriggerConfig
().
getTriggerType
()
)
,
k
->
new
ArrayList
<>());
watchersMap
.
get
(
WatcherTriggerType
.
getTypeByName
(
watcherData
.
getTriggerConfig
().
getTriggerType
())
)
.
add
(
watcher
);
watchersMap
.
computeIfAbsent
(
watcherData
.
getTriggerConfig
().
get
Watcher
TriggerType
(),
k
->
new
ArrayList
<>());
watchersMap
.
get
(
watcherData
.
getTriggerConfig
().
get
Watcher
TriggerType
()).
add
(
watcher
);
});
}
...
...
@@ -55,16 +58,19 @@ public abstract class ActivityHandler {
}
public
PlayerActivityData
initPlayerActivityData
(
Player
player
){
return
PlayerActivityData
.
of
()
PlayerActivityData
playerActivityData
=
PlayerActivityData
.
of
()
.
activityId
(
activityConfigItem
.
getActivityId
())
.
uid
(
player
.
getUid
())
.
watcherInfoMap
(
initWatchersDataForPlayer
())
.
build
();
}
onInitPlayerActivityData
(
playerActivityData
);
return
playerActivityData
;
}
public
void
buildProto
(
PlayerActivityData
playerActivityData
,
ActivityInfoOuterClass
.
ActivityInfo
.
Builder
activityInfo
){
activityInfo
.
setActivityId
(
activityConfigItem
.
getActivityId
())
public
ActivityInfoOuterClass
.
ActivityInfo
toProto
(
PlayerActivityData
playerActivityData
){
var
proto
=
ActivityInfoOuterClass
.
ActivityInfo
.
newBuilder
();
proto
.
setActivityId
(
activityConfigItem
.
getActivityId
())
.
setActivityType
(
activityConfigItem
.
getActivityType
())
.
setScheduleId
(
activityConfigItem
.
getScheduleId
())
.
setBeginTime
(
DateHelper
.
getUnixTime
(
activityConfigItem
.
getBeginTime
()))
...
...
@@ -73,9 +79,12 @@ public abstract class ActivityHandler {
.
addAllMeetCondList
(
activityConfigItem
.
getMeetCondList
());
if
(
playerActivityData
!=
null
){
activityInf
o
.
addAllWatcherInfoList
(
playerActivityData
.
getAllWatcherInfoList
());
prot
o
.
addAllWatcherInfoList
(
playerActivityData
.
getAllWatcherInfoList
());
}
onProtoBuild
(
playerActivityData
,
proto
);
return
proto
.
build
();
}
}
src/main/java/emu/grasscutter/game/activity/ActivityManager.java
View file @
12146ff0
...
...
@@ -6,6 +6,7 @@ import emu.grasscutter.Grasscutter;
import
emu.grasscutter.data.DataLoader
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.props.ActivityType
;
import
emu.grasscutter.game.props.WatcherTriggerType
;
import
emu.grasscutter.net.proto.ActivityInfoOuterClass
;
import
emu.grasscutter.server.packet.send.PacketActivityScheduleInfoNotify
;
...
...
@@ -25,41 +26,22 @@ public class ActivityManager {
static
{
activityConfigItemMap
=
new
HashMap
<>();
loadActivityConfigData
();
}
public
ActivityManager
(
Player
player
){
this
.
player
=
player
;
playerActivityDataMap
=
new
ConcurrentHashMap
<>();
// load data for player
activityConfigItemMap
.
values
().
forEach
(
item
->
{
var
data
=
PlayerActivityData
.
getByPlayer
(
player
,
item
.
getActivityId
());
if
(
data
==
null
){
data
=
item
.
getActivityHandler
().
initPlayerActivityData
(
player
);
data
.
save
();
}
data
.
setPlayer
(
player
);
playerActivityDataMap
.
put
(
item
.
getActivityId
(),
data
);
});
player
.
sendPacket
(
new
PacketActivityScheduleInfoNotify
(
activityConfigItemMap
.
values
()));
}
private
static
void
loadActivityConfigData
()
{
// scan activity type handler & watcher type
var
activityHandlerTypeMap
=
new
HashMap
<
String
,
ConstructorAccess
<?>>();
var
activityWatcherTypeMap
=
new
HashMap
<
String
,
ConstructorAccess
<?>>();
var
activityHandlerTypeMap
=
new
HashMap
<
ActivityType
,
ConstructorAccess
<?>>();
var
activityWatcherTypeMap
=
new
HashMap
<
WatcherTriggerType
,
ConstructorAccess
<?>>();
var
reflections
=
new
Reflections
(
ActivityManager
.
class
.
getPackage
().
getName
());
reflections
.
getSubTypesOf
(
ActivityHandler
.
class
).
forEach
(
item
->
{
var
typeName
=
item
.
getAnnotation
(
Activity
Type
.
class
);
var
typeName
=
item
.
getAnnotation
(
Game
Activity
.
class
);
activityHandlerTypeMap
.
put
(
typeName
.
value
(),
ConstructorAccess
.
get
(
item
));
});
reflections
.
getSubTypesOf
(
ActivityWatcher
.
class
).
forEach
(
item
->
{
var
typeName
=
item
.
getAnnotation
(
WatcherType
.
class
);
activityWatcherTypeMap
.
put
(
typeName
.
value
()
.
name
()
,
ConstructorAccess
.
get
(
item
));
var
typeName
=
item
.
getAnnotation
(
Activity
WatcherType
.
class
);
activityWatcherTypeMap
.
put
(
typeName
.
value
(),
ConstructorAccess
.
get
(
item
));
});
try
(
InputStream
is
=
DataLoader
.
load
(
"ActivityConfig.json"
);
InputStreamReader
isr
=
new
InputStreamReader
(
is
))
{
...
...
@@ -74,39 +56,49 @@ public class ActivityManager {
Grasscutter
.
getLogger
().
warn
(
"activity {} not exist."
,
item
.
getActivityId
());
return
;
}
var
activityHandlerType
=
activityHandlerTypeMap
.
get
(
activityData
.
getActivityType
());
var
activityHandlerType
=
activityHandlerTypeMap
.
get
(
ActivityType
.
getTypeByName
(
activityData
.
getActivityType
()));
ActivityHandler
activityHandler
;
if
(
activityHandlerType
!=
null
)
{
var
activityHandler
=
(
ActivityHandler
)
activityHandlerType
.
newInstance
();
activityHandler
.
setActivityConfigItem
(
item
);
activityHandler
.
initWatchers
(
activityWatcherTypeMap
);
item
.
setActivityHandler
(
activityHandler
);
activityHandler
=
(
ActivityHandler
)
activityHandlerType
.
newInstance
();
}
else
{
activityHandler
=
new
DefaultActivityHandler
();
}
activityHandler
.
setActivityConfigItem
(
item
);
activityHandler
.
initWatchers
(
activityWatcherTypeMap
);
item
.
setActivityHandler
(
activityHandler
);
activityConfigItemMap
.
putIfAbsent
(
item
.
getActivityId
(),
item
);
});
Grasscutter
.
getLogger
().
error
(
"Enable {} activities."
,
activityConfigItemMap
.
size
());
Grasscutter
.
getLogger
().
info
(
"Enable {} activities."
,
activityConfigItemMap
.
size
());
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Unable to load
chest reward
config."
,
e
);
Grasscutter
.
getLogger
().
error
(
"Unable to load
activities
config."
,
e
);
}
}
public
ActivityInfoOuterClass
.
ActivityInfo
getInfoProto
(
int
activityId
){
var
activityHandler
=
activityConfigItemMap
.
get
(
activityId
).
getActivityHandler
();
var
activityData
=
playerActivityDataMap
.
get
(
activityId
);
public
ActivityManager
(
Player
player
){
this
.
player
=
player
;
var
proto
=
ActivityInfoOuterClass
.
ActivityInfo
.
newBuilder
();
activityHandler
.
buildProto
(
activityData
,
proto
);
playerActivityDataMap
=
new
ConcurrentHashMap
<>();
// load data for player
activityConfigItemMap
.
values
().
forEach
(
item
->
{
var
data
=
PlayerActivityData
.
getByPlayer
(
player
,
item
.
getActivityId
());
if
(
data
==
null
){
data
=
item
.
getActivityHandler
().
initPlayerActivityData
(
player
);
data
.
save
();
}
data
.
setPlayer
(
player
);
data
.
setActivityHandler
(
item
.
getActivityHandler
());
playerActivityDataMap
.
put
(
item
.
getActivityId
(),
data
);
});
return
proto
.
build
(
);
player
.
sendPacket
(
new
PacketActivityScheduleInfoNotify
(
activityConfigItemMap
.
values
())
);
}
/**
* trigger activity watcher
* @param watcherTriggerType
* @param params
*/
public
void
triggerWatcher
(
WatcherTriggerType
watcherTriggerType
,
String
...
params
)
{
var
watchers
=
activityConfigItemMap
.
values
().
stream
()
...
...
@@ -122,4 +114,37 @@ public class ActivityManager {
playerActivityDataMap
.
get
(
watcher
.
getActivityHandler
().
getActivityConfigItem
().
getActivityId
()),
params
));
}
public
ActivityInfoOuterClass
.
ActivityInfo
getInfoProtoByActivityId
(
int
activityId
){
var
activityHandler
=
activityConfigItemMap
.
get
(
activityId
).
getActivityHandler
();
var
activityData
=
playerActivityDataMap
.
get
(
activityId
);
return
activityHandler
.
toProto
(
activityData
);
}
public
Optional
<
ActivityHandler
>
getActivityHandler
(
ActivityType
type
){
return
activityConfigItemMap
.
values
().
stream
()
.
map
(
ActivityConfigItem:
:
getActivityHandler
)
.
filter
(
x
->
type
==
x
.
getClass
().
getAnnotation
(
GameActivity
.
class
).
value
())
.
findFirst
();
}
public
<
T
extends
ActivityHandler
>
Optional
<
T
>
getActivityHandlerAs
(
ActivityType
type
,
Class
<
T
>
clazz
){
return
getActivityHandler
(
type
).
map
(
x
->
(
T
)
x
);
}
public
Optional
<
Integer
>
getActivityIdByActivityType
(
ActivityType
type
){
return
getActivityHandler
(
type
)
.
map
(
ActivityHandler:
:
getActivityConfigItem
)
.
map
(
ActivityConfigItem:
:
getActivityId
);
}
public
Optional
<
PlayerActivityData
>
getPlayerActivityDataByActivityType
(
ActivityType
type
){
return
getActivityIdByActivityType
(
type
)
.
map
(
playerActivityDataMap:
:
get
);
}
public
Optional
<
ActivityInfoOuterClass
.
ActivityInfo
>
getInfoProtoByActivityType
(
ActivityType
type
){
return
getActivityIdByActivityType
(
type
)
.
map
(
this
::
getInfoProtoByActivityId
);
}
}
src/main/java/emu/grasscutter/game/activity/WatcherType.java
→
src/main/java/emu/grasscutter/game/activity/
Activity
WatcherType.java
View file @
12146ff0
...
...
@@ -9,6 +9,6 @@ import java.lang.annotation.Target;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
TYPE
)
public
@interface
WatcherType
{
public
@interface
Activity
WatcherType
{
WatcherTriggerType
value
();
}
src/main/java/emu/grasscutter/game/activity/DefaultActivityHandler.java
0 → 100644
View file @
12146ff0
package
emu.grasscutter.game.activity
;
import
emu.grasscutter.game.props.ActivityType
;
import
emu.grasscutter.net.proto.ActivityInfoOuterClass
;
@GameActivity
(
ActivityType
.
NONE
)
public
class
DefaultActivityHandler
extends
ActivityHandler
{
@Override
public
void
onProtoBuild
(
PlayerActivityData
playerActivityData
,
ActivityInfoOuterClass
.
ActivityInfo
.
Builder
activityInfo
)
{
}
@Override
public
void
onInitPlayerActivityData
(
PlayerActivityData
playerActivityData
)
{
}
}
src/main/java/emu/grasscutter/game/activity/DefaultWatcher.java
View file @
12146ff0
...
...
@@ -2,7 +2,7 @@ package emu.grasscutter.game.activity;
import
emu.grasscutter.game.props.WatcherTriggerType
;
@WatcherType
(
WatcherTriggerType
.
TRIGGER_NONE
)
@
Activity
WatcherType
(
WatcherTriggerType
.
TRIGGER_NONE
)
public
class
DefaultWatcher
extends
ActivityWatcher
{
@Override
protected
boolean
isMeet
(
String
...
param
)
{
...
...
src/main/java/emu/grasscutter/game/activity/Activity
Type
.java
→
src/main/java/emu/grasscutter/game/activity/
Game
Activity.java
View file @
12146ff0
package
emu.grasscutter.game.activity
;
import
emu.grasscutter.game.props.ActivityType
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
...
...
@@ -7,6 +9,6 @@ import java.lang.annotation.Target;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
TYPE
)
public
@interface
Activity
Type
{
String
value
();
public
@interface
Game
Activity
{
ActivityType
value
();
}
src/main/java/emu/grasscutter/game/activity/PlayerActivityData.java
View file @
12146ff0
...
...
@@ -3,8 +3,14 @@ package emu.grasscutter.game.activity;
import
dev.morphia.annotations.Entity
;
import
dev.morphia.annotations.Id
;
import
dev.morphia.annotations.Transient
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.common.ItemParamData
;
import
emu.grasscutter.data.excels.ActivityWatcherData
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.inventory.GameItem
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.props.ActionReason
;
import
emu.grasscutter.net.proto.ActivityWatcherInfoOuterClass
;
import
emu.grasscutter.server.packet.send.PacketActivityUpdateWatcherNotify
;
import
lombok.AccessLevel
;
...
...
@@ -12,8 +18,10 @@ import lombok.Builder;
import
lombok.Data
;
import
lombok.experimental.FieldDefaults
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Optional
;
@Entity
(
"activities"
)
@Data
...
...
@@ -25,9 +33,12 @@ public class PlayerActivityData {
int
uid
;
int
activityId
;
Map
<
Integer
,
WatcherInfo
>
watcherInfoMap
;
/**
* the detail data of each type of activity (Json format)
*/
String
detail
;
@Transient
Player
player
;
@Transient
ActivityHandler
activityHandler
;
public
void
save
(){
DatabaseHelper
.
savePlayerActivityData
(
this
);
}
...
...
@@ -56,6 +67,35 @@ public class PlayerActivityData {
.
toList
();
}
public
void
setDetail
(
Object
detail
){
this
.
detail
=
Grasscutter
.
getGsonFactory
().
toJson
(
detail
);
}
public
void
takeWatcherReward
(
int
watcherId
)
{
var
watcher
=
watcherInfoMap
.
get
(
watcherId
);
if
(
watcher
==
null
||
watcher
.
isTakenReward
()){
return
;
}
var
reward
=
Optional
.
of
(
watcher
)
.
map
(
WatcherInfo:
:
getMetadata
)
.
map
(
ActivityWatcherData:
:
getRewardID
)
.
map
(
id
->
GameData
.
getRewardDataMap
().
get
(
id
.
intValue
()));
if
(
reward
.
isEmpty
()){
return
;
}
List
<
GameItem
>
rewards
=
new
ArrayList
<>();
for
(
ItemParamData
param
:
reward
.
get
().
getRewardItemList
())
{
rewards
.
add
(
new
GameItem
(
param
.
getId
(),
Math
.
max
(
param
.
getCount
(),
1
)));
}
player
.
getInventory
().
addItems
(
rewards
,
ActionReason
.
ActivityWatcher
);
watcher
.
setTakenReward
(
true
);
save
();
}
@Entity
@Data
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
...
...
@@ -66,6 +106,10 @@ public class PlayerActivityData {
int
curProgress
;
boolean
isTakenReward
;
public
ActivityWatcherData
getMetadata
(){
return
GameData
.
getActivityWatcherDataMap
().
get
(
watcherId
);
}
public
static
WatcherInfo
init
(
ActivityWatcher
watcher
){
return
WatcherInfo
.
of
()
.
watcherId
(
watcher
.
getWatcherId
())
...
...
src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameActivityHandler.java
View file @
12146ff0
package
emu.grasscutter.game.activity.musicgame
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.game.activity.ActivityHandler
;
import
emu.grasscutter.game.activity.Activity
Type
;
import
emu.grasscutter.game.activity.
Game
Activity
;
import
emu.grasscutter.game.activity.PlayerActivityData
;
import
emu.grasscutter.game.props.ActivityType
;
import
emu.grasscutter.net.proto.ActivityInfoOuterClass
;
import
emu.grasscutter.net.proto.MusicBriefInfoOuterClass
;
import
emu.grasscutter.net.proto.MusicGameActivityDetailInfoOuterClass
;
@ActivityType
(
"NEW_ACTIVITY_MUSIC_GAME"
)
import
java.util.stream.Collectors
;
@GameActivity
(
ActivityType
.
NEW_ACTIVITY_MUSIC_GAME
)
public
class
MusicGameActivityHandler
extends
ActivityHandler
{
@Override
public
void
buildProto
(
PlayerActivityData
playerActivityData
,
ActivityInfoOuterClass
.
ActivityInfo
.
Builder
activityInfo
)
{
super
.
buildProto
(
playerActivityData
,
activityInfo
);
public
void
onInitPlayerActivityData
(
PlayerActivityData
playerActivityData
)
{
var
musicGamePlayerData
=
MusicGamePlayerData
.
create
();
playerActivityData
.
setDetail
(
musicGamePlayerData
);
}
@Override
public
void
onProtoBuild
(
PlayerActivityData
playerActivityData
,
ActivityInfoOuterClass
.
ActivityInfo
.
Builder
activityInfo
)
{
MusicGamePlayerData
musicGamePlayerData
=
getMusicGameRecord
(
playerActivityData
);
activityInfo
.
setMusicGameInfo
(
MusicGameActivityDetailInfoOuterClass
.
MusicGameActivityDetailInfo
.
newBuilder
()
.
putAllMusicGameRecordMap
(
musicGamePlayerData
.
getMusicGameRecord
().
values
().
stream
()
.
collect
(
Collectors
.
toMap
(
MusicGamePlayerData
.
MusicGameRecord
::
getMusicId
,
MusicGamePlayerData
.
MusicGameRecord
::
toProto
)))
.
addAllPersonCustomBeatmap
(
musicGamePlayerData
.
getPersonalCustomBeatmapRecord
().
values
().
stream
()
.
map
(
MusicGamePlayerData
.
CustomBeatmapRecord
::
toProto
)
.
map
(
MusicBriefInfoOuterClass
.
MusicBriefInfo
.
Builder
::
build
)
.
toList
())
.
addAllPersonCustomBeatmap
(
musicGamePlayerData
.
getOthersCustomBeatmapRecord
().
values
().
stream
()
.
map
(
MusicGamePlayerData
.
CustomBeatmapRecord
::
toProto
)
.
map
(
MusicBriefInfoOuterClass
.
MusicBriefInfo
.
Builder
::
build
)
.
toList
())
.
build
());
}
public
MusicGamePlayerData
getMusicGameRecord
(
PlayerActivityData
playerActivityData
){
if
(
playerActivityData
.
getDetail
()
==
null
||
playerActivityData
.
getDetail
().
isBlank
()){
onInitPlayerActivityData
(
playerActivityData
);
playerActivityData
.
save
();
}
return
Grasscutter
.
getGsonFactory
().
fromJson
(
playerActivityData
.
getDetail
(),
MusicGamePlayerData
.
class
);
}
public
boolean
setMusicGameRecord
(
PlayerActivityData
playerActivityData
,
MusicGamePlayerData
.
MusicGameRecord
newRecord
){
var
musicGamePlayerData
=
getMusicGameRecord
(
playerActivityData
);
var
saveRecord
=
musicGamePlayerData
.
getMusicGameRecord
().
get
(
newRecord
.
getMusicId
());
saveRecord
.
setMaxCombo
(
Math
.
max
(
newRecord
.
getMaxCombo
(),
saveRecord
.
getMaxCombo
()));
saveRecord
.
setMaxScore
(
Math
.
max
(
newRecord
.
getMaxScore
(),
saveRecord
.
getMaxScore
()));
playerActivityData
.
setDetail
(
musicGamePlayerData
);
playerActivityData
.
save
();
return
newRecord
.
getMaxScore
()
>
saveRecord
.
getMaxScore
();
}
public
void
setMusicGameCustomBeatmapRecord
(
PlayerActivityData
playerActivityData
,
MusicGamePlayerData
.
CustomBeatmapRecord
newRecord
){
var
musicGamePlayerData
=
getMusicGameRecord
(
playerActivityData
);
musicGamePlayerData
.
getOthersCustomBeatmapRecord
().
put
(
newRecord
.
getMusicShareId
(),
newRecord
);
playerActivityData
.
setDetail
(
musicGamePlayerData
);
playerActivityData
.
save
();
}
public
void
addPersonalBeatmap
(
PlayerActivityData
playerActivityData
,
MusicGameBeatmap
musicGameBeatmap
)
{
var
musicGamePlayerData
=
getMusicGameRecord
(
playerActivityData
);
musicGamePlayerData
.
getPersonalCustomBeatmapRecord
().
put
(
musicGameBeatmap
.
getMusicShareId
(),
MusicGamePlayerData
.
CustomBeatmapRecord
.
of
()
.
musicShareId
(
musicGameBeatmap
.
getMusicShareId
())
.
build
());
playerActivityData
.
setDetail
(
musicGamePlayerData
);
playerActivityData
.
save
();
}
}
src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameBeatmap.java
0 → 100644
View file @
12146ff0
package
emu.grasscutter.game.activity.musicgame
;
import
dev.morphia.annotations.Entity
;
import
dev.morphia.annotations.Id
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.net.proto.MusicBeatmapListOuterClass
;
import
emu.grasscutter.net.proto.MusicBeatmapNoteOuterClass
;
import
emu.grasscutter.net.proto.MusicBeatmapOuterClass
;
import
emu.grasscutter.net.proto.MusicBriefInfoOuterClass
;
import
lombok.AccessLevel
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.experimental.FieldDefaults
;
import
java.util.List
;
import
java.util.Random
;
@Entity
(
"music_game_beatmaps"
)
@Data
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
@Builder
(
builderMethodName
=
"of"
)
public
class
MusicGameBeatmap
{
@Id
long
musicShareId
;
int
authorUid
;
int
musicId
;
int
musicNoteCount
;
int
savePosition
;
int
maxScore
;
int
createTime
;
List
<
List
<
BeatmapNote
>>
beatmap
;
public
static
MusicGameBeatmap
getByShareId
(
long
musicShareId
){
return
DatabaseHelper
.
getMusicGameBeatmap
(
musicShareId
);
}
public
void
save
(){
if
(
musicShareId
==
0
){
musicShareId
=
new
Random
().
nextLong
(
100000000000000L
,
999999999999999L
);
}
DatabaseHelper
.
saveMusicGameBeatmap
(
this
);
}
public
static
List
<
List
<
BeatmapNote
>>
parse
(
List
<
MusicBeatmapListOuterClass
.
MusicBeatmapList
>
beatmapItemListList
)
{
return
beatmapItemListList
.
stream
()
.
map
(
item
->
item
.
getBeatmapNoteListList
().
stream
()
.
map
(
BeatmapNote:
:
parse
)
.
toList
())
.
toList
();
}
public
MusicBeatmapOuterClass
.
MusicBeatmap
toProto
(){
return
MusicBeatmapOuterClass
.
MusicBeatmap
.
newBuilder
()
.
setMusicId
(
musicId
)
.
addAllBeatmapItemList
(
beatmap
.
stream
()
.
map
(
this
::
musicBeatmapListToProto
)
.
toList
())
.
build
();
}
public
MusicBriefInfoOuterClass
.
MusicBriefInfo
.
Builder
toBriefProto
(){
var
player
=
DatabaseHelper
.
getPlayerByUid
(
authorUid
);
return
MusicBriefInfoOuterClass
.
MusicBriefInfo
.
newBuilder
()
.
setCanShare
(
true
)
.
setMusicId
(
musicId
)
.
setMusicNoteCount
(
musicNoteCount
)
.
setMusicShareId
(
musicShareId
)
.
setMaxScore
(
maxScore
)
.
setCreateTime
(
createTime
)
.
setShareTime
(
createTime
)
.
setAuthorNickname
(
player
.
getNickname
())
.
setVersion
(
1
)
;
}
private
MusicBeatmapListOuterClass
.
MusicBeatmapList
musicBeatmapListToProto
(
List
<
BeatmapNote
>
beatmapNoteList
){
return
MusicBeatmapListOuterClass
.
MusicBeatmapList
.
newBuilder
()
.
addAllBeatmapNoteList
(
beatmapNoteList
.
stream
()
.
map
(
BeatmapNote:
:
toProto
)
.
toList
())
.
build
();
}
@Data
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
@Builder
(
builderMethodName
=
"of"
)
@Entity
public
static
class
BeatmapNote
{
int
startTime
;
int
endTime
;
public
static
BeatmapNote
parse
(
MusicBeatmapNoteOuterClass
.
MusicBeatmapNote
note
){
return
BeatmapNote
.
of
()
.
startTime
(
note
.
getStartTime
())
.
endTime
(
note
.
getEndTime
())
.
build
();
}
public
MusicBeatmapNoteOuterClass
.
MusicBeatmapNote
toProto
(){
return
MusicBeatmapNoteOuterClass
.
MusicBeatmapNote
.
newBuilder
()
.
setStartTime
(
startTime
)
.
setEndTime
(
endTime
)
.
build
();
}
}
}
src/main/java/emu/grasscutter/game/activity/musicgame/MusicGamePlayerData.java
0 → 100644
View file @
12146ff0
package
emu.grasscutter.game.activity.musicgame
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.excels.MusicGameBasicData
;
import
emu.grasscutter.net.proto.MusicBriefInfoOuterClass
;
import
emu.grasscutter.net.proto.MusicGameRecordOuterClass
;
import
lombok.AccessLevel
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.experimental.FieldDefaults
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
@Data
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
@Builder
(
builderMethodName
=
"of"
)
public
class
MusicGamePlayerData
{
Map
<
Integer
,
MusicGameRecord
>
musicGameRecord
;
Map
<
Long
,
CustomBeatmapRecord
>
personalCustomBeatmapRecord
;
Map
<
Long
,
CustomBeatmapRecord
>
othersCustomBeatmapRecord
;
public
static
MusicGamePlayerData
create
(){
return
MusicGamePlayerData
.
of
()
.
musicGameRecord
(
GameData
.
getMusicGameBasicDataMap
().
values
().
stream
()
.
collect
(
Collectors
.
toMap
(
MusicGameBasicData:
:
getId
,
MusicGamePlayerData
.
MusicGameRecord
::
create
)))
.
personalCustomBeatmapRecord
(
new
HashMap
<>())
.
othersCustomBeatmapRecord
(
new
HashMap
<>())
.
build
();
}
@Data
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
@Builder
(
builderMethodName
=
"of"
)
public
static
class
MusicGameRecord
{
int
musicId
;
int
maxCombo
;
int
maxScore
;
public
static
MusicGameRecord
create
(
MusicGameBasicData
musicGameBasicData
){
return
MusicGameRecord
.
of
()
.
musicId
(
musicGameBasicData
.
getId
())
.
build
();
}
public
MusicGameRecordOuterClass
.
MusicGameRecord
toProto
(){
return
MusicGameRecordOuterClass
.
MusicGameRecord
.
newBuilder
()
.
setIsUnlock
(
true
)
.
setMaxCombo
(
maxCombo
)
.
setMaxScore
(
maxScore
)
.
build
();
}
}
@Data
@FieldDefaults
(
level
=
AccessLevel
.
PRIVATE
)
@Builder
(
builderMethodName
=
"of"
)
public
static
class
CustomBeatmapRecord
{
long
musicShareId
;
int
score
;
boolean
settle
;
public
MusicBriefInfoOuterClass
.
MusicBriefInfo
.
Builder
toProto
(){
var
musicGameBeatmap
=
MusicGameBeatmap
.
getByShareId
(
musicShareId
);
return
musicGameBeatmap
.
toBriefProto
()
.
setScore
(
score
)
.
setSettle
(
settle
)
;
}
}
}
src/main/java/emu/grasscutter/game/activity/musicgame/MusicGameScoreTrigger.java
View file @
12146ff0
package
emu.grasscutter.game.activity.musicgame
;
import
emu.grasscutter.game.activity.ActivityWatcher
;
import
emu.grasscutter.game.activity.WatcherType
;
import
emu.grasscutter.game.activity.
Activity
WatcherType
;
import
emu.grasscutter.game.props.WatcherTriggerType
;
@WatcherType
(
WatcherTriggerType
.
TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE
)
@
Activity
WatcherType
(
WatcherTriggerType
.
TRIGGER_FLEUR_FAIR_MUSIC_GAME_REACH_SCORE
)
public
class
MusicGameScoreTrigger
extends
ActivityWatcher
{
@Override
protected
boolean
isMeet
(
String
...
param
)
{
...
...
src/main/java/emu/grasscutter/game/props/ActivityType.java
0 → 100644
View file @
12146ff0
package
emu.grasscutter.game.props
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.stream.Stream
;
@Getter
@AllArgsConstructor
public
enum
ActivityType
{
NONE
(
0
),
NEW_ACTIVITY_MUSIC_GAME
(
2202
),
;
private
final
int
value
;
private
static
final
Int2ObjectMap
<
ActivityType
>
map
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Map
<
String
,
ActivityType
>
stringMap
=
new
HashMap
<>();
static
{
Stream
.
of
(
values
()).
forEach
(
e
->
{
map
.
put
(
e
.
getValue
(),
e
);
stringMap
.
put
(
e
.
name
(),
e
);
});
}
public
static
ActivityType
getTypeByValue
(
int
value
)
{
return
map
.
getOrDefault
(
value
,
NONE
);
}
public
static
ActivityType
getTypeByName
(
String
name
)
{
return
stringMap
.
getOrDefault
(
name
,
NONE
);
}
}
src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java
View file @
12146ff0
...
...
@@ -899,6 +899,12 @@ public class PacketOpcodes {
public
static
final
int
MultistagePlayInfoNotify
=
5309
;
public
static
final
int
MultistagePlaySettleNotify
=
5314
;
public
static
final
int
MultistagePlayStageEndNotify
=
5340
;
public
static
final
int
MusicGameCreateBeatmapReq
=
6326
;
public
static
final
int
MusicGameCreateBeatmapRsp
=
6347
;
public
static
final
int
MusicGameGetBeatmapReq
=
6318
;
public
static
final
int
MusicGameGetBeatmapRsp
=
6309
;
public
static
final
int
MusicGameSearchBeatmapReq
=
6343
;
public
static
final
int
MusicGameSearchBeatmapRsp
=
6304
;
public
static
final
int
MusicGameSettleReq
=
8745
;
public
static
final
int
MusicGameSettleRsp
=
8288
;
public
static
final
int
MusicGameStartReq
=
8927
;
...
...
src/main/java/emu/grasscutter/server/packet/recv/HandlerActivityTakeWatcherRewardReq.java
0 → 100644
View file @
12146ff0
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.ActivityTakeWatcherRewardReqOuterClass
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketActivityTakeWatcherRewardRsp
;
import
java.util.Optional
;
@Opcodes
(
PacketOpcodes
.
ActivityTakeWatcherRewardReq
)
public
class
HandlerActivityTakeWatcherRewardReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
var
req
=
ActivityTakeWatcherRewardReqOuterClass
.
ActivityTakeWatcherRewardReq
.
parseFrom
(
payload
);
Optional
.
ofNullable
(
session
.
getPlayer
().
getActivityManager
().
getPlayerActivityDataMap
().
get
(
req
.
getActivityId
()))
.
ifPresent
(
x
->
x
.
takeWatcherReward
(
req
.
getWatcherId
()));
session
.
send
(
new
PacketActivityTakeWatcherRewardRsp
(
req
.
getActivityId
(),
req
.
getWatcherId
()));
}
}
src/main/java/emu/grasscutter/server/packet/recv/HandlerMusicGameCreateBeatmapReq.java
0 → 100644
View file @
12146ff0
package
emu.grasscutter.server.packet.recv
;
import
emu.grasscutter.game.activity.musicgame.MusicGameActivityHandler
;
import
emu.grasscutter.game.activity.musicgame.MusicGameBeatmap
;
import
emu.grasscutter.game.props.ActivityType
;
import
emu.grasscutter.net.packet.Opcodes
;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.MusicGameCreateBeatmapReqOuterClass
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.PacketActivityInfoNotify
;
import
emu.grasscutter.server.packet.send.PacketMusicGameCreateBeatmapRsp
;
import
emu.grasscutter.utils.Utils
;
@Opcodes
(
PacketOpcodes
.
MusicGameCreateBeatmapReq
)
public
class
HandlerMusicGameCreateBeatmapReq
extends
PacketHandler
{
@Override
public
void
handle
(
GameSession
session
,
byte
[]
header
,
byte
[]
payload
)
throws
Exception
{
var
req
=
MusicGameCreateBeatmapReqOuterClass
.
MusicGameCreateBeatmapReq
.
parseFrom
(
payload
);
var
musicGameBeatmap
=
MusicGameBeatmap
.
of
()
.
musicId
(
req
.
getMusicBriefInfo
().
getMusicId
())
.
musicNoteCount
(
req
.
getMusicBriefInfo
().
getMusicNoteCount
())
.
savePosition
(
req
.
getMusicBriefInfo
().
getSavePosition
())
.
maxScore
(
req
.
getMusicBriefInfo
().
getMaxScore
())
.
authorUid
(
session
.
getPlayer
().
getUid
())
.
beatmap
(
MusicGameBeatmap
.
parse
(
req
.
getMusicRecord
().
getBeatmapItemListList
()))
.
createTime
(
Utils
.
getCurrentSeconds
())
.
build
();
// TODO avoid player save too much to make server down
musicGameBeatmap
.
save
();
var
playerData
=
session
.
getPlayer
().
getActivityManager
().
getPlayerActivityDataByActivityType
(
ActivityType
.
NEW_ACTIVITY_MUSIC_GAME
);
if
(
playerData
.
isEmpty
()){
return
;
}
var
handler
=
(
MusicGameActivityHandler
)
playerData
.
get
().
getActivityHandler
();
handler
.
addPersonalBeatmap
(
playerData
.
get
(),
musicGameBeatmap
);
session
.
send
(
new
PacketActivityInfoNotify
(
handler
.
toProto
(
playerData
.
get
())));
session
.
send
(
new
PacketMusicGameCreateBeatmapRsp
(
musicGameBeatmap
.
getMusicShareId
(),
req
.
getUnknownEnum1
()));
}
}
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