2022-04-17 05:43:07 -07:00
package emu.grasscutter.server.game ;
2022-04-26 21:21:57 -07:00
import emu.grasscutter.GameConstants ;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.Grasscutter ;
2022-04-20 20:21:38 +08:00
import emu.grasscutter.command.CommandMap ;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.database.DatabaseHelper ;
2022-04-18 21:38:19 -07:00
import emu.grasscutter.game.Account ;
2022-04-27 17:42:02 +08:00
import emu.grasscutter.game.drop.DropManager ;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.game.dungeons.DungeonManager ;
import emu.grasscutter.game.gacha.GachaManager ;
import emu.grasscutter.game.managers.ChatManager ;
import emu.grasscutter.game.managers.InventoryManager ;
import emu.grasscutter.game.managers.MultiplayerManager ;
2022-04-26 21:24:25 -07:00
import emu.grasscutter.game.player.Player ;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.game.shop.ShopManager ;
2022-04-26 21:24:25 -07:00
import emu.grasscutter.game.world.World ;
2022-04-17 05:43:07 -07:00
import emu.grasscutter.net.packet.PacketHandler ;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail ;
2022-04-26 21:21:57 -07:00
import emu.grasscutter.netty.KcpServer ;
2022-04-26 02:07:00 -04:00
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 ;
2022-04-27 06:04:21 +08:00
import emu.grasscutter.task.TaskMap ;
2022-04-17 05:43:07 -07:00
2022-04-27 17:42:02 +08:00
import java.net.InetSocketAddress ;
import java.time.OffsetDateTime ;
import java.util.* ;
import java.util.concurrent.ConcurrentHashMap ;
2022-04-26 21:21:57 -07:00
public final class GameServer extends KcpServer {
2022-04-17 05:43:07 -07:00
private final InetSocketAddress address ;
private final GameServerPacketHandler packetHandler ;
2022-04-18 21:35:01 -07:00
2022-04-26 21:21:57 -07:00
private final Map < Integer , Player > players ;
2022-04-25 14:12:35 -07:00
private final Set < World > worlds ;
2022-04-17 05:43:07 -07:00
private final ChatManager chatManager ;
private final InventoryManager inventoryManager ;
private final GachaManager gachaManager ;
private final ShopManager shopManager ;
private final MultiplayerManager multiplayerManager ;
private final DungeonManager dungeonManager ;
2022-04-18 21:35:01 -07:00
private final CommandMap commandMap ;
2022-04-27 06:04:21 +08:00
private final TaskMap taskMap ;
2022-04-27 17:42:02 +08:00
private final DropManager dropManager ;
2022-04-17 05:43:07 -07:00
public GameServer ( InetSocketAddress address ) {
super ( address ) ;
2022-04-20 16:05:53 +08:00
2022-04-17 05:43:07 -07:00
this . setServerInitializer ( new GameServerInitializer ( this ) ) ;
this . address = address ;
this . packetHandler = new GameServerPacketHandler ( PacketHandler . class ) ;
this . players = new ConcurrentHashMap < > ( ) ;
2022-04-25 14:12:35 -07:00
this . worlds = Collections . synchronizedSet ( new HashSet < > ( ) ) ;
2022-04-17 05:43:07 -07:00
this . chatManager = new ChatManager ( this ) ;
this . inventoryManager = new InventoryManager ( this ) ;
this . gachaManager = new GachaManager ( this ) ;
this . shopManager = new ShopManager ( this ) ;
this . multiplayerManager = new MultiplayerManager ( this ) ;
this . dungeonManager = new DungeonManager ( this ) ;
2022-04-18 21:35:01 -07:00
this . commandMap = new CommandMap ( true ) ;
2022-04-27 06:04:21 +08:00
this . taskMap = new TaskMap ( true ) ;
2022-04-27 17:42:02 +08:00
this . dropManager = new DropManager ( this ) ;
2022-04-17 05:43:07 -07:00
2022-04-18 21:35:01 -07:00
// Schedule game loop.
Timer gameLoop = new Timer ( ) ;
gameLoop . scheduleAtFixedRate ( new TimerTask ( ) {
2022-04-17 05:43:07 -07:00
@Override
public void run ( ) {
try {
onTick ( ) ;
} catch ( Exception e ) {
2022-04-18 21:35:01 -07:00
Grasscutter . getLogger ( ) . error ( " An error occurred during game update. " , e ) ;
2022-04-17 05:43:07 -07:00
}
}
} , new Date ( ) , 1000L ) ;
2022-04-18 21:35:01 -07:00
// Hook into shutdown event.
2022-04-17 05:43:07 -07:00
Runtime . getRuntime ( ) . addShutdownHook ( new Thread ( this : : onServerShutdown ) ) ;
}
public GameServerPacketHandler getPacketHandler ( ) {
return packetHandler ;
}
2022-04-26 21:21:57 -07:00
public Map < Integer , Player > getPlayers ( ) {
2022-04-17 05:43:07 -07:00
return players ;
}
2022-04-25 14:12:35 -07:00
public Set < World > getWorlds ( ) {
return worlds ;
}
2022-04-17 05:43:07 -07:00
public ChatManager getChatManager ( ) {
return chatManager ;
}
public InventoryManager getInventoryManager ( ) {
return inventoryManager ;
}
public GachaManager getGachaManager ( ) {
return gachaManager ;
}
public ShopManager getShopManager ( ) {
return shopManager ;
}
public MultiplayerManager getMultiplayerManager ( ) {
return multiplayerManager ;
}
2022-04-27 17:42:02 +08:00
public DropManager getDropManager ( ) {
return dropManager ;
}
2022-04-17 05:43:07 -07:00
public DungeonManager getDungeonManager ( ) {
return dungeonManager ;
}
2022-04-18 21:35:01 -07:00
public CommandMap getCommandMap ( ) {
return this . commandMap ;
}
2022-04-27 06:04:21 +08:00
public TaskMap getTaskMap ( ) {
return this . taskMap ;
}
2022-04-18 21:35:01 -07:00
2022-04-26 21:21:57 -07:00
public void registerPlayer ( Player player ) {
2022-04-19 02:22:21 -07:00
getPlayers ( ) . put ( player . getUid ( ) , player ) ;
2022-04-17 05:43:07 -07:00
}
2022-04-26 21:21:57 -07:00
public Player getPlayerByUid ( int id ) {
2022-04-19 02:22:21 -07:00
return this . getPlayerByUid ( id , false ) ;
2022-04-17 05:43:07 -07:00
}
2022-04-26 21:21:57 -07:00
public Player getPlayerByUid ( int id , boolean allowOfflinePlayers ) {
2022-04-17 05:43:07 -07:00
// Console check
2022-04-26 21:21:57 -07:00
if ( id = = GameConstants . SERVER_CONSOLE_UID ) {
2022-04-17 05:43:07 -07:00
return null ;
}
// Get from online players
2022-04-26 21:21:57 -07:00
Player player = this . getPlayers ( ) . get ( id ) ;
2022-04-19 02:22:21 -07:00
if ( ! allowOfflinePlayers ) {
return player ;
}
2022-04-17 05:43:07 -07:00
// Check database if character isnt here
if ( player = = null ) {
player = DatabaseHelper . getPlayerById ( id ) ;
}
return player ;
}
2022-04-19 02:22:21 -07:00
public SocialDetail . Builder getSocialDetailByUid ( int id ) {
2022-04-17 05:43:07 -07:00
// Get from online players
2022-04-26 21:21:57 -07:00
Player player = this . getPlayerByUid ( id , true ) ;
2022-04-17 05:43:07 -07:00
if ( player = = null ) {
return null ;
}
return player . getSocialDetail ( ) ;
}
2022-04-18 21:38:19 -07:00
public Account getAccountByName ( String username ) {
2022-04-26 21:21:57 -07:00
Optional < Player > playerOpt = getPlayers ( ) . values ( ) . stream ( ) . filter ( player - > player . getAccount ( ) . getUsername ( ) . equals ( username ) ) . findFirst ( ) ;
2022-04-20 21:14:18 +08:00
if ( playerOpt . isPresent ( ) ) {
2022-04-18 21:38:19 -07:00
return playerOpt . get ( ) . getAccount ( ) ;
}
return DatabaseHelper . getAccountByName ( username ) ;
}
2022-04-17 05:43:07 -07:00
public void onTick ( ) throws Exception {
2022-04-25 14:12:35 -07:00
Iterator < World > it = this . getWorlds ( ) . iterator ( ) ;
while ( it . hasNext ( ) ) {
World world = it . next ( ) ;
if ( world . getPlayerCount ( ) = = 0 ) {
it . remove ( ) ;
}
world . onTick ( ) ;
}
2022-04-27 19:37:25 -07:00
for ( Player player : this . getPlayers ( ) . values ( ) ) {
player . onTick ( ) ;
}
2022-04-26 11:17:02 -04:00
2022-04-27 19:37:25 -07:00
ServerTickEvent event = new ServerTickEvent ( ) ; event . call ( ) ;
2022-04-17 05:43:07 -07:00
}
2022-04-25 14:12:35 -07:00
public void registerWorld ( World world ) {
this . getWorlds ( ) . add ( world ) ;
}
public void deregisterWorld ( World world ) {
// TODO Auto-generated method stub
}
2022-04-17 05:43:07 -07:00
@Override
public void onStartFinish ( ) {
2022-04-27 11:16:14 -07:00
Grasscutter . getLogger ( ) . info ( " Grasscutter is FREE software. If you have paid for this, you may have been scammed. Homepage: https://github.com/Grasscutters/Grasscutter " ) ;
2022-04-17 05:43:07 -07:00
Grasscutter . getLogger ( ) . info ( " Game Server started on port " + address . getPort ( ) ) ;
2022-04-26 02:07:00 -04:00
ServerStartEvent event = new ServerStartEvent ( ServerEvent . Type . GAME , OffsetDateTime . now ( ) ) ; event . call ( ) ;
2022-04-17 05:43:07 -07:00
}
public void onServerShutdown ( ) {
2022-04-26 02:07:00 -04:00
ServerStopEvent event = new ServerStopEvent ( ServerEvent . Type . GAME , OffsetDateTime . now ( ) ) ; event . call ( ) ;
2022-04-20 17:31:41 +08:00
2022-04-17 05:43:07 -07:00
// Kick and save all players
2022-04-26 21:21:57 -07:00
List < Player > list = new ArrayList < > ( this . getPlayers ( ) . size ( ) ) ;
2022-04-17 05:43:07 -07:00
list . addAll ( this . getPlayers ( ) . values ( ) ) ;
2022-04-26 21:21:57 -07:00
for ( Player player : list ) {
2022-04-17 05:43:07 -07:00
player . getSession ( ) . close ( ) ;
}
}
}