2016-08-22 14:18:37 -04:00
using FFXIVClassic.Common ;
using FFXIVClassic_World_Server.DataObjects ;
2016-12-17 09:37:18 -05:00
using FFXIVClassic_World_Server.DataObjects.Group ;
2016-12-18 09:50:23 -05:00
using FFXIVClassic_World_Server.Packets.Send.Subpackets ;
2016-12-17 09:37:18 -05:00
using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups ;
2016-12-03 14:00:24 -05:00
using FFXIVClassic_World_Server.Packets.WorldPackets.Send ;
2016-12-21 09:27:51 -05:00
using FFXIVClassic_World_Server.Packets.WorldPackets.Send.Group ;
2016-08-22 14:18:37 -04:00
using MySql.Data.MySqlClient ;
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Net ;
using System.Net.Sockets ;
using System.Text ;
using System.Threading.Tasks ;
namespace FFXIVClassic_World_Server
{
class WorldManager
{
private Server mServer ;
2016-08-29 08:17:14 -04:00
public Dictionary < string , ZoneServer > mZoneServerList ;
2016-09-26 16:20:01 -04:00
private Dictionary < uint , ZoneEntrance > zoneEntranceList ;
2016-08-22 14:18:37 -04:00
2016-12-17 09:37:18 -05:00
//World Scope Group Management
private Object mGroupLock = new object ( ) ;
private ulong mRunningGroupIndex = 1 ;
private Dictionary < ulong , Group > mCurrentWorldGroups = new Dictionary < ulong , Group > ( ) ;
private PartyManager mPartyManager ;
private RetainerGroupManager mRetainerGroupManager ;
private LinkshellManager mLinkshellManager ;
private RelationGroupManager mRelationGroupManager ;
2016-08-22 14:18:37 -04:00
public WorldManager ( Server server )
{
mServer = server ;
2016-12-17 09:37:18 -05:00
mPartyManager = new PartyManager ( this , mGroupLock , mCurrentWorldGroups ) ;
mLinkshellManager = new LinkshellManager ( this , mGroupLock , mCurrentWorldGroups ) ;
mRetainerGroupManager = new RetainerGroupManager ( this , mGroupLock , mCurrentWorldGroups ) ;
mRelationGroupManager = new RelationGroupManager ( this , mGroupLock , mCurrentWorldGroups ) ;
2016-08-22 14:18:37 -04:00
}
public void LoadZoneServerList ( )
{
mZoneServerList = new Dictionary < string , ZoneServer > ( ) ;
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
string query = @ "
SELECT
2016-12-03 12:19:59 -05:00
id ,
2016-08-22 14:18:37 -04:00
serverIp ,
serverPort
FROM server_zones
WHERE serverIp IS NOT NULL ";
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
2016-12-03 12:19:59 -05:00
uint id = reader . GetUInt32 ( 0 ) ;
string ip = reader . GetString ( 1 ) ;
int port = reader . GetInt32 ( 2 ) ;
2016-08-22 14:18:37 -04:00
string address = ip + ":" + port ;
if ( ! mZoneServerList . ContainsKey ( address ) )
{
2016-12-03 12:19:59 -05:00
ZoneServer zone = new ZoneServer ( ip , port , id ) ;
2016-08-22 14:18:37 -04:00
mZoneServerList . Add ( address , zone ) ;
}
2016-12-03 12:19:59 -05:00
else
mZoneServerList [ address ] . AddLoadedZone ( id ) ;
2016-08-22 14:18:37 -04:00
}
}
}
catch ( MySqlException e )
{ Console . WriteLine ( e ) ; }
finally
{
conn . Dispose ( ) ;
}
}
}
2016-09-26 16:20:01 -04:00
public void LoadZoneEntranceList ( )
{
zoneEntranceList = new Dictionary < uint , ZoneEntrance > ( ) ;
int count = 0 ;
using ( MySqlConnection conn = new MySqlConnection ( String . Format ( "Server={0}; Port={1}; Database={2}; UID={3}; Password={4}" , ConfigConstants . DATABASE_HOST , ConfigConstants . DATABASE_PORT , ConfigConstants . DATABASE_NAME , ConfigConstants . DATABASE_USERNAME , ConfigConstants . DATABASE_PASSWORD ) ) )
{
try
{
conn . Open ( ) ;
string query = @ "
SELECT
id ,
zoneId ,
spawnType ,
spawnX ,
spawnY ,
spawnZ ,
spawnRotation ,
privateAreaName
FROM server_zones_spawnlocations ";
MySqlCommand cmd = new MySqlCommand ( query , conn ) ;
using ( MySqlDataReader reader = cmd . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
uint id = reader . GetUInt32 ( 0 ) ;
string privArea = null ;
if ( ! reader . IsDBNull ( 7 ) )
privArea = reader . GetString ( 7 ) ;
ZoneEntrance entance = new ZoneEntrance ( reader . GetUInt32 ( 1 ) , privArea , reader . GetByte ( 2 ) , reader . GetFloat ( 3 ) , reader . GetFloat ( 4 ) , reader . GetFloat ( 5 ) , reader . GetFloat ( 6 ) ) ;
zoneEntranceList [ id ] = entance ;
count + + ;
}
}
}
catch ( MySqlException e )
{ Console . WriteLine ( e ) ; }
finally
{
conn . Dispose ( ) ;
}
}
Program . Log . Info ( String . Format ( "Loaded {0} zone spawn locations." , count ) ) ;
}
2016-08-22 14:18:37 -04:00
public void ConnectToZoneServers ( )
{
Program . Log . Info ( "--------------------------" ) ;
Program . Log . Info ( "Connecting to zone servers" ) ;
Program . Log . Info ( "--------------------------" ) ;
foreach ( ZoneServer zs in mZoneServerList . Values )
{
zs . Connect ( ) ;
}
}
2016-12-03 12:19:59 -05:00
public ZoneServer GetZoneServer ( uint zoneId )
{
foreach ( ZoneServer zs in mZoneServerList . Values )
{
if ( zs . ownedZoneIds . Contains ( zoneId ) )
return zs ;
}
return null ;
}
2016-08-22 14:18:37 -04:00
//Moves the actor to the new zone if exists. No packets are sent nor position changed.
public void DoSeamlessZoneServerChange ( Session session , uint destinationZoneId )
{
}
//Moves actor to new zone, and sends packets to spawn at the given zone entrance
public void DoZoneServerChange ( Session session , uint zoneEntrance )
{
2016-09-26 16:20:01 -04:00
if ( ! zoneEntranceList . ContainsKey ( zoneEntrance ) )
{
Program . Log . Error ( "Given zone entrance was not found: " + zoneEntrance ) ;
return ;
}
ZoneEntrance ze = zoneEntranceList [ zoneEntrance ] ;
DoZoneServerChange ( session , ze . zoneId , ze . privateAreaName , ze . spawnType , ze . spawnX , ze . spawnY , ze . spawnZ , ze . spawnRotation ) ;
2016-08-22 14:18:37 -04:00
}
//Moves actor to new zone, and sends packets to spawn at the given coords.
public void DoZoneServerChange ( Session session , uint destinationZoneId , string destinationPrivateArea , byte spawnType , float spawnX , float spawnY , float spawnZ , float spawnRotation )
{
2016-12-03 14:00:24 -05:00
ZoneServer zs = GetZoneServer ( destinationZoneId ) ;
2016-12-11 23:31:13 -05:00
if ( zs = = null )
return ;
2016-12-13 15:02:28 -05:00
session . currentZoneId = destinationZoneId ;
//Intrazone change, just update the id
if ( zs . Equals ( session . routing1 ) )
return ;
2016-12-03 14:00:24 -05:00
if ( zs . isConnected )
session . routing1 . SendSessionEnd ( session , destinationZoneId , destinationPrivateArea , spawnType , spawnX , spawnY , spawnZ , spawnRotation ) ;
else if ( zs . Connect ( ) )
session . routing1 . SendSessionEnd ( session , destinationZoneId , destinationPrivateArea , spawnType , spawnX , spawnY , spawnZ , spawnRotation ) ;
else
session . routing1 . SendPacket ( ErrorPacket . BuildPacket ( session , 1 ) ) ;
2016-08-22 14:18:37 -04:00
}
//Login Zone In
public void DoLogin ( Session session )
2016-12-18 09:50:23 -05:00
{
SendMotD ( session ) ;
//Send party, retainer, ls groups
2016-12-21 08:27:23 -05:00
Party pt = mPartyManager . GetParty ( session . sessionId ) ;
2016-12-21 18:02:50 -05:00
if ( session . sessionId = = 0x6c )
{
mPartyManager . AddToParty ( pt . groupIndex , 156 ) ;
}
2016-12-21 08:27:23 -05:00
pt . SendGroupPackets ( session ) ;
2016-12-21 09:27:51 -05:00
SendPartySync ( pt ) ;
2016-12-18 09:50:23 -05:00
mRetainerGroupManager . GetRetainerGroup ( session . sessionId ) . SendGroupPackets ( session ) ;
List < Linkshell > linkshells = mLinkshellManager . GetPlayerLinkshellMembership ( session . sessionId ) ;
foreach ( Linkshell ls in linkshells )
ls . SendGroupPackets ( session ) ;
2016-12-18 10:07:06 -05:00
2016-12-21 08:27:23 -05:00
mRelationGroupManager . CreateRelationGroup ( 157 , session . sessionId , 40001 ) . SendGroupPackets ( session ) ;
2016-12-18 09:50:23 -05:00
}
private void SendMotD ( Session session )
{
session . clientConnection . QueuePacket ( SendMessagePacket . BuildPacket ( session . sessionId , session . sessionId , SendMessagePacket . MESSAGE_TYPE_GENERAL_INFO , "" , "-------- Login Message --------" ) , true , false ) ;
2016-12-21 09:27:51 -05:00
session . clientConnection . QueuePacket ( SendMessagePacket . BuildPacket ( session . sessionId , session . sessionId , SendMessagePacket . MESSAGE_TYPE_GENERAL_INFO , "" , String . Format ( "Welcome to {0}!" , ConfigConstants . PREF_SERVERNAME ) ) , true , false ) ;
2016-12-18 09:50:23 -05:00
session . clientConnection . QueuePacket ( SendMessagePacket . BuildPacket ( session . sessionId , session . sessionId , SendMessagePacket . MESSAGE_TYPE_GENERAL_INFO , "" , "Welcome to Eorzea!" ) , true , false ) ;
session . clientConnection . QueuePacket ( SendMessagePacket . BuildPacket ( session . sessionId , session . sessionId , SendMessagePacket . MESSAGE_TYPE_GENERAL_INFO , "" , "Here is a test Message of the Day from the World Server!" ) , true , false ) ;
2016-08-22 14:18:37 -04:00
}
2016-12-21 09:27:51 -05:00
public void SendPartySync ( Party party )
2016-12-21 18:02:50 -05:00
{
List < ZoneServer > alreadySent = new List < ZoneServer > ( ) ;
2016-12-21 09:27:51 -05:00
foreach ( uint member in party . members )
{
Session session = Server . GetServer ( ) . GetSession ( member ) ;
if ( session = = null )
continue ;
2016-12-21 18:02:50 -05:00
if ( alreadySent . Contains ( session . routing1 ) )
continue ;
alreadySent . Add ( session . routing1 ) ;
2016-12-21 09:27:51 -05:00
SubPacket syncPacket = PartySyncPacket . BuildPacket ( session , party ) ;
session . routing1 . SendPacket ( syncPacket ) ;
}
}
2016-08-22 14:18:37 -04:00
public class ZoneEntrance
{
public uint zoneId ;
public string privateAreaName ;
public byte spawnType ;
public float spawnX ;
public float spawnY ;
public float spawnZ ;
public float spawnRotation ;
public ZoneEntrance ( uint zoneId , string privateAreaName , byte spawnType , float x , float y , float z , float rot )
{
this . zoneId = zoneId ;
this . privateAreaName = privateAreaName ;
this . spawnType = spawnType ;
this . spawnX = x ;
this . spawnY = y ;
this . spawnZ = z ;
this . spawnRotation = rot ;
}
2016-12-17 09:37:18 -05:00
}
public void SendGroupData ( Session session , ulong groupId )
{
if ( mCurrentWorldGroups . ContainsKey ( groupId ) )
{
Group group = mCurrentWorldGroups [ groupId ] ;
group . SendGroupPackets ( session ) ;
}
}
public void SendGroupDataToAllMembers ( ulong groupId )
{
if ( mCurrentWorldGroups . ContainsKey ( groupId ) )
{
Group group = mCurrentWorldGroups [ groupId ] ;
foreach ( GroupMember member in group . BuildMemberList ( ) )
group . SendGroupPackets ( mServer . GetSession ( member . actorId ) ) ;
}
2016-12-21 08:27:23 -05:00
}
2016-12-17 09:37:18 -05:00
public void IncrementGroupIndex ( )
{
mRunningGroupIndex + + ;
}
public ulong GetGroupIndex ( )
{
2016-12-18 09:50:23 -05:00
return mRunningGroupIndex | 0x8000000000000000 ;
2016-12-17 09:37:18 -05:00
}
public bool SendGroupInit ( Session session , ulong groupId )
{
if ( mCurrentWorldGroups . ContainsKey ( groupId ) )
{
mCurrentWorldGroups [ groupId ] . SendInitWorkValues ( session ) ;
return true ;
}
return false ;
}
2016-08-22 14:18:37 -04:00
2016-12-17 09:37:18 -05:00
public PartyManager GetPartyManager ( )
{
return mPartyManager ;
}
public RetainerGroupManager GetRetainerManager ( )
{
return mRetainerGroupManager ;
}
public LinkshellManager GetLinkshellManager ( )
{
return mLinkshellManager ;
}
2016-08-22 14:18:37 -04:00
}
}