2024-09-10 00:31:40 +08:00
using System ;
using System.Collections.Generic ;
using System.IO ;
2024-12-08 10:56:05 +08:00
using Newtonsoft.Json ;
2024-12-10 13:33:57 +08:00
using PSO2SERVER.Json ;
2024-09-10 01:13:20 +08:00
using PSO2SERVER.Models ;
using PSO2SERVER.Object ;
2024-11-27 18:05:53 +08:00
using PSO2SERVER.Protocol ;
using PSO2SERVER.Protocol.Packets ;
2024-12-07 23:01:27 +08:00
using static PSO2SERVER . Zone . Map ;
2024-09-10 00:31:40 +08:00
2024-09-10 01:13:20 +08:00
namespace PSO2SERVER.Zone
2024-09-10 00:31:40 +08:00
{
2024-12-03 18:17:43 +08:00
public struct PSOLocation
{
public float RotX , RotY , RotZ , RotW , PosX , PosY , PosZ ; // RotX, RotY, RotZ, and RotW make up a Quaternion
public PSOLocation ( float RotX , float RotY , float RotZ , float RotW , float PosX , float PosY , float PosZ )
{
this . RotX = RotX ;
this . RotY = RotY ;
this . RotZ = RotZ ;
this . RotW = RotW ;
this . PosX = PosX ;
this . PosY = PosY ;
this . PosZ = PosZ ;
}
public override string ToString ( )
{
return String . Format ( "Rot: ({0}, {1}, {2}, {3}) Loc: ({4}, {5}, {6})"
, RotX , RotY , RotZ , RotW , PosX , PosY , PosZ ) ;
}
}
2024-09-10 00:31:40 +08:00
public class Map
{
public string Name { get ; set ; }
public MapType Type { get ; set ; }
public PSOObject [ ] Objects { get ; set ; }
public PSONPC [ ] NPCs { get ; set ; }
public ObjectHeader MapHeader { get ; set ; }
public int MapID { get ; set ; }
public int VariantID { get ; set ; }
public MapFlags Flags { get ; set ; }
public List < Client > Clients { get ; set ; }
public GenParam GenerationArgs { get ; set ; }
public string InstanceName { get ; set ; }
2024-12-10 13:33:57 +08:00
public List < MapData > mapDatas { get ; set ; }
2024-09-10 00:31:40 +08:00
public Map ( string name , int id , int variant , MapType type , MapFlags flags )
{
Name = name ;
MapID = id ;
VariantID = variant ;
Type = type ;
Flags = flags ;
Clients = new List < Client > ( ) ;
GenerationArgs = new GenParam ( ) ;
Objects = ObjectManager . Instance . GetObjectsForZone ( Name ) ;
2024-09-18 00:55:35 +08:00
NPCs = ObjectManager . Instance . GetNpcSForZone ( Name ) ;
2024-09-10 00:31:40 +08:00
}
2024-12-03 18:17:43 +08:00
2024-09-10 00:31:40 +08:00
public PSOLocation GetDefaultLocation ( )
{
PSOLocation location ;
switch ( Type )
{
case MapType . Lobby :
location = new PSOLocation ( 0f , 1f , 0f , 0f , - 0.417969f , 0f , 137.375f ) ;
break ;
case MapType . Casino :
2024-09-13 10:27:47 +08:00
location = new PSOLocation ( 0f , 1f , 0f , 0f , 2f , 6f , 102f ) ;
2024-09-10 00:31:40 +08:00
break ;
default :
location = new PSOLocation ( 0f , 1f , 0f , 0f , 0f , 0f , 0f ) ;
break ;
}
return location ;
}
/// <summary>
/// Spawns a client into a map at a given location
/// </summary>
/// <param name="c">Client to spawn into map</param>
/// <param name="location">Location to spawn client at</param>
/// <param name="questOveride">If this also sets the quest data, specify the quest name here to load the spawn from the bin rather then generate it.</param>
public void SpawnClient ( Client c , PSOLocation location , string questOveride = "" )
{
if ( Clients . Contains ( c ) )
{
return ;
}
// Set area
if ( questOveride ! = "" ) // TODO: This is a temporary hack, fix me!!
{
2024-09-18 00:55:35 +08:00
//var setAreaPacket = File.ReadAllBytes("Resources\\quests\\" + questOveride + ".bin");
//c.SendPacket(0x03, 0x24, 0x04, setAreaPacket);
c . SendPacket ( new LoadingLevelPacket ( questOveride ) ) ;
2024-09-10 00:31:40 +08:00
}
else
{
2024-12-10 13:33:57 +08:00
//var _map = new Map("", MapID, VariantID, Type, Flags);
//_map.GenerationArgs.seed = GenerationArgs.seed;
//_map.GenerationArgs.xsize = GenerationArgs.xsize;
//_map.GenerationArgs.ysize = GenerationArgs.ysize;
ZoneData zoneData = new ZoneData ( ) ;
2024-09-18 00:55:35 +08:00
2024-12-10 13:33:57 +08:00
c . SendPacket ( new MapTransferPacket ( zoneData , ( uint ) MapID , ( uint ) c . _account . AccountId ) ) ;
2024-09-10 00:31:40 +08:00
}
2024-12-10 23:08:39 +08:00
if ( c . CurrentMap ! = null )
2024-09-10 00:31:40 +08:00
{
2024-12-10 23:08:39 +08:00
c . CurrentMap . RemoveClient ( c ) ;
2024-09-10 00:31:40 +08:00
}
2024-11-29 10:01:28 +08:00
// 设置客户端的账户ID
c . SendPacket ( new SetAccountIDPacket ( c . _account . AccountId ) ) ;
2024-09-10 00:31:40 +08:00
2024-12-11 19:54:48 +08:00
Logger . WriteObj ( c . Character ) ;
2024-09-10 00:31:40 +08:00
// Spawn Character
2024-12-11 19:54:48 +08:00
c . SendPacket ( new CharacterSpawnPacket ( c , location , true , true ) ) ;
2024-09-10 00:31:40 +08:00
c . CurrentLocation = location ;
2024-12-10 23:08:39 +08:00
c . CurrentMap = this ;
2024-09-10 00:31:40 +08:00
// Objects
foreach ( PSOObject obj in Objects )
{
2024-09-18 00:55:35 +08:00
c . SendPacket ( new ObjectSpawnPacket ( obj ) ) ;
2024-09-10 00:31:40 +08:00
}
// NPCs
foreach ( PSONPC npc in NPCs )
{
2024-09-18 00:55:35 +08:00
c . SendPacket ( new NPCSpawnPacket ( npc ) ) ;
2024-09-10 00:31:40 +08:00
}
// Spawn for others, Spawn others for me
2024-12-11 19:54:48 +08:00
CharacterSpawnPacket spawnMe = new CharacterSpawnPacket ( c , location , false , true ) ;
2024-09-10 00:31:40 +08:00
foreach ( Client other in Clients )
{
other . SendPacket ( spawnMe ) ;
2024-12-11 19:54:48 +08:00
c . SendPacket ( new CharacterSpawnPacket ( other , other . CurrentLocation , false , true ) ) ;
2024-09-10 00:31:40 +08:00
}
Clients . Add ( c ) ;
2024-09-20 21:58:37 +08:00
Logger . Write ( "[MAP] {0} 已生成至 {1}." , c . _account . Username , Name ) ;
2024-09-10 00:31:40 +08:00
if ( InstanceName ! = null & & ZoneManager . Instance . playerCounter . ContainsKey ( InstanceName ) )
{
ZoneManager . Instance . playerCounter [ InstanceName ] + = 1 ;
}
}
public void RemoveClient ( Client c )
{
if ( ! Clients . Contains ( c ) )
return ;
2024-12-10 23:08:39 +08:00
c . CurrentMap = null ;
2024-09-10 00:31:40 +08:00
Clients . Remove ( c ) ;
foreach ( Client other in Clients )
{
2024-09-20 21:58:37 +08:00
other . SendPacket ( new DespawnPlayerPacket ( other . _account . AccountId , c . _account . AccountId ) ) ;
2024-09-10 00:31:40 +08:00
}
if ( InstanceName ! = null & & ZoneManager . Instance . playerCounter . ContainsKey ( InstanceName ) )
{
ZoneManager . Instance . playerCounter [ InstanceName ] - = 1 ;
if ( ZoneManager . Instance . playerCounter [ InstanceName ] < = 0 )
{
ZoneManager . Instance . playerCounter . Remove ( InstanceName ) ;
ZoneManager . Instance . instances . Remove ( InstanceName ) ;
}
}
}
public class GenParam
{
2024-12-10 23:22:43 +08:00
public uint seed { get ; set ; } = 0 ;
public uint xsize { get ; set ; } = 0 ;
public uint ysize { get ; set ; } = 0 ;
2024-09-10 00:31:40 +08:00
public GenParam ( )
{
}
public GenParam ( uint seed , uint x , uint y )
{
this . seed = seed ;
this . xsize = x ;
this . ysize = y ;
}
}
2024-12-10 01:23:49 +08:00
public enum MapType : int
{
Lobby = 4 ,
Casino = 11 ,
MyRoom = 8 ,
TeamRoom = 7 ,
ChallengeLobby = 5 ,
Campship = 1 ,
Quest = 0 ,
Other = ~ 0
} ;
[Flags]
public enum MapFlags : uint
{
None = 0 ,
MultiPartyArea = 1 ,
Unknown1 = 2 ,
EnableMap = 4
}
2024-09-10 00:31:40 +08:00
}
2024-12-07 23:01:27 +08:00
2024-09-10 00:31:40 +08:00
}