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
2935f0a6
Commit
2935f0a6
authored
Apr 26, 2022
by
Melledy
Committed by
GitHub
Apr 26, 2022
Browse files
Merge pull request #270 from Yazawazi/development
Add `bless of moon` feature
parents
782618cd
aa4b88d7
Changes
10
Show whitespace changes
Inline
Side-by-side
build.gradle
View file @
2935f0a6
...
@@ -67,6 +67,9 @@ dependencies {
...
@@ -67,6 +67,9 @@ dependencies {
implementation
group:
'org.greenrobot'
,
name:
'eventbus-java'
,
version:
'3.3.1'
implementation
group:
'org.greenrobot'
,
name:
'eventbus-java'
,
version:
'3.3.1'
implementation
group:
'org.danilopianini'
,
name:
'java-quadtree'
,
version:
'0.1.9'
implementation
group:
'org.danilopianini'
,
name:
'java-quadtree'
,
version:
'0.1.9'
implementation
group:
'org.quartz-scheduler'
,
name:
'quartz'
,
version:
'2.3.2'
implementation
group:
'org.quartz-scheduler'
,
name:
'quartz-jobs'
,
version:
'2.3.2'
protobuf
files
(
'proto/'
)
protobuf
files
(
'proto/'
)
}
}
...
...
src/main/java/emu/grasscutter/game/GenshinPlayer.java
View file @
2935f0a6
...
@@ -35,6 +35,7 @@ import emu.grasscutter.server.game.GameServer;
...
@@ -35,6 +35,7 @@ import emu.grasscutter.server.game.GameServer;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.game.GameSession
;
import
emu.grasscutter.server.packet.send.*
;
import
emu.grasscutter.server.packet.send.*
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.Position
;
import
emu.grasscutter.utils.DateHelper
;
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
;
...
@@ -81,6 +82,11 @@ public class GenshinPlayer {
...
@@ -81,6 +82,11 @@ public class GenshinPlayer {
private
int
mainCharacterId
;
private
int
mainCharacterId
;
private
boolean
godmode
;
private
boolean
godmode
;
private
boolean
moonCard
;
private
Date
moonCardStartTime
;
private
int
moonCardDuration
;
private
Set
<
Date
>
moonCardGetTimes
;
@Transient
private
boolean
paused
;
@Transient
private
boolean
paused
;
@Transient
private
int
enterSceneToken
;
@Transient
private
int
enterSceneToken
;
@Transient
private
SceneLoadState
sceneState
;
@Transient
private
SceneLoadState
sceneState
;
...
@@ -124,6 +130,7 @@ public class GenshinPlayer {
...
@@ -124,6 +130,7 @@ public class GenshinPlayer {
this
.
birthday
=
new
PlayerBirthday
();
this
.
birthday
=
new
PlayerBirthday
();
this
.
rewardedLevels
=
new
HashSet
<>();
this
.
rewardedLevels
=
new
HashSet
<>();
this
.
moonCardGetTimes
=
new
HashSet
<>();
}
}
// On player creation
// On player creation
...
@@ -486,6 +493,95 @@ public class GenshinPlayer {
...
@@ -486,6 +493,95 @@ public class GenshinPlayer {
this
.
regionId
=
regionId
;
this
.
regionId
=
regionId
;
}
}
public
boolean
inMoonCard
()
{
return
moonCard
;
}
public
void
setMoonCard
(
boolean
moonCard
)
{
this
.
moonCard
=
moonCard
;
}
public
void
addMoonCardDays
(
int
days
)
{
this
.
moonCardDuration
+=
days
;
}
public
int
getMoonCardDuration
()
{
return
moonCardDuration
;
}
public
void
setMoonCardDuration
(
int
moonCardDuration
)
{
this
.
moonCardDuration
=
moonCardDuration
;
}
public
Date
getMoonCardStartTime
()
{
return
moonCardStartTime
;
}
public
void
setMoonCardStartTime
(
Date
moonCardStartTime
)
{
this
.
moonCardStartTime
=
moonCardStartTime
;
}
public
Set
<
Date
>
getMoonCardGetTimes
()
{
return
moonCardGetTimes
;
}
public
void
setMoonCardGetTimes
(
Set
<
Date
>
moonCardGetTimes
)
{
this
.
moonCardGetTimes
=
moonCardGetTimes
;
}
public
int
getMoonCardRemainDays
()
{
Calendar
remainCalendar
=
Calendar
.
getInstance
();
remainCalendar
.
setTime
(
moonCardStartTime
);
remainCalendar
.
add
(
Calendar
.
DATE
,
moonCardDuration
);
Date
theLastDay
=
remainCalendar
.
getTime
();
Date
now
=
DateHelper
.
onlyYearMonthDay
(
new
Date
());
return
(
int
)
((
theLastDay
.
getTime
()
-
now
.
getTime
())
/
(
24
*
60
*
60
*
1000
));
// By copilot
}
public
void
rechargeMoonCard
()
{
LinkedList
<
GenshinItem
>
items
=
new
LinkedList
<
GenshinItem
>();
for
(
int
i
=
0
;
i
<
300
;
i
++)
{
items
.
add
(
new
GenshinItem
(
203
));
}
inventory
.
addItems
(
items
);
if
(!
moonCard
)
{
moonCard
=
true
;
Date
now
=
new
Date
();
moonCardStartTime
=
DateHelper
.
onlyYearMonthDay
(
now
);
moonCardDuration
=
30
;
}
else
{
moonCardDuration
+=
30
;
}
if
(!
moonCardGetTimes
.
contains
(
moonCardStartTime
))
{
moonCardGetTimes
.
add
(
moonCardStartTime
);
}
}
public
void
getTodayMoonCard
()
{
if
(!
moonCard
)
{
return
;
}
Date
now
=
DateHelper
.
onlyYearMonthDay
(
new
Date
());
if
(
moonCardGetTimes
.
contains
(
now
))
{
return
;
}
Date
stopTime
=
new
Date
();
Calendar
stopCalendar
=
Calendar
.
getInstance
();
stopCalendar
.
setTime
(
stopTime
);
stopCalendar
.
add
(
Calendar
.
DATE
,
moonCardDuration
);
stopTime
=
stopCalendar
.
getTime
();
if
(
now
.
after
(
stopTime
))
{
moonCard
=
false
;
return
;
}
moonCardGetTimes
.
add
(
now
);
addMoonCardDays
(
1
);
GenshinItem
genshinItem
=
new
GenshinItem
(
201
,
90
);
getInventory
().
addItem
(
genshinItem
);
session
.
send
(
new
PacketItemAddHintNotify
(
genshinItem
,
ActionReason
.
BlessingRedeemReward
));
session
.
send
(
new
PacketCardProductRewardNotify
(
getMoonCardRemainDays
()));
}
public
boolean
inGodmode
()
{
public
boolean
inGodmode
()
{
return
godmode
;
return
godmode
;
}
}
...
...
src/main/java/emu/grasscutter/game/managers/InventoryManager.java
View file @
2935f0a6
...
@@ -923,6 +923,11 @@ public class InventoryManager {
...
@@ -923,6 +923,11 @@ public class InventoryManager {
break
;
break
;
}
}
if
(
useItem
.
getItemId
()
==
1202
)
{
player
.
rechargeMoonCard
();
used
=
1
;
}
if
(
used
>
0
)
{
if
(
used
>
0
)
{
player
.
getInventory
().
removeItem
(
useItem
,
used
);
player
.
getInventory
().
removeItem
(
useItem
,
used
);
return
useItem
;
return
useItem
;
...
...
src/main/java/emu/grasscutter/server/game/GameServer.java
View file @
2935f0a6
...
@@ -25,6 +25,7 @@ import emu.grasscutter.server.event.ServerEvent;
...
@@ -25,6 +25,7 @@ import emu.grasscutter.server.event.ServerEvent;
import
emu.grasscutter.server.event.game.ServerTickEvent
;
import
emu.grasscutter.server.event.game.ServerTickEvent
;
import
emu.grasscutter.server.event.internal.ServerStartEvent
;
import
emu.grasscutter.server.event.internal.ServerStartEvent
;
import
emu.grasscutter.server.event.internal.ServerStopEvent
;
import
emu.grasscutter.server.event.internal.ServerStopEvent
;
import
emu.grasscutter.task.TaskMap
;
public
final
class
GameServer
extends
MihoyoKcpServer
{
public
final
class
GameServer
extends
MihoyoKcpServer
{
private
final
InetSocketAddress
address
;
private
final
InetSocketAddress
address
;
...
@@ -40,6 +41,7 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -40,6 +41,7 @@ public final class GameServer extends MihoyoKcpServer {
private
final
MultiplayerManager
multiplayerManager
;
private
final
MultiplayerManager
multiplayerManager
;
private
final
DungeonManager
dungeonManager
;
private
final
DungeonManager
dungeonManager
;
private
final
CommandMap
commandMap
;
private
final
CommandMap
commandMap
;
private
final
TaskMap
taskMap
;
public
GameServer
(
InetSocketAddress
address
)
{
public
GameServer
(
InetSocketAddress
address
)
{
super
(
address
);
super
(
address
);
...
@@ -57,6 +59,7 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -57,6 +59,7 @@ public final class GameServer extends MihoyoKcpServer {
this
.
multiplayerManager
=
new
MultiplayerManager
(
this
);
this
.
multiplayerManager
=
new
MultiplayerManager
(
this
);
this
.
dungeonManager
=
new
DungeonManager
(
this
);
this
.
dungeonManager
=
new
DungeonManager
(
this
);
this
.
commandMap
=
new
CommandMap
(
true
);
this
.
commandMap
=
new
CommandMap
(
true
);
this
.
taskMap
=
new
TaskMap
(
true
);
// Schedule game loop.
// Schedule game loop.
Timer
gameLoop
=
new
Timer
();
Timer
gameLoop
=
new
Timer
();
...
@@ -115,6 +118,10 @@ public final class GameServer extends MihoyoKcpServer {
...
@@ -115,6 +118,10 @@ public final class GameServer extends MihoyoKcpServer {
return
this
.
commandMap
;
return
this
.
commandMap
;
}
}
public
TaskMap
getTaskMap
()
{
return
this
.
taskMap
;
}
public
void
registerPlayer
(
GenshinPlayer
player
)
{
public
void
registerPlayer
(
GenshinPlayer
player
)
{
getPlayers
().
put
(
player
.
getUid
(),
player
);
getPlayers
().
put
(
player
.
getUid
(),
player
);
}
}
...
...
src/main/java/emu/grasscutter/server/packet/send/PacketCardProductRewardNotify.java
0 → 100644
View file @
2935f0a6
package
emu.grasscutter.server.packet.send
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.packet.PacketOpcodes
;
import
emu.grasscutter.net.proto.CardProductRewardNotifyOuterClass.CardProductRewardNotify
;
public
class
PacketCardProductRewardNotify
extends
GenshinPacket
{
public
PacketCardProductRewardNotify
(
int
remainsDay
)
{
super
(
PacketOpcodes
.
CardProductRewardNotify
);
CardProductRewardNotify
proto
=
CardProductRewardNotify
.
newBuilder
()
.
setProductId
(
"ys_chn_blessofmoon_tier5"
)
.
setHcoin
(
90
)
.
setRemainDays
(
remainsDay
)
.
build
();
// Hard code Product id keep cool 😎
this
.
setData
(
proto
);
}
}
src/main/java/emu/grasscutter/task/Task.java
0 → 100644
View file @
2935f0a6
package
emu.grasscutter.task
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
/*
* So what is cron expression?
The format of a Cron expression is as follows.
Second Minute Hour Day Month Week Year
Seconds: 0-59
Minute: 0-59
hour: 0-23
Day: 1-31
Month: 1-12
Week: 1-7 (0-6 sometimes)
Year: Specify your own
If you want to express every second or every minute or something like that, use the * symbol in that position;
if you want to express more than one such as every 15 minutes and every 30 minutes, you can write:`15, 30`.
For the rest of the wildcard characters, please Google them yourself
*/
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
Task
{
String
taskName
()
default
"NO_NAME"
;
String
taskCronExpression
()
default
"0 0 0 0 0 ?"
;
String
triggerName
()
default
"NO_NAME"
;
}
src/main/java/emu/grasscutter/task/TaskHandler.java
0 → 100644
View file @
2935f0a6
package
emu.grasscutter.task
;
import
org.quartz.Job
;
import
org.quartz.JobExecutionContext
;
import
org.quartz.JobExecutionException
;
public
interface
TaskHandler
extends
Job
{
default
void
execute
(
JobExecutionContext
context
)
throws
JobExecutionException
{
}
}
src/main/java/emu/grasscutter/task/TaskMap.java
0 → 100644
View file @
2935f0a6
package
emu.grasscutter.task
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.game.Account
;
import
emu.grasscutter.game.GenshinPlayer
;
import
org.quartz.CronScheduleBuilder
;
import
org.quartz.CronTrigger
;
import
org.quartz.JobBuilder
;
import
org.quartz.JobDetail
;
import
org.quartz.Scheduler
;
import
org.quartz.SchedulerException
;
import
org.quartz.SchedulerFactory
;
import
org.quartz.Trigger
;
import
org.quartz.TriggerBuilder
;
import
org.quartz.impl.StdSchedulerFactory
;
import
org.quartz.spi.MutableTrigger
;
import
org.reflections.Reflections
;
import
java.util.*
;
@SuppressWarnings
({
"UnusedReturnValue"
,
"unused"
})
public
final
class
TaskMap
{
private
final
Map
<
String
,
TaskHandler
>
tasks
=
new
HashMap
<>();
private
final
Map
<
String
,
Task
>
annotations
=
new
HashMap
<>();
private
final
SchedulerFactory
schedulerFactory
=
new
StdSchedulerFactory
();
public
TaskMap
()
{
this
(
false
);
}
public
TaskMap
(
boolean
scan
)
{
if
(
scan
)
this
.
scan
();
}
public
static
TaskMap
getInstance
()
{
return
Grasscutter
.
getGameServer
().
getTaskMap
();
}
public
TaskMap
registerTask
(
String
taskName
,
TaskHandler
task
)
{
Task
annotation
=
task
.
getClass
().
getAnnotation
(
Task
.
class
);
this
.
annotations
.
put
(
taskName
,
annotation
);
this
.
tasks
.
put
(
taskName
,
task
);
// register task
try
{
Scheduler
scheduler
=
schedulerFactory
.
getScheduler
();
JobDetail
job
=
JobBuilder
.
newJob
(
task
.
getClass
())
.
withIdentity
(
taskName
)
.
build
();
Trigger
convTrigger
=
TriggerBuilder
.
newTrigger
()
.
withIdentity
(
annotation
.
triggerName
())
.
withSchedule
(
CronScheduleBuilder
.
cronSchedule
(
annotation
.
taskCronExpression
()))
.
build
();
scheduler
.
scheduleJob
(
job
,
convTrigger
);
scheduler
.
start
();
}
catch
(
SchedulerException
e
)
{
e
.
printStackTrace
();
}
return
this
;
}
public
List
<
TaskHandler
>
getHandlersAsList
()
{
return
new
LinkedList
<>(
this
.
tasks
.
values
());
}
public
HashMap
<
String
,
TaskHandler
>
getHandlers
()
{
return
new
LinkedHashMap
<>(
this
.
tasks
);
}
public
TaskHandler
getHandler
(
String
taskName
)
{
return
this
.
tasks
.
get
(
taskName
);
}
private
void
scan
()
{
Reflections
reflector
=
Grasscutter
.
reflector
;
Set
<
Class
<?>>
classes
=
reflector
.
getTypesAnnotatedWith
(
Task
.
class
);
classes
.
forEach
(
annotated
->
{
try
{
Task
taskData
=
annotated
.
getAnnotation
(
Task
.
class
);
Object
object
=
annotated
.
newInstance
();
if
(
object
instanceof
TaskHandler
)
this
.
registerTask
(
taskData
.
taskName
(),
(
TaskHandler
)
object
);
else
Grasscutter
.
getLogger
().
error
(
"Class "
+
annotated
.
getName
()
+
" is not a TaskHandler!"
);
}
catch
(
Exception
exception
)
{
Grasscutter
.
getLogger
().
error
(
"Failed to register task handler for "
+
annotated
.
getSimpleName
(),
exception
);
}
});
}
}
src/main/java/emu/grasscutter/task/tasks/MoonCard.java
0 → 100644
View file @
2935f0a6
package
emu.grasscutter.task.tasks
;
import
emu.grasscutter.database.DatabaseManager
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.task.Task
;
import
emu.grasscutter.task.TaskHandler
;
import
java.util.List
;
import
org.quartz.JobExecutionContext
;
import
org.quartz.JobExecutionException
;
@Task
(
taskName
=
"MoonCard"
,
taskCronExpression
=
"0 0 0 * * ?"
,
triggerName
=
"MoonCardTrigger"
)
// taskCronExpression: Fixed time period: 0:0:0 every day (twenty-four hour system)
public
final
class
MoonCard
implements
TaskHandler
{
@Override
public
void
execute
(
JobExecutionContext
context
)
throws
JobExecutionException
{
List
<
GenshinPlayer
>
players
=
DatabaseManager
.
getDatastore
().
find
(
GenshinPlayer
.
class
).
stream
().
toList
();
for
(
GenshinPlayer
player
:
players
)
{
if
(
player
.
isOnline
())
{
if
(
player
.
inMoonCard
())
{
player
.
getTodayMoonCard
();
}
}
}
}
}
src/main/java/emu/grasscutter/utils/DateHelper.java
0 → 100644
View file @
2935f0a6
package
emu.grasscutter.utils
;
import
java.util.Date
;
import
java.util.Calendar
;
public
final
class
DateHelper
{
public
static
Date
onlyYearMonthDay
(
Date
now
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
setTime
(
now
);
calendar
.
set
(
Calendar
.
HOUR_OF_DAY
,
0
);
calendar
.
set
(
Calendar
.
MINUTE
,
0
);
calendar
.
set
(
Calendar
.
SECOND
,
0
);
calendar
.
set
(
Calendar
.
MILLISECOND
,
0
);
return
calendar
.
getTime
();
}
}
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