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
627a2f1e
Commit
627a2f1e
authored
Apr 26, 2022
by
Magix
Committed by
GitHub
Apr 26, 2022
Browse files
Merge branch 'api' into development
parents
fe055af5
444270fd
Changes
20
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
627a2f1e
...
...
@@ -30,6 +30,9 @@ hs_err_pid*
build/
out/
# Ignore Gradle properties
gradle.properties
# Eclipse
.project
.classpath
...
...
build.gradle
View file @
627a2f1e
...
...
@@ -12,11 +12,22 @@ plugins {
// Apply the application plugin to add support for building a CLI application
id
'application'
id
'maven-publish'
id
'signing'
}
group
=
'tech.xigam'
version
=
'1.0.0-dev'
sourceCompatibility
=
17
targetCompatibility
=
17
java
{
withJavadocJar
()
withSourcesJar
()
}
repositories
{
mavenCentral
()
}
...
...
@@ -65,3 +76,68 @@ jar {
destinationDir
=
file
(
"."
)
}
publishing
{
publications
{
mavenJava
(
MavenPublication
)
{
artifactId
=
'grasscutter'
from
components
.
java
versionMapping
{
usage
(
'java-api'
)
{
fromResolutionOf
(
'runtimeClasspath'
)
}
usage
(
'java-runtime'
)
{
fromResolutionResult
()
}
}
pom
{
name
=
'Grasscutter'
description
=
'A server software reimplementation for an anime game.'
url
=
'https://github.com/Grasscutters/Grasscutter'
licenses
{
license
{
name
=
'The Apache License, Version 2.0'
url
=
'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers
{
developer
{
id
=
'melledy'
name
=
'Melledy'
email
=
'melledy@xigam.tech'
// not a real email kek
}
developer
{
id
=
'magix'
name
=
'Magix'
email
=
'magix@xigam.tech'
}
}
scm
{
connection
=
'scm:git:git@github.com:Grasscutters/Grasscutter.git'
developerConnection
=
'scm:git:ssh://github.com:Grasscutters/Grasscutter.git'
url
=
'https://github.com/Grasscutters/Grasscutter'
}
}
}
}
repositories
{
maven
{
// change URLs to point to your repos, e.g. http://my.org/repo
def
releasesRepoUrl
=
'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
def
snapshotsRepoUrl
=
'https://s01.oss.sonatype.org/content/repositories/snapshots/'
url
=
version
.
endsWith
(
'SNAPSHOT'
)
?
snapshotsRepoUrl
:
releasesRepoUrl
name
=
'sonatype'
credentials
(
PasswordCredentials
)
}
}
}
signing
{
sign
publishing
.
publications
.
mavenJava
}
javadoc
{
if
(
JavaVersion
.
current
().
isJava9Compatible
())
{
options
.
addBooleanOption
(
'html5'
,
true
)
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/Grasscutter.java
View file @
627a2f1e
...
...
@@ -36,7 +36,7 @@ public final class Grasscutter {
private
static
GameServer
gameServer
;
private
static
PluginManager
pluginManager
;
public
static
final
Reflections
reflector
=
new
Reflections
();
public
static
final
Reflections
reflector
=
new
Reflections
(
"emu.grasscutter"
);
static
{
// Declare logback configuration.
...
...
@@ -70,13 +70,13 @@ public final class Grasscutter {
// Database
DatabaseManager
.
initialize
();
// Create plugin manager instance.
pluginManager
=
new
PluginManager
();
// Create server instances.
dispatchServer
=
new
DispatchServer
();
gameServer
=
new
GameServer
(
new
InetSocketAddress
(
getConfig
().
getGameServerOptions
().
Ip
,
getConfig
().
getGameServerOptions
().
Port
));
// Create plugin manager instance.
pluginManager
=
new
PluginManager
();
// Start servers.
if
(
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
dispatchServer
.
start
();
...
...
src/main/java/emu/grasscutter/command/commands/ClearCommand.java
View file @
627a2f1e
...
...
@@ -3,15 +3,10 @@ package emu.grasscutter.command.commands;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.command.Command
;
import
emu.grasscutter.command.CommandHandler
;
import
emu.grasscutter.data.GenshinData
;
import
emu.grasscutter.data.def.ItemData
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.inventory.GenshinItem
;
import
emu.grasscutter.game.inventory.Inventory
;
import
emu.grasscutter.game.inventory.ItemType
;
import
java.util.Collection
;
import
java.util.LinkedList
;
import
java.util.List
;
@Command
(
label
=
"clear"
,
usage
=
"clear <all|wp|art|mat>"
,
//Merged /clearartifacts and /clearweapons to /clear <args> [uid]
...
...
@@ -33,62 +28,62 @@ public final class ClearCommand implements CommandHandler {
try
{
target
=
Integer
.
parseInt
(
args
.
get
(
0
));
GenshinPlayer
targetPlayer
=
Grasscutter
.
getGameServer
().
getPlayerByUid
(
target
);
if
(
targetPlayer
==
null
&&
sender
!=
null
)
{
if
(
targetPlayer
==
null
)
{
target
=
sender
.
getUid
();
}
else
{
switch
(
cmdSwitch
){
case
"wp"
:
switch
(
cmdSwitch
)
{
case
"wp"
->
{
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_WEAPON
)
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_WEAPON
)
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
sender
.
dropMessage
(
"Cleared weapons for "
+
targetPlayer
.
getNickname
()
+
" ."
);
break
;
case
"art"
:
}
case
"art"
->
{
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
)
.
filter
(
item
->
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
)
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
)
.
filter
(
item
->
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
)
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
sender
.
dropMessage
(
"Cleared artifacts for "
+
targetPlayer
.
getNickname
()
+
" ."
);
break
;
case
"mat"
:
}
case
"mat"
->
{
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_MATERIAL
)
.
filter
(
item
->
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
)
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
.
filter
(
item
->
item
.
getItemType
()
==
ItemType
.
ITEM_MATERIAL
)
.
filter
(
item
->
item
.
getLevel
()
==
1
&&
item
.
getExp
()
==
0
)
.
filter
(
item
->
!
item
.
isLocked
()
&&
!
item
.
isEquipped
())
.
forEach
(
item
->
playerInventory
.
removeItem
(
item
,
item
.
getCount
()));
sender
.
dropMessage
(
"Cleared artifacts for "
+
targetPlayer
.
getNickname
()
+
" ."
);
break
;
case
"all"
:
}
case
"all"
->
{
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item1
->
item1
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
)
.
filter
(
item1
->
item1
.
getLevel
()
==
1
&&
item1
.
getExp
()
==
0
)
.
filter
(
item1
->
!
item1
.
isLocked
()
&&
!
item1
.
isEquipped
())
.
forEach
(
item1
->
playerInventory
.
removeItem
(
item1
,
item1
.
getCount
()));
.
filter
(
item1
->
item1
.
getItemType
()
==
ItemType
.
ITEM_RELIQUARY
)
.
filter
(
item1
->
item1
.
getLevel
()
==
1
&&
item1
.
getExp
()
==
0
)
.
filter
(
item1
->
!
item1
.
isLocked
()
&&
!
item1
.
isEquipped
())
.
forEach
(
item1
->
playerInventory
.
removeItem
(
item1
,
item1
.
getCount
()));
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item2
->
item2
.
getItemType
()
==
ItemType
.
ITEM_MATERIAL
)
.
filter
(
item2
->
!
item2
.
isLocked
()
&&
!
item2
.
isEquipped
())
.
forEach
(
item2
->
playerInventory
.
removeItem
(
item2
,
item2
.
getCount
()));
.
filter
(
item2
->
item2
.
getItemType
()
==
ItemType
.
ITEM_MATERIAL
)
.
filter
(
item2
->
!
item2
.
isLocked
()
&&
!
item2
.
isEquipped
())
.
forEach
(
item2
->
playerInventory
.
removeItem
(
item2
,
item2
.
getCount
()));
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item3
->
item3
.
getItemType
()
==
ItemType
.
ITEM_WEAPON
)
.
filter
(
item3
->
item3
.
getLevel
()
==
1
&&
item3
.
getExp
()
==
0
)
.
filter
(
item3
->
!
item3
.
isLocked
()
&&
!
item3
.
isEquipped
())
.
forEach
(
item3
->
playerInventory
.
removeItem
(
item3
,
item3
.
getCount
()));
.
filter
(
item3
->
item3
.
getItemType
()
==
ItemType
.
ITEM_WEAPON
)
.
filter
(
item3
->
item3
.
getLevel
()
==
1
&&
item3
.
getExp
()
==
0
)
.
filter
(
item3
->
!
item3
.
isLocked
()
&&
!
item3
.
isEquipped
())
.
forEach
(
item3
->
playerInventory
.
removeItem
(
item3
,
item3
.
getCount
()));
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item4
->
item4
.
getItemType
()
==
ItemType
.
ITEM_FURNITURE
)
.
filter
(
item4
->
!
item4
.
isLocked
()
&&
!
item4
.
isEquipped
())
.
forEach
(
item4
->
playerInventory
.
removeItem
(
item4
,
item4
.
getCount
()));
.
filter
(
item4
->
item4
.
getItemType
()
==
ItemType
.
ITEM_FURNITURE
)
.
filter
(
item4
->
!
item4
.
isLocked
()
&&
!
item4
.
isEquipped
())
.
forEach
(
item4
->
playerInventory
.
removeItem
(
item4
,
item4
.
getCount
()));
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item5
->
item5
.
getItemType
()
==
ItemType
.
ITEM_DISPLAY
)
.
filter
(
item5
->
!
item5
.
isLocked
()
&&
!
item5
.
isEquipped
())
.
forEach
(
item5
->
playerInventory
.
removeItem
(
item5
,
item5
.
getCount
()));
.
filter
(
item5
->
item5
.
getItemType
()
==
ItemType
.
ITEM_DISPLAY
)
.
filter
(
item5
->
!
item5
.
isLocked
()
&&
!
item5
.
isEquipped
())
.
forEach
(
item5
->
playerInventory
.
removeItem
(
item5
,
item5
.
getCount
()));
playerInventory
.
getItems
().
values
().
stream
()
.
filter
(
item6
->
item6
.
getItemType
()
==
ItemType
.
ITEM_VIRTUAL
)
.
filter
(
item6
->
!
item6
.
isLocked
()
&&
!
item6
.
isEquipped
())
.
forEach
(
item6
->
playerInventory
.
removeItem
(
item6
,
item6
.
getCount
()));
.
filter
(
item6
->
item6
.
getItemType
()
==
ItemType
.
ITEM_VIRTUAL
)
.
filter
(
item6
->
!
item6
.
isLocked
()
&&
!
item6
.
isEquipped
())
.
forEach
(
item6
->
playerInventory
.
removeItem
(
item6
,
item6
.
getCount
()));
sender
.
dropMessage
(
"Cleared everything for "
+
targetPlayer
.
getNickname
()
+
" ."
);
break
;
}
}
}
}
catch
(
NumberFormatException
ignored
)
{
...
...
src/main/java/emu/grasscutter/command/commands/HealCommand.java
View file @
627a2f1e
...
...
@@ -6,20 +6,19 @@ import emu.grasscutter.game.GenshinPlayer;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify
;
import
emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify
;
import
java.util.List
;
@Command
(
label
=
"heal"
,
usage
=
"heal|h"
,
description
=
"Heal all characters in your current team."
,
aliases
=
{
"h"
},
permission
=
"player.heal"
)
public
class
HealCommand
implements
CommandHandler
{
@Command
(
label
=
"heal"
,
usage
=
"heal|h"
,
aliases
=
{
"h"
},
description
=
"Heal all characters in your current team."
,
permission
=
"player.heal"
)
public
final
class
HealCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
sender
,
List
<
String
>
args
)
{
if
(
sender
==
null
)
{
CommandHandler
.
sendMessage
(
null
,
"Run this command in-game."
);
return
;
}
sender
.
getTeamManager
().
getActiveTeam
().
forEach
(
entity
->
{
boolean
isAlive
=
entity
.
isAlive
();
entity
.
setFightProperty
(
...
...
@@ -31,6 +30,6 @@ public class HealCommand implements CommandHandler {
entity
.
getWorld
().
broadcastPacket
(
new
PacketAvatarLifeStateChangeNotify
(
entity
.
getAvatar
()));
}
});
CommandHandler
.
sendMessage
(
sender
,
"All characters
are
healed."
);
CommandHandler
.
sendMessage
(
sender
,
"All characters
have been
healed."
);
}
}
src/main/java/emu/grasscutter/command/commands/ListCommand.java
View file @
627a2f1e
...
...
@@ -9,7 +9,7 @@ import java.util.List;
import
java.util.Map
;
@Command
(
label
=
"list"
,
description
=
"List online players"
)
public
class
ListCommand
implements
CommandHandler
{
public
final
class
ListCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
sender
,
List
<
String
>
args
)
{
...
...
@@ -19,14 +19,10 @@ public class ListCommand implements CommandHandler {
if
(
playersMap
.
size
()
!=
0
)
{
StringBuilder
playerSet
=
new
StringBuilder
();
for
(
Map
.
Entry
<
Integer
,
GenshinPlayer
>
entry
:
playersMap
.
entrySet
())
{
playerSet
.
append
(
entry
.
getValue
().
getNickname
());
playerSet
.
append
(
", "
);
}
playersMap
.
values
().
forEach
(
player
->
playerSet
.
append
(
player
.
getNickname
()).
append
(
", "
));
String
players
=
playerSet
.
toString
();
CommandHandler
.
sendMessage
(
sender
,
players
.
substring
(
0
,
players
.
length
()
-
2
));
}
}
...
...
src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java
View file @
627a2f1e
...
...
@@ -43,7 +43,7 @@ public final class SetFetterLevelCommand implements CommandHandler {
sender
.
sendPacket
(
new
PacketAvatarFetterDataNotify
(
avatar
));
CommandHandler
.
sendMessage
(
sender
,
"Fetter level set to "
+
fetterLevel
);
}
catch
(
NumberFormatException
ignored
)
{
CommandHandler
.
sendMessage
(
null
,
"Invalid fetter level."
);
CommandHandler
.
sendMessage
(
sender
,
"Invalid fetter level."
);
}
}
...
...
src/main/java/emu/grasscutter/command/commands/TalentCommand.java
View file @
627a2f1e
...
...
@@ -13,7 +13,7 @@ import java.util.List;
@Command
(
label
=
"talent"
,
usage
=
"talent <talentID> <value>"
,
description
=
"Set talent level for your current active character"
,
permission
=
"player.settalent"
)
public
class
TalentCommand
implements
CommandHandler
{
public
final
class
TalentCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
sender
,
List
<
String
>
args
)
{
...
...
src/main/java/emu/grasscutter/command/commands/Tele
P
ortCommand.java
→
src/main/java/emu/grasscutter/command/commands/Tele
p
ortCommand.java
View file @
627a2f1e
...
...
@@ -9,7 +9,7 @@ import java.util.List;
@Command
(
label
=
"teleport"
,
usage
=
"teleport <x> <y> <z>"
,
aliases
=
{
"tp"
},
description
=
"Change the player's position."
,
permission
=
"player.teleport"
)
public
class
Tele
P
ortCommand
implements
CommandHandler
{
public
final
class
Tele
p
ortCommand
implements
CommandHandler
{
@Override
public
void
execute
(
GenshinPlayer
sender
,
List
<
String
>
args
)
{
...
...
src/main/java/emu/grasscutter/game/gacha/GachaManager.java
View file @
627a2f1e
...
...
@@ -286,8 +286,6 @@ public class GachaManager {
this
.
watchService
=
FileSystems
.
getDefault
().
newWatchService
();
Path
path
=
new
File
(
Grasscutter
.
getConfig
().
DATA_FOLDER
).
toPath
();
path
.
register
(
watchService
,
new
WatchEvent
.
Kind
[]{
StandardWatchEventKinds
.
ENTRY_MODIFY
},
SensitivityWatchEventModifier
.
HIGH
);
server
.
OnGameServerTick
.
register
(
this
);
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"
);
e
.
printStackTrace
();
...
...
src/main/java/emu/grasscutter/plugin/api/Item.java
0 → 100644
View file @
627a2f1e
package
emu.grasscutter.plugin.api
;
public
enum
Item
{
/* TODO: Use handbook to generate an Item enum. */
}
src/main/java/emu/grasscutter/plugin/api/PlayerHook.java
0 → 100644
View file @
627a2f1e
package
emu.grasscutter.plugin.api
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.game.avatar.GenshinAvatar
;
import
emu.grasscutter.game.entity.EntityAvatar
;
import
emu.grasscutter.game.props.EnterReason
;
import
emu.grasscutter.game.props.FightProperty
;
import
emu.grasscutter.net.packet.GenshinPacket
;
import
emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType
;
import
emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify
;
import
emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify
;
import
emu.grasscutter.utils.Position
;
/**
* Hooks into the {@link GenshinPlayer} class, adding convenient ways to do certain things.
*/
public
final
class
PlayerHook
{
private
final
GenshinPlayer
player
;
/**
* Hooks into the player.
* @param player The player to hook into.
*/
public
PlayerHook
(
GenshinPlayer
player
)
{
this
.
player
=
player
;
}
/**
* Kicks a player from the server.
*/
public
void
kick
()
{
this
.
player
.
getSession
().
close
();
}
/**
* Sends a player to another scene.
* @param sceneId The scene to send the player to.
*/
public
void
changeScenes
(
int
sceneId
)
{
this
.
player
.
getWorld
().
transferPlayerToScene
(
this
.
player
,
sceneId
,
this
.
player
.
getPos
());
}
/**
* Broadcasts an avatar property notify to all world players.
* @param property The property that was updated.
*/
public
void
updateFightProperty
(
FightProperty
property
)
{
this
.
broadcastPacketToWorld
(
new
PacketAvatarFightPropUpdateNotify
(
this
.
getCurrentAvatar
(),
property
));
}
/**
* Broadcasts the packet sent to all world players.
* @param packet The packet to send.
*/
public
void
broadcastPacketToWorld
(
GenshinPacket
packet
)
{
this
.
player
.
getWorld
().
broadcastPacket
(
packet
);
}
/**
* Set the currently equipped avatar's health.
* @param health The health to set the avatar to.
*/
public
void
setHealth
(
float
health
)
{
this
.
getCurrentAvatarEntity
().
setFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
,
health
);
this
.
updateFightProperty
(
FightProperty
.
FIGHT_PROP_CUR_HP
);
}
/**
* Revives the specified avatar.
* @param avatar The avatar to revive.
*/
public
void
reviveAvatar
(
GenshinAvatar
avatar
)
{
this
.
broadcastPacketToWorld
(
new
PacketAvatarLifeStateChangeNotify
(
avatar
));
}
/**
* Teleports a player to a position.
* This will **not** transfer the player to another scene.
* @param position The position to teleport the player to.
*/
public
void
teleport
(
Position
position
)
{
this
.
player
.
getPos
().
set
(
position
);
this
.
player
.
sendPacket
(
new
PacketPlayerEnterSceneNotify
(
this
.
player
,
EnterType
.
EnterJump
,
EnterReason
.
TransPoint
,
this
.
player
.
getSceneId
(),
position
));
}
/**
* Gets the currently selected avatar's max health.
* @return The max health as a float.
*/
public
float
getMaxHealth
()
{
return
this
.
getCurrentAvatarEntity
().
getFightProperty
(
FightProperty
.
FIGHT_PROP_MAX_HP
);
}
/**
* Gets the currently selected avatar in entity form.
* @return The avatar as an {@link EntityAvatar}.
*/
public
EntityAvatar
getCurrentAvatarEntity
()
{
return
this
.
player
.
getTeamManager
().
getCurrentAvatarEntity
();
}
/**
* Gets the currently selected avatar.
* @return The avatar as an {@link GenshinAvatar}.
*/
public
GenshinAvatar
getCurrentAvatar
()
{
return
this
.
getCurrentAvatarEntity
().
getAvatar
();
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/plugin/api/README.md
0 → 100644
View file @
627a2f1e
# Grasscutter Plugin API
**Warning!**
As of now, this is a work in progress and isn't completely documented.
\ No newline at end of file
src/main/java/emu/grasscutter/plugin/api/ServerHook.java
0 → 100644
View file @
627a2f1e
package
emu.grasscutter.plugin.api
;
import
emu.grasscutter.game.GenshinPlayer
;
import
emu.grasscutter.server.game.GameServer
;
import
java.util.LinkedList
;
import
java.util.List
;
/**
* Hooks into the {@link GameServer} class, adding convenient ways to do certain things.
*/
public
final
class
ServerHook
{
private
static
ServerHook
instance
;
private
final
GameServer
server
;
/**
* Gets the server hook instance.
* @return A {@link ServerHook} singleton.
*/
public
static
ServerHook
getInstance
()
{
return
instance
;
}
/**
* Hooks into a server.
* @param server The server to hook into.
*/
public
ServerHook
(
GameServer
server
)
{
this
.
server
=
server
;
instance
=
this
;
}
/**
* Gets all online players.
* @return Players connected to the server.
*/
public
List
<
GenshinPlayer
>
getOnlinePlayers
()
{
return
new
LinkedList
<>(
this
.
server
.
getPlayers
().
values
());
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/server/dispatch/DispatchServer.java
View file @
627a2f1e
...
...
@@ -103,8 +103,8 @@ public final class DispatchServer {
byte
[]
decoded2
=
Base64
.
getDecoder
().
decode
(
query_cur_region
);
QueryCurrRegionHttpRsp
regionQuery
=
QueryCurrRegionHttpRsp
.
parseFrom
(
decoded2
);
List
<
RegionSimpleInfo
>
servers
=
new
ArrayList
<
RegionSimpleInfo
>();
List
<
String
>
usedNames
=
new
ArrayList
<
String
>();
// List to check for potential naming conflicts
List
<
RegionSimpleInfo
>
servers
=
new
ArrayList
<>();
List
<
String
>
usedNames
=
new
ArrayList
<>();
// List to check for potential naming conflicts
if
(
Grasscutter
.
getConfig
().
RunMode
.
equalsIgnoreCase
(
"HYBRID"
))
{
// Automatically add the game server if in
// hybrid mode
RegionSimpleInfo
server
=
RegionSimpleInfo
.
newBuilder
()
...
...
@@ -268,7 +268,10 @@ public final class DispatchServer {
Grasscutter
.
getLogger
()
.
info
(
String
.
format
(
"[Dispatch] Client %s request: query_region_list"
,
t
.
getRemoteAddress
()));
responseHTML
(
t
,
regionListBase64
);
// Invoke event.
QueryAllRegionsEvent
event
=
new
QueryAllRegionsEvent
(
regionListBase64
);
event
.
call
();
// Respond with event result.
responseHTML
(
t
,
event
.
getRegionList
());
});
for
(
String
regionName
:
regions
.
keySet
())
{
...
...
src/main/java/emu/grasscutter/server/event/ServerEvent.java
View file @
627a2f1e
...
...
@@ -10,6 +10,10 @@ public abstract class ServerEvent extends Event {
this
.
type
=
type
;
}
public
Type
getServerType
()
{
return
this
.
type
;
}
public
enum
Type
{
DISPATCH
,
GAME
...
...
src/main/java/emu/grasscutter/server/event/game/ServerTickEvent.java
0 → 100644
View file @
627a2f1e
package
emu.grasscutter.server.event.game
;
import
emu.grasscutter.server.event.ServerEvent
;
public
final
class
ServerTickEvent
extends
ServerEvent
{
public
ServerTickEvent
()
{
super
(
Type
.
GAME
);
}
}
src/main/java/emu/grasscutter/server/event/internal/ServerStartEvent.java
0 → 100644
View file @
627a2f1e
package
emu.grasscutter.server.event.internal
;
import
emu.grasscutter.server.event.ServerEvent
;
import
java.time.OffsetDateTime
;
public
final
class
ServerStartEvent
extends
ServerEvent
{
private
final
OffsetDateTime
startTime
;
public
ServerStartEvent
(
Type
type
,
OffsetDateTime
startTime
)
{
super
(
type
);
this
.
startTime
=
startTime
;
}
public
OffsetDateTime
getStartTime
()
{
return
this
.
startTime
;
}
}
src/main/java/emu/grasscutter/server/event/internal/ServerStopEvent.java
0 → 100644
View file @
627a2f1e
package
emu.grasscutter.server.event.internal
;
import
emu.grasscutter.server.event.ServerEvent
;
import
java.time.OffsetDateTime
;
public
final
class
ServerStopEvent
extends
ServerEvent
{
private
final
OffsetDateTime
stopTime
;
public
ServerStopEvent
(
Type
type
,
OffsetDateTime
stopTime
)
{
super
(
type
);
this
.
stopTime
=
stopTime
;
}
public
OffsetDateTime
getStopTime
()
{
return
this
.
stopTime
;
}
}
src/main/java/emu/grasscutter/server/game/GameServer.java
View file @
627a2f1e
package
emu.grasscutter.server.game
;
import
java.net.InetSocketAddress
;
import
java.time.OffsetDateTime
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
...
...
@@ -20,7 +21,10 @@ import emu.grasscutter.game.shop.ShopManager;
import
emu.grasscutter.net.packet.PacketHandler
;
import
emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail
;
import
emu.grasscutter.netty.MihoyoKcpServer
;
import
org.greenrobot.eventbus.EventBus
;
import
emu.grasscutter.server.event.ServerEvent
;
import
emu.grasscutter.server.event.game.ServerTickEvent
;
import
emu.grasscutter.server.event.internal.ServerStartEvent
;
import
emu.grasscutter.server.event.internal.ServerStopEvent
;
public
final
class
GameServer
extends
MihoyoKcpServer
{
private
final
InetSocketAddress
address
;
...
...
@@ -36,18 +40,10 @@ public final class GameServer extends MihoyoKcpServer {
private
final
MultiplayerManager
multiplayerManager
;
private
final
DungeonManager
dungeonManager
;
private
final
CommandMap
commandMap
;
public
EventBus
OnGameServerStartFinish
;
public
EventBus
OnGameServerTick
;
public
EventBus
OnGameServerStop
;
public
GameServer
(
InetSocketAddress
address
)
{
super
(
address
);
OnGameServerStartFinish
=
EventBus
.
builder
().
throwSubscriberException
(
true
).
logNoSubscriberMessages
(
false
).
build
();
OnGameServerTick
=
EventBus
.
builder
().
throwSubscriberException
(
true
).
logNoSubscriberMessages
(
false
).
build
();
OnGameServerStop
=
EventBus
.
builder
().
throwSubscriberException
(
true
).
logNoSubscriberMessages
(
false
).
build
();
this
.
setServerInitializer
(
new
GameServerInitializer
(
this
));
this
.
address
=
address
;
this
.
packetHandler
=
new
GameServerPacketHandler
(
PacketHandler
.
class
);
...
...
@@ -178,12 +174,8 @@ public final class GameServer extends MihoyoKcpServer {
world
.
onTick
();
}
for
(
GenshinPlayer
player
:
this
.
getPlayers
().
values
())
{
player
.
onTick
();
}
OnGameServerTick
.
post
(
new
GameServerTickEvent
());
ServerTickEvent
event
=
new
ServerTickEvent
();
event
.
call
();
}
public
void
registerWorld
(
World
world
)
{
...
...
@@ -198,12 +190,11 @@ public final class GameServer extends MihoyoKcpServer {
@Override
public
void
onStartFinish
()
{
Grasscutter
.
getLogger
().
info
(
"Game Server started on port "
+
address
.
getPort
());
OnGameServerStartFinish
.
post
(
new
GameServerStartFinishEvent
());
ServerStartEvent
event
=
new
ServerStartEvent
(
ServerEvent
.
Type
.
GAME
,
OffsetDateTime
.
now
());
event
.
call
();
}
public
void
onServerShutdown
()
{
OnGame
ServerStop
.
post
(
new
GameServerStopEvent
()
);
ServerStop
Event
event
=
new
ServerStopEvent
(
ServerEvent
.
Type
.
GAME
,
OffsetDateTime
.
now
());
event
.
call
(
);
// Kick and save all players
List
<
GenshinPlayer
>
list
=
new
ArrayList
<>(
this
.
getPlayers
().
size
());
...
...
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