1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-23 05:07:47 +00:00

Initial Commit.

This commit is contained in:
Filip Maj 2015-09-25 18:52:25 -04:00
commit 46c4c26d01
82 changed files with 70188 additions and 0 deletions

View file

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FFXIVClassic Map Server", "FFXIVClassic Map Server\FFXIVClassic Map Server.csproj", "{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data></configuration>

View file

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using FFXIVClassic_Lobby_Server.packets;
using System.Diagnostics;
using FFXIVClassic_Lobby_Server.common;
using System.Collections.Concurrent;
using System.IO;
using Cyotek.Collections.Generic;
using System.Net;
namespace FFXIVClassic_Lobby_Server
{
class ClientConnection
{
//Connection stuff
public Blowfish blowfish;
public Socket socket;
public byte[] buffer = new byte[0xffff];
public CircularBuffer<byte> incomingStream = new CircularBuffer<byte>(1024);
public BlockingCollection<BasePacket> sendPacketQueue = new BlockingCollection<BasePacket>(100);
//Instance Stuff
public uint owner = 0;
public uint connType = 0;
public void processIncoming(int bytesIn)
{
if (bytesIn == 0)
return;
incomingStream.Put(buffer, 0, bytesIn);
}
public void queuePacket(BasePacket packet)
{
sendPacketQueue.Add(packet);
}
public void flushQueuedSendPackets()
{
if (!socket.Connected)
return;
while (sendPacketQueue.Count > 0)
{
BasePacket packet = sendPacketQueue.Take();
byte[] packetBytes = packet.getPacketBytes();
byte[] buffer = new byte[0xffff];
Array.Copy(packetBytes, buffer, packetBytes.Length);
try
{
socket.Send(packetBytes);
}
catch (Exception e)
{ Log.error(String.Format("Weird case, socket was d/ced: {0}", e)); }
}
}
public String getAddress()
{
return String.Format("{0}:{1}", (socket.RemoteEndPoint as IPEndPoint).Address, (socket.RemoteEndPoint as IPEndPoint).Port);
}
public void disconnect()
{
socket.Disconnect(false);
}
}
}

View file

@ -0,0 +1,55 @@
using FFXIVClassic_Lobby_Server.common;
using STA.Settings;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Lobby_Server
{
class ConfigConstants
{
public static String OPTIONS_BINDIP;
public static bool OPTIONS_TIMESTAMP = false;
public static uint DATABASE_WORLDID;
public static String DATABASE_HOST;
public static String DATABASE_PORT;
public static String DATABASE_NAME;
public static String DATABASE_USERNAME;
public static String DATABASE_PASSWORD;
public static bool load()
{
Console.Write("Loading config.ini file... ");
if (!File.Exists("./config.ini"))
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[FILE NOT FOUND]");
Console.ForegroundColor = ConsoleColor.Gray;
return false;
}
INIFile configIni = new INIFile("./config.ini");
ConfigConstants.OPTIONS_BINDIP = configIni.GetValue("General", "server_ip", "127.0.0.1");
ConfigConstants.OPTIONS_TIMESTAMP = configIni.GetValue("General", "showtimestamp", "true").ToLower().Equals("true");
ConfigConstants.DATABASE_WORLDID = configIni.GetValue("Database", "worldid", (uint)0);
ConfigConstants.DATABASE_HOST = configIni.GetValue("Database", "host", "");
ConfigConstants.DATABASE_PORT = configIni.GetValue("Database", "port", "");
ConfigConstants.DATABASE_NAME = configIni.GetValue("Database", "database", "");
ConfigConstants.DATABASE_USERNAME = configIni.GetValue("Database", "username", "");
ConfigConstants.DATABASE_PASSWORD = configIni.GetValue("Database", "password", "");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[OK]");
Console.ForegroundColor = ConsoleColor.Gray;
return true;
}
}
}

View file

@ -0,0 +1,90 @@
using FFXIVClassic_Lobby_Server.dataobjects;
using MySql.Data.MySqlClient;
using Dapper;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Lobby_Server.common;
namespace FFXIVClassic_Lobby_Server
{
class Database
{
public static uint getUserIdFromSession(String sessionId)
{
uint id = 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();
MySqlCommand cmd = new MySqlCommand("SELECT * FROM sessions WHERE id = @sessionId AND expiration > NOW()", conn);
cmd.Parameters.AddWithValue("@sessionId", sessionId);
using (MySqlDataReader Reader = cmd.ExecuteReader())
{
while (Reader.Read())
{
id = Reader.GetUInt32("userId");
}
}
}
catch (MySqlException e)
{ Console.WriteLine(e); }
finally
{
conn.Dispose();
}
}
return id;
}
public static World getServer(uint serverId)
{
using (var 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)))
{
World world = null;
try
{
conn.Open();
world = conn.Query<World>("SELECT * FROM servers WHERE id=@ServerId", new {ServerId = serverId}).SingleOrDefault();
}
catch (MySqlException e)
{
}
finally
{
conn.Dispose();
}
return world;
}
}
public static Character getCharacter(uint userId, uint charId)
{
using (var 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)))
{
Character chara = null;
try
{
conn.Open();
chara = conn.Query<Character>("SELECT * FROM characters WHERE id=@CharaId and userId=@UserId", new { UserId = userId, CharaId = charId }).SingleOrDefault();
}
catch (MySqlException e)
{
}
finally
{
conn.Dispose();
}
return chara;
}
}
}
}

View file

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E8FA2784-D4B9-4711-8CC6-712A4B1CD54F}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FFXIVClassic_Map_Server</RootNamespace>
<AssemblyName>FFXIVClassic Map Server</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Cyotek.Collections.Generic.CircularBuffer">
<HintPath>..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll</HintPath>
</Reference>
<Reference Include="Dapper">
<HintPath>..\packages\Dapper.1.42\lib\net45\Dapper.dll</HintPath>
</Reference>
<Reference Include="MySql.Data">
<HintPath>..\packages\MySql.Data.6.9.7\lib\net45\MySql.Data.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ClientConnection.cs" />
<Compile Include="common\Bitfield.cs" />
<Compile Include="common\Blowfish.cs" />
<Compile Include="common\Log.cs" />
<Compile Include="common\STA_INIFile.cs" />
<Compile Include="common\Utils.cs" />
<Compile Include="ConfigConstants.cs" />
<Compile Include="Database.cs" />
<Compile Include="dataobjects\Actor.cs" />
<Compile Include="dataobjects\Character.cs" />
<Compile Include="dataobjects\CharaInfo.cs" />
<Compile Include="dataobjects\Player.cs" />
<Compile Include="dataobjects\World.cs" />
<Compile Include="PacketProcessor.cs" />
<Compile Include="packets\BasePacket.cs" />
<Compile Include="packets\receive\HandshakePacket.cs" />
<Compile Include="packets\send\login\0x2Packet.cs" />
<Compile Include="packets\send\Actor\AddActorPacket.cs" />
<Compile Include="packets\send\Actor\MoveActorToPositionPacket.cs" />
<Compile Include="packets\send\Actor\RemoveActorPacketPacket.cs" />
<Compile Include="packets\send\Actor\SetActorAppearancePacket.cs" />
<Compile Include="packets\send\Actor\SetActorPositionPacket.cs" />
<Compile Include="packets\send\login\InitPacket.cs" />
<Compile Include="packets\send\PongPacket.cs" />
<Compile Include="packets\send\SetMapPacket.cs" />
<Compile Include="packets\send\SetMusicPacket.cs" />
<Compile Include="packets\send\SetWeatherPacket.cs" />
<Compile Include="packets\SubPacket.cs" />
<Compile Include="packets\receive\PingPacket.cs" />
<Compile Include="packets\receive\UpdatePlayerPositionPacket.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Server.cs" />
<Compile Include="UnknownLoginPacket.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,226 @@
using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Lobby_Server.packets;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Map_Server.dataobjects;
using FFXIVClassic_Map_Server.packets;
using FFXIVClassic_Map_Server.packets.receive;
using FFXIVClassic_Map_Server.packets.send;
using FFXIVClassic_Map_Server.packets.send.login;
namespace FFXIVClassic_Lobby_Server
{
class PacketProcessor
{
Dictionary<uint, Player> mPlayers = new Dictionary<uint, Player>();
List<ClientConnection> mConnections;
Boolean isAlive = true;
public PacketProcessor(List<ClientConnection> connectionList)
{
mConnections = connectionList;
}
public void update()
{
Console.WriteLine("Packet processing thread has started");
while (isAlive)
{
lock (mConnections)
{
foreach (ClientConnection conn in mConnections)
{
//Receive conn1 packets
while (true)
{
if (conn == null || conn.incomingStream.Size < BasePacket.BASEPACKET_SIZE)
break;
try {
if (conn.incomingStream.Size < BasePacket.BASEPACKET_SIZE)
break;
BasePacketHeader header = BasePacket.getHeader(conn.incomingStream.Peek(BasePacket.BASEPACKET_SIZE));
if (conn.incomingStream.Size < header.packetSize)
break;
BasePacket packet = new BasePacket(conn.incomingStream.Get(header.packetSize));
processPacket(conn, packet);
}
catch(OverflowException)
{ break; }
}
//Send packets
if (conn != null && conn.sendPacketQueue.Count != 0)
conn.flushQueuedSendPackets();
}
}
//Don't waste CPU if isn't needed
if (mConnections.Count == 0)
Thread.Sleep(2000);
else
Thread.Sleep(100);
}
}
private void processPacket(ClientConnection client, BasePacket packet)
{
Player player = null;
if (client.owner != 0 && mPlayers.ContainsKey(client.owner))
player = mPlayers[client.owner];
if (packet.header.isEncrypted == 0x01)
BasePacket.decryptPacket(client.blowfish, ref packet);
List<SubPacket> subPackets = packet.getSubpackets();
foreach (SubPacket subpacket in subPackets)
{
//Console.WriteLine(client.getAddress());
switch (subpacket.header.opcode)
{
//Initial
case 0x0000:
BasePacket init = InitPacket.buildPacket(0, Utils.UnixTimeStampUTC());
BasePacket reply2 = new BasePacket("./packets/login2.bin");
//Already Handshaked
if (client.owner != 0)
{
using (MemoryStream mem = new MemoryStream(reply2.data))
{
using (BinaryWriter binReader = new BinaryWriter(mem))
{
binReader.BaseStream.Seek(0x10, SeekOrigin.Begin);
binReader.Write(player.actorID);
}
}
client.sendPacketQueue.Add(init);
client.sendPacketQueue.Add(reply2);
break;
}
uint actorID = 0;
using (MemoryStream mem = new MemoryStream(packet.data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
byte[] readIn = new byte[12];
binReader.BaseStream.Seek(0x14, SeekOrigin.Begin);
binReader.Read(readIn, 0, 12);
actorID = UInt32.Parse(Encoding.ASCII.GetString(readIn));
}
catch (Exception)
{}
}
}
if (actorID == 0)
break;
using (MemoryStream mem = new MemoryStream(reply2.data))
{
using (BinaryWriter binReader = new BinaryWriter(mem))
{
binReader.BaseStream.Seek(0x10, SeekOrigin.Begin);
binReader.Write(actorID);
}
}
Log.debug(String.Format("Got actorID {0} for conn {1}.", actorID, client.getAddress()));
if (player == null)
{
player = new Player(actorID);
mPlayers[actorID] = player;
client.owner = actorID;
client.connType = 0;
player.setConnection1(client);
}
else
{
client.owner = actorID;
client.connType = 1;
player.setConnection2(client);
}
//Get Character info
//Create player actor
client.sendPacketQueue.Add(init);
client.sendPacketQueue.Add(reply2);
break;
//Ping
case 0x0001:
subpacket.debugPrintSubPacket();
PingPacket pingPacket = new PingPacket(subpacket.data);
client.queuePacket(BasePacket.createPacket(PongPacket.buildPacket(player.actorID, pingPacket.time), true, false));
break;
//Unknown
case 0x0002:
subpacket.debugPrintSubPacket();
BasePacket setMapPacket = BasePacket.createPacket(SetMapPacket.buildPacket(player.actorID, 0xD1), true, false);
BasePacket setPlayerActorPacket = BasePacket.createPacket(_0x2Packet.buildPacket(player.actorID), true, false);
BasePacket reply5 = new BasePacket("./packets/asd/login5.bin");
BasePacket reply6 = new BasePacket("./packets/asd/login6_data.bin");
BasePacket reply7 = new BasePacket("./packets/asd/login7_data.bin");
BasePacket reply8 = new BasePacket("./packets/asd/login8_data.bin");
BasePacket reply9 = new BasePacket("./packets/asd/login9_zonesetup.bin");
BasePacket reply10 = new BasePacket("./packets/asd/login10.bin");
client.sendPacketQueue.Add(setMapPacket);
client.sendPacketQueue.Add(setPlayerActorPacket);
client.sendPacketQueue.Add(reply5);
client.sendPacketQueue.Add(reply6);
client.sendPacketQueue.Add(reply7);
client.sendPacketQueue.Add(reply8);
client.sendPacketQueue.Add(reply9);
//client.sendPacketQueue.Add(reply10);
break;
//Chat Received
case 0x0003:
subpacket.debugPrintSubPacket();
break;
//Update Position
case 0x00CA:
UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data);
player.updatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState);
break;
case 0x00CD:
subpacket.debugPrintSubPacket();
//ProcessSetSelection(subPacket);
break;
case 0x012D:
subpacket.debugPrintSubPacket();
//ProcessScriptCommand(subPacket);
break;
case 0x012E:
subpacket.debugPrintSubPacket();
//ProcessScriptResult(subPacket);
break;
default:
Log.debug(String.Format("Unknown command 0x{0:X} received.", subpacket.header.opcode));
subpacket.debugPrintSubPacket();
break;
}
}
}
}
}

View file

@ -0,0 +1,81 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Diagnostics;
using System.Threading;
using FFXIVClassic_Lobby_Server.common;
using System.Runtime.InteropServices;
using MySql.Data.MySqlClient;
using System.Reflection;
using FFXIVClassic_Lobby_Server.dataobjects;
namespace FFXIVClassic_Lobby_Server
{
class Program
{
static void Main(string[] args)
{
#if DEBUG
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(myWriter);
#endif
bool startServer = true;
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("---------FFXIV 1.0 Map Server---------");
Console.ForegroundColor = ConsoleColor.Gray;
Assembly assem = Assembly.GetExecutingAssembly();
Version vers = assem.GetName().Version;
Console.WriteLine("Version: " + vers.ToString());
//Load Config
if (!ConfigConstants.load())
startServer = false;
//Test DB Connection
Console.Write("Testing DB connection... ");
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();
conn.Close();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[OK]");
Console.ForegroundColor = ConsoleColor.Gray;
}
catch (MySqlException e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[FAILED]");
Console.ForegroundColor = ConsoleColor.Gray;
startServer = false;
}
}
//Check World ID
World thisWorld = Database.getServer(ConfigConstants.DATABASE_WORLDID);
if (thisWorld != null)
Console.WriteLine("Successfully pulled world info from DB. Server name is {0}.", thisWorld.name);
else
Console.WriteLine("World info could not be retrieved from the DB. Welcome and MOTD will not be displayed.");
//Start server if A-OK
if (startServer)
{
Server server = new Server();
server.startServer();
while (true) Thread.Sleep(10000);
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("FFXIVClassic Map Server")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FFXIVClassic Map Server")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("01e76cc8-4442-4a1f-aaa4-fe418e18e34b")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,183 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;
using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Map_Server.dataobjects;
namespace FFXIVClassic_Lobby_Server
{
class Server
{
public const int FFXIV_MAP_PORT = 54992;
public const int BUFFER_SIZE = 0x400;
public const int BACKLOG = 100;
private Socket mServerSocket;
private List<Player> mConnectedPlayerList = new List<Player>();
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
private PacketProcessor mProcessor;
private Thread mProcessorThread;
#region Socket Handling
public bool startServer()
{
IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), FFXIV_MAP_PORT);
try{
mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
catch (Exception e)
{
throw new ApplicationException("Could not create socket, check to make sure not duplicating port", e);
}
try
{
mServerSocket.Bind(serverEndPoint);
mServerSocket.Listen(BACKLOG);
}
catch (Exception e)
{
throw new ApplicationException("Error occured while binding socket, check inner exception", e);
}
try
{
mServerSocket.BeginAccept(new AsyncCallback(acceptCallback), mServerSocket);
}
catch (Exception e)
{
throw new ApplicationException("Error occured starting listeners, check inner exception", e);
}
Console.Write("Game server has started @ ");
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("{0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port);
Console.ForegroundColor = ConsoleColor.Gray;
mProcessor = new PacketProcessor(mConnectionList);
mProcessorThread = new Thread(new ThreadStart(mProcessor.update));
mProcessorThread.Start();
return true;
}
private void acceptCallback(IAsyncResult result)
{
ClientConnection conn = null;
Socket socket = (System.Net.Sockets.Socket)result.AsyncState;
try
{
conn = new ClientConnection();
conn.socket = socket.EndAccept(result);
conn.buffer = new byte[BUFFER_SIZE];
lock (mConnectionList)
{
mConnectionList.Add(conn);
}
Log.conn(String.Format("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port));
//Queue recieving of data from the connection
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn);
//Queue the accept of the next incomming connection
mServerSocket.BeginAccept(new AsyncCallback(acceptCallback), mServerSocket);
}
catch (SocketException)
{
if (conn != null)
{
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
mServerSocket.BeginAccept(new AsyncCallback(acceptCallback), mServerSocket);
}
catch (Exception)
{
if (conn != null)
{
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
mServerSocket.BeginAccept(new AsyncCallback(acceptCallback), mServerSocket);
}
}
private Player findPlayerBySocket(Socket s)
{
lock (mConnectedPlayerList)
{
foreach (Player p in mConnectedPlayerList)
{
if ((p.getConnection1().socket.RemoteEndPoint as IPEndPoint).Address.Equals((s.RemoteEndPoint as IPEndPoint).Address))
{
return p;
}
if ((p.getConnection2().socket.RemoteEndPoint as IPEndPoint).Address.Equals((s.RemoteEndPoint as IPEndPoint).Address))
{
return p;
}
}
}
return null;
}
private Player findPlayerByClientConnection(ClientConnection conn)
{
throw new NotImplementedException();
}
private void receiveCallback(IAsyncResult result)
{
ClientConnection conn = (ClientConnection)result.AsyncState;
try
{
int bytesRead = conn.socket.EndReceive(result);
if (bytesRead > 0)
{
conn.processIncoming(bytesRead);
//Queue the next receive
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), conn);
}
else
{
Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner));
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
}
catch (SocketException)
{
if (conn.socket != null)
{
Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner));
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
}
}
#endregion
}
}

View file

@ -0,0 +1 @@


View file

@ -0,0 +1,274 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Cyotek.Collections.Generic.CircularBuffer</name>
</assembly>
<members>
<member name="T:Cyotek.Collections.Generic.CircularBuffer`1">
<summary>
Represents a first-in, first-out collection of objects using a fixed buffer and automatic overwrite support.
</summary>
<typeparam name="T">Specifies the type of elements in the buffer.</typeparam>
<remarks>
<para>The capacity of a <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> is the number of elements the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> can
hold. If an attempt is made to put more items in the buffer than available capacity, items at the start of the buffer are
automatically overwritten. This behavior can be modified via the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property.</para>
<para>CircularBuffer{T} accepts <c>null</c> as a valid value for reference types and allows duplicate elements.</para>
<para>The <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.Get"/> methods will remove the items that are returned from the CircularBuffer{T}. To view the contents of the CircularBuffer{T} without removing items, use the <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek"/> or <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.PeekLast"/> methods.</para>
</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.#ctor(System.Int32)">
<summary>
Initializes a new instance of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> class that is empty and has the specified initial capacity and default overwrite behavior.
</summary>
<param name="capacity">The maximum capcity of the buffer.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.#ctor(System.Int32,System.Boolean)">
<summary>
Initializes a new instance of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> class that is empty and has the specified initial capacity and overwrite behavior.
</summary>
<param name="capacity">The maximum capcity of the buffer.</param>
<param name="allowOverwrite">If set to <c>true</c> the buffer will automatically overwrite the oldest items when full.</param>
<exception cref="T:System.ArgumentException">Thown if the <paramref name="capacity"/> is less than zero.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Clear">
<summary>
Removes all items from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Contains(`0)">
<summary>
Determines whether the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> contains a specific value.
</summary>
<param name="item">The object to locate in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</param>
<returns><c>true</c> if <paramref name="item"/> is found in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>; otherwise, <c>false</c>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.CopyTo(`0[])">
<summary>
Copies the entire <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the beginning of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.CopyTo(`0[],System.Int32)">
<summary>
Copies the entire <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the specified index of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.CopyTo(System.Int32,`0[],System.Int32,System.Int32)">
<summary>
Copies a range of elements from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the specified index of the target array.
</summary>
<param name="index">The zero-based index in the source <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> at which copying begins.</param>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
<param name="count">The number of elements to copy.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get(System.Int32)">
<summary>
Removes and returns the specified number of objects from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="count">The number of elements to remove and return from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</param>
<returns>The objects that are removed from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get(`0[])">
<summary>
Copies and removes the specified number elements from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the beginning of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<returns>The actual number of elements copied into <paramref name="array"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get(`0[],System.Int32,System.Int32)">
<summary>
Copies and removes the specified number elements from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the specified index of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
<param name="count">The number of elements to copy.</param>
<returns>The actual number of elements copied into <paramref name="array"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get">
<summary>
Removes and returns the object at the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<returns>The object that is removed from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
<remarks>This method is similar to the <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek"/> method, but <c>Peek</c> does not modify the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.GetEnumerator">
<summary>
Returns an enumerator that iterates through the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<returns>A <see cref="T:System.Collections.Generic.IEnumerator`1"/> for the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek">
<summary>
Returns the object at the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> without removing it.
</summary>
<returns>The object at the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek(System.Int32)">
<summary>
Returns the specified number of objects from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="count">The number of elements to return from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</param>
<returns>The objects that from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.PeekLast">
<summary>
Returns the object at the end of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> without removing it.
</summary>
<returns>The object at the end of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Put(`0[])">
<summary>
Copies an entire compatible one-dimensional array to the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the source of the elements copied to <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<exception cref="T:System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
<remarks>If <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.Size"/> plus the size of <paramref name="array"/> exceeds the capacity of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> and the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> are overwritten with <paramref name="array"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Put(`0[],System.Int32,System.Int32)">
<summary>
Copies a range of elements from a compatible one-dimensional array to the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the source of the elements copied to <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
<param name="count">The number of elements to copy.</param>
<exception cref="T:System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
<remarks>If <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.Size"/> plus <paramref name="count"/> exceeds the capacity of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> and the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> are overwritten with <paramref name="array"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Put(`0)">
<summary>
Adds an object to the end of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="item">The object to add to the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The value can be <c>null</c> for reference types.</param>
<exception cref="T:System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
<remarks>If <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.Size"/> already equals the capacity and the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is <c>true</c>, the oldest item in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> is overwritten with <paramref name="item"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Skip(System.Int32)">
<summary>
Increments the starting index of the data buffer in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="count">The number of elements to increment the data buffer start index by.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.ToArray">
<summary>
Copies the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> elements to a new array.
</summary>
<returns>A new array containing elements copied from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<remarks>The <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> is not modified. The order of the elements in the new array is the same as the order of the elements from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to its end.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#CopyTo(System.Array,System.Int32)">
<summary>
Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.ICollection"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#Add(`0)">
<summary>
Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1" />.
</summary>
<param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#Remove(`0)">
<summary>
Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
</summary>
<param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
<returns><c>true</c> if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, <c>false</c>. This method also returns <c>false</c> if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.</returns>
<exception cref="T:System.NotSupportedException">Cannot remove items from collection.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#IEnumerable{T}#GetEnumerator">
<summary>
Returns an enumerator that iterates through the collection.
</summary>
<returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#IEnumerable#GetEnumerator">
<summary>
Returns an enumerator that iterates through a collection.
</summary>
<returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite">
<summary>
Gets or sets a value indicating whether the buffer will automatically overwrite the oldest items in the buffer when the maximum capacity is reached.
</summary>
<value><c>true</c> if the oldest items in the buffer are automatically overwritten when the buffer is full; otherwise, <c>false</c>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Capacity">
<summary>
Gets or sets the total number of elements the internal data structure can hold.
</summary>
<value>The total number of elements that the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> can contain.</value>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown if the specified new capacity is smaller than the current contents of the buffer.</exception>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Head">
<summary>
Gets the index of the beginning of the buffer data.
</summary>
<value>The index of the first element in the buffer.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.IsEmpty">
<summary>
Gets a value indicating whether the buffer is empty.
</summary>
<value><c>true</c> if buffer is empty; otherwise, <c>false</c>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.IsFull">
<summary>
Gets a value indicating whether the buffer is full.
</summary>
<value><c>true</c> if the buffer is full; otherwise, <c>false</c>.</value>
<remarks>The <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.IsFull"/> property always returns <c>false</c> if the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is set to <c>true</c>.</remarks>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Size">
<summary>
Gets the number of elements contained in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<value>The number of elements contained in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Tail">
<summary>
Gets the index of the end of the buffer data.
</summary>
<value>The index of the last element in the buffer.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#Count">
<summary>
Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
</summary>
<value>The number of elements actually contained in the <see cref="T:System.Collections.ICollection"/>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#IsSynchronized">
<summary>
Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread safe).
</summary>
<value><c>true</c> if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread safe); otherwise, <c>false</c>. In the default implementation of <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>, this property always returns <c>false</c>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#SyncRoot">
<summary>
Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
</summary>
<value>An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/></value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#Count">
<summary>
Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
</summary>
<value>The number of elements actually contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#IsReadOnly">
<summary>
Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
</summary>
<value><c>true</c> if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, <c>false</c>. In the default implementation of <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>, this property always returns <c>false</c>.</value>
</member>
</members>
</doc>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data></configuration>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data></configuration>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
[General]
server_ip=141.117.161.40
showtimestamp = true
[Database]
worldid=1
host="141.117.162.99"
port=3306
database="ffxiv_server"
username="root"
password="faqsfaqs"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Lobby_Server.common
{
[global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed class BitfieldLengthAttribute : Attribute
{
uint length;
public BitfieldLengthAttribute(uint length)
{
this.length = length;
}
public uint Length { get { return length; } }
}
static class PrimitiveConversion
{
public static UInt32 ToUInt32<T>(T t) where T : struct
{
UInt32 r = 0;
int offset = 0;
// For every field suitably attributed with a BitfieldLength
foreach (System.Reflection.FieldInfo f in t.GetType().GetFields())
{
object[] attrs = f.GetCustomAttributes(typeof(BitfieldLengthAttribute), false);
if (attrs.Length == 1)
{
uint fieldLength = ((BitfieldLengthAttribute)attrs[0]).Length;
// Calculate a bitmask of the desired length
uint mask = 0;
for (int i = 0; i < fieldLength; i++)
mask |= (UInt32)1 << i;
r |= ((UInt32)f.GetValue(t) & mask) << offset;
offset += (int)fieldLength;
}
}
return r;
}
public static long ToLong<T>(T t) where T : struct
{
long r = 0;
int offset = 0;
// For every field suitably attributed with a BitfieldLength
foreach (System.Reflection.FieldInfo f in t.GetType().GetFields())
{
object[] attrs = f.GetCustomAttributes(typeof(BitfieldLengthAttribute), false);
if (attrs.Length == 1)
{
uint fieldLength = ((BitfieldLengthAttribute)attrs[0]).Length;
// Calculate a bitmask of the desired length
long mask = 0;
for (int i = 0; i < fieldLength; i++)
mask |= 1 << i;
r |= ((UInt32)f.GetValue(t) & mask) << offset;
offset += (int)fieldLength;
}
}
return r;
}
}
}

View file

@ -0,0 +1,74 @@
using System;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace FFXIVClassic_Lobby_Server.common
{
public class Blowfish
{
[DllImport("./Blowfish.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern short initializeBlowfish(byte[] key, short keySize, uint[] P, uint[,] S);
[DllImport("./Blowfish.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void blowfish_encipher(ref int xl, ref int xr, uint[] P);
[DllImport("./Blowfish.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void blowfish_decipher(ref int xl, ref int xr, uint[] P);
private uint[] P = new uint[16+2];
private uint[,] S = new uint[4,256];
public Blowfish(byte[] key)
{
InitBlowfish(key);
}
private int InitBlowfish(byte[] key)
{
return initializeBlowfish(key, (short)key.Length, P, S);
}
public void Encipher(byte[] data, int offset, int length)
{
if ((length - offset) % 8 != 0)
throw new ArgumentException("Needs to be a multiple of 8");
for (int i = offset; i < offset+length; i+=8)
{
int xl = (data[i + 0]) | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24);
int xr = (data[i + 4]) | (data[i + 5] << 8) | (data[i + 6] << 16) | (data[i + 7] << 24);
blowfish_encipher(ref xl, ref xr, P);
data[i + 0] = (byte)(xl >> 0);
data[i + 1] = (byte)(xl >> 8);
data[i + 2] = (byte)(xl >> 16);
data[i + 3] = (byte)(xl >> 24);
data[i + 4] = (byte)(xr >> 0);
data[i + 5] = (byte)(xr >> 8);
data[i + 6] = (byte)(xr >> 16);
data[i + 7] = (byte)(xr >> 24);
}
}
public void Decipher(byte[] data, int offset, int length)
{
if ((length - offset) % 8 != 0)
throw new ArgumentException("Needs to be a multiple of 8");
for (int i = offset; i < offset + length; i += 8)
{
int xl = (data[i + 0]) | (data[i + 1] << 8) | (data[i + 2] << 16) | (data[i + 3] << 24);
int xr = (data[i + 4]) | (data[i + 5] << 8) | (data[i + 6] << 16) | (data[i + 7] << 24);
blowfish_decipher(ref xl, ref xr, P);
data[i + 0] = (byte)(xl >> 0);
data[i + 1] = (byte)(xl >> 8);
data[i + 2] = (byte)(xl >> 16);
data[i + 3] = (byte)(xl >> 24);
data[i + 4] = (byte)(xr >> 0);
data[i + 5] = (byte)(xr >> 8);
data[i + 6] = (byte)(xr >> 16);
data[i + 7] = (byte)(xr >> 24);
}
}
}
}

View file

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Lobby_Server.common
{
class Log
{
public static void error(String message)
{
Console.Write("[{0}]", DateTime.Now.ToString("dd/MMM HH:mm"));
Console.ForegroundColor = ConsoleColor.Red;
Console.Write("[ERROR] ");
Console.ForegroundColor = ConsoleColor.Gray ;
Console.WriteLine(message);
}
public static void debug(String message)
{
Console.Write("[{0}]", DateTime.Now.ToString("dd/MMM HH:mm"));
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("[DEBUG] ");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(message);
}
public static void info(String message)
{
Console.Write("[{0}]", DateTime.Now.ToString("dd/MMM HH:mm"));
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write("[INFO] ");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(message);
}
public static void database(String message)
{
Console.Write("[{0}]", DateTime.Now.ToString("dd/MMM HH:mm"));
Console.ForegroundColor = ConsoleColor.Magenta;
Console.Write("[SQL] ");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(message);
}
public static void conn(String message)
{
Console.Write("[{0}]", DateTime.Now.ToString("dd/MMM HH:mm"));
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("[CONN] ");
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(message);
}
}
}

View file

@ -0,0 +1,541 @@
// *******************************
// *** INIFile class V2.1 ***
// *******************************
// *** (C)2009-2013 S.T.A. snc ***
// *******************************
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
namespace STA.Settings
{
internal class INIFile
{
#region "Declarations"
// *** Lock for thread-safe access to file and local cache ***
private object m_Lock = new object();
// *** File name ***
private string m_FileName = null;
internal string FileName
{
get
{
return m_FileName;
}
}
// *** Lazy loading flag ***
private bool m_Lazy = false;
// *** Automatic flushing flag ***
private bool m_AutoFlush = false;
// *** Local cache ***
private Dictionary<string, Dictionary<string, string>> m_Sections = new Dictionary<string, Dictionary<string, string>>();
private Dictionary<string, Dictionary<string, string>> m_Modified = new Dictionary<string, Dictionary<string, string>>();
// *** Local cache modified flag ***
private bool m_CacheModified = false;
#endregion
#region "Methods"
// *** Constructor ***
public INIFile(string FileName)
{
Initialize(FileName, false, false);
}
public INIFile(string FileName, bool Lazy, bool AutoFlush)
{
Initialize(FileName, Lazy, AutoFlush);
}
// *** Initialization ***
private void Initialize(string FileName, bool Lazy, bool AutoFlush)
{
m_FileName = FileName;
m_Lazy = Lazy;
m_AutoFlush = AutoFlush;
if (!m_Lazy) Refresh();
}
// *** Parse section name ***
private string ParseSectionName(string Line)
{
if (!Line.StartsWith("[")) return null;
if (!Line.EndsWith("]")) return null;
if (Line.Length < 3) return null;
return Line.Substring(1, Line.Length - 2);
}
// *** Parse key+value pair ***
private bool ParseKeyValuePair(string Line, ref string Key, ref string Value)
{
// *** Check for key+value pair ***
int i;
if ((i = Line.IndexOf('=')) <= 0) return false;
int j = Line.Length - i - 1;
Key = Line.Substring(0, i).Trim();
if (Key.Length <= 0) return false;
Value = (j > 0) ? (Line.Substring(i + 1, j).Trim()) : ("");
return true;
}
// *** Read file contents into local cache ***
internal void Refresh()
{
lock (m_Lock)
{
StreamReader sr = null;
try
{
// *** Clear local cache ***
m_Sections.Clear();
m_Modified.Clear();
// *** Open the INI file ***
try
{
sr = new StreamReader(m_FileName);
}
catch (FileNotFoundException)
{
return;
}
// *** Read up the file content ***
Dictionary<string, string> CurrentSection = null;
string s;
string SectionName;
string Key = null;
string Value = null;
while ((s = sr.ReadLine()) != null)
{
s = s.Trim();
// *** Check for section names ***
SectionName = ParseSectionName(s);
if (SectionName != null)
{
// *** Only first occurrence of a section is loaded ***
if (m_Sections.ContainsKey(SectionName))
{
CurrentSection = null;
}
else
{
CurrentSection = new Dictionary<string, string>();
m_Sections.Add(SectionName, CurrentSection);
}
}
else if (CurrentSection != null)
{
// *** Check for key+value pair ***
if (ParseKeyValuePair(s, ref Key, ref Value))
{
// *** Only first occurrence of a key is loaded ***
if (!CurrentSection.ContainsKey(Key))
{
CurrentSection.Add(Key, Value);
}
}
}
}
}
finally
{
// *** Cleanup: close file ***
if (sr != null) sr.Close();
sr = null;
}
}
}
// *** Flush local cache content ***
internal void Flush()
{
lock (m_Lock)
{
PerformFlush();
}
}
private void PerformFlush()
{
// *** If local cache was not modified, exit ***
if (!m_CacheModified) return;
m_CacheModified = false;
// *** Check if original file exists ***
bool OriginalFileExists = File.Exists(m_FileName);
// *** Get temporary file name ***
string TmpFileName = Path.ChangeExtension(m_FileName, "$n$");
// *** Copy content of original file to temporary file, replace modified values ***
StreamWriter sw = null;
// *** Create the temporary file ***
sw = new StreamWriter(TmpFileName);
try
{
Dictionary<string, string> CurrentSection = null;
if (OriginalFileExists)
{
StreamReader sr = null;
try
{
// *** Open the original file ***
sr = new StreamReader(m_FileName);
// *** Read the file original content, replace changes with local cache values ***
string s;
string SectionName;
string Key = null;
string Value = null;
bool Unmodified;
bool Reading = true;
while (Reading)
{
s = sr.ReadLine();
Reading = (s != null);
// *** Check for end of file ***
if (Reading)
{
Unmodified = true;
s = s.Trim();
SectionName = ParseSectionName(s);
}
else
{
Unmodified = false;
SectionName = null;
}
// *** Check for section names ***
if ((SectionName != null) || (!Reading))
{
if (CurrentSection != null)
{
// *** Write all remaining modified values before leaving a section ****
if (CurrentSection.Count > 0)
{
foreach (string fkey in CurrentSection.Keys)
{
if (CurrentSection.TryGetValue(fkey, out Value))
{
sw.Write(fkey);
sw.Write('=');
sw.WriteLine(Value);
}
}
sw.WriteLine();
CurrentSection.Clear();
}
}
if (Reading)
{
// *** Check if current section is in local modified cache ***
if (!m_Modified.TryGetValue(SectionName, out CurrentSection))
{
CurrentSection = null;
}
}
}
else if (CurrentSection != null)
{
// *** Check for key+value pair ***
if (ParseKeyValuePair(s, ref Key, ref Value))
{
if (CurrentSection.TryGetValue(Key, out Value))
{
// *** Write modified value to temporary file ***
Unmodified = false;
CurrentSection.Remove(Key);
sw.Write(Key);
sw.Write('=');
sw.WriteLine(Value);
}
}
}
// *** Write unmodified lines from the original file ***
if (Unmodified)
{
sw.WriteLine(s);
}
}
// *** Close the original file ***
sr.Close();
sr = null;
}
finally
{
// *** Cleanup: close files ***
if (sr != null) sr.Close();
sr = null;
}
}
// *** Cycle on all remaining modified values ***
foreach (KeyValuePair<string, Dictionary<string, string>> SectionPair in m_Modified)
{
CurrentSection = SectionPair.Value;
if (CurrentSection.Count > 0)
{
sw.WriteLine();
// *** Write the section name ***
sw.Write('[');
sw.Write(SectionPair.Key);
sw.WriteLine(']');
// *** Cycle on all key+value pairs in the section ***
foreach (KeyValuePair<string, string> ValuePair in CurrentSection)
{
// *** Write the key+value pair ***
sw.Write(ValuePair.Key);
sw.Write('=');
sw.WriteLine(ValuePair.Value);
}
CurrentSection.Clear();
}
}
m_Modified.Clear();
// *** Close the temporary file ***
sw.Close();
sw = null;
// *** Rename the temporary file ***
File.Copy(TmpFileName, m_FileName, true);
// *** Delete the temporary file ***
File.Delete(TmpFileName);
}
finally
{
// *** Cleanup: close files ***
if (sw != null) sw.Close();
sw = null;
}
}
// *** Read a value from local cache ***
internal string GetValue(string SectionName, string Key, string DefaultValue)
{
// *** Lazy loading ***
if (m_Lazy)
{
m_Lazy = false;
Refresh();
}
lock (m_Lock)
{
// *** Check if the section exists ***
Dictionary<string, string> Section;
if (!m_Sections.TryGetValue(SectionName, out Section)) return DefaultValue;
// *** Check if the key exists ***
string Value;
if (!Section.TryGetValue(Key, out Value)) return DefaultValue;
// *** Return the found value ***
return Value;
}
}
// *** Insert or modify a value in local cache ***
internal void SetValue(string SectionName, string Key, string Value)
{
// *** Lazy loading ***
if (m_Lazy)
{
m_Lazy = false;
Refresh();
}
lock (m_Lock)
{
// *** Flag local cache modification ***
m_CacheModified = true;
// *** Check if the section exists ***
Dictionary<string, string> Section;
if (!m_Sections.TryGetValue(SectionName, out Section))
{
// *** If it doesn't, add it ***
Section = new Dictionary<string, string>();
m_Sections.Add(SectionName,Section);
}
// *** Modify the value ***
if (Section.ContainsKey(Key)) Section.Remove(Key);
Section.Add(Key, Value);
// *** Add the modified value to local modified values cache ***
if (!m_Modified.TryGetValue(SectionName, out Section))
{
Section = new Dictionary<string, string>();
m_Modified.Add(SectionName, Section);
}
if (Section.ContainsKey(Key)) Section.Remove(Key);
Section.Add(Key, Value);
// *** Automatic flushing : immediately write any modification to the file ***
if (m_AutoFlush) PerformFlush();
}
}
// *** Encode byte array ***
private string EncodeByteArray(byte[] Value)
{
if (Value == null) return null;
StringBuilder sb = new StringBuilder();
foreach (byte b in Value)
{
string hex = Convert.ToString(b, 16);
int l = hex.Length;
if (l > 2)
{
sb.Append(hex.Substring(l - 2, 2));
}
else
{
if (l < 2) sb.Append("0");
sb.Append(hex);
}
}
return sb.ToString();
}
// *** Decode byte array ***
private byte[] DecodeByteArray(string Value)
{
if (Value == null) return null;
int l = Value.Length;
if (l < 2) return new byte[] { };
l /= 2;
byte[] Result = new byte[l];
for (int i = 0; i < l; i++) Result[i] = Convert.ToByte(Value.Substring(i * 2, 2), 16);
return Result;
}
// *** Getters for various types ***
internal bool GetValue(string SectionName, string Key, bool DefaultValue)
{
string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(System.Globalization.CultureInfo.InvariantCulture));
int Value;
if (int.TryParse(StringValue, out Value)) return (Value != 0);
return DefaultValue;
}
internal int GetValue(string SectionName, string Key, int DefaultValue)
{
string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
int Value;
if (int.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
return DefaultValue;
}
internal uint GetValue(string SectionName, string Key, uint DefaultValue)
{
string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
uint Value;
if (uint.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
return DefaultValue;
}
internal long GetValue(string SectionName, string Key, long DefaultValue)
{
string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
long Value;
if (long.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
return DefaultValue;
}
internal double GetValue(string SectionName, string Key, double DefaultValue)
{
string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
double Value;
if (double.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
return DefaultValue;
}
internal byte[] GetValue(string SectionName, string Key, byte[] DefaultValue)
{
string StringValue = GetValue(SectionName, Key, EncodeByteArray(DefaultValue));
try
{
return DecodeByteArray(StringValue);
}
catch (FormatException)
{
return DefaultValue;
}
}
internal DateTime GetValue(string SectionName, string Key, DateTime DefaultValue)
{
string StringValue = GetValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
DateTime Value;
if (DateTime.TryParse(StringValue, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.AssumeLocal, out Value)) return Value;
return DefaultValue;
}
// *** Setters for various types ***
internal void SetValue(string SectionName, string Key, bool Value)
{
SetValue(SectionName, Key, (Value) ? ("1") : ("0"));
}
internal void SetValue(string SectionName, string Key, int Value)
{
SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
}
internal void SetValue(string SectionName, string Key, long Value)
{
SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
}
internal void SetValue(string SectionName, string Key, double Value)
{
SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
}
internal void SetValue(string SectionName, string Key, byte[] Value)
{
SetValue(SectionName, Key, EncodeByteArray(Value));
}
internal void SetValue(string SectionName, string Key, DateTime Value)
{
SetValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
}
#endregion
}
}

View file

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Lobby_Server.common
{
static class Utils
{
private static readonly uint[] _lookup32 = CreateLookup32();
private static uint[] CreateLookup32()
{
var result = new uint[256];
for (int i = 0; i < 256; i++)
{
string s = i.ToString("X2");
result[i] = ((uint)s[0]) + ((uint)s[1] << 16);
}
return result;
}
public static string ByteArrayToHex(byte[] bytes)
{
var lookup32 = _lookup32;
var result = new char[(bytes.Length * 3) + ((bytes.Length/16) < 1 ? 1 : (bytes.Length/16)*3) + bytes.Length+60];
int numNewLines = 0;
for (int i = 0; i < bytes.Length; i++)
{
var val = lookup32[bytes[i]];
result[(3 * i) + (17 * numNewLines) + 0] = (char)val;
result[(3 * i) + (17 * numNewLines) + 1] = (char)(val >> 16);
result[(3 * i) + (17 * numNewLines) + 2] = ' ';
result[(numNewLines * (3*16+17)) + (3 * 16) + (i % 16)] = (char)bytes[i] >= 32 && (char)bytes[i] <= 126 ? (char)bytes[i] : '.';
if (i != bytes.Length - 1 && bytes.Length > 16 && i != 0 && (i+1) % 16 == 0)
{
result[(numNewLines * (3*16+17)) + (3 * 16) + (16)] = '\n';
numNewLines++;
}
}
return new string(result);
}
public static UInt32 UnixTimeStampUTC()
{
UInt32 unixTimeStamp;
DateTime currentTime = DateTime.Now;
DateTime zuluTime = currentTime.ToUniversalTime();
DateTime unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (UInt32)(zuluTime.Subtract(unixEpoch)).TotalSeconds;
return unixTimeStamp;
}
}
}

View file

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FFXIVClassic_Map_Server.dataobjects
{
class Actor
{
enum Appearance {
MODEL,
SIZE,
COLORINFO,
FACEINFO,
HIGHLIGHT_HAIR,
VOICE,
WEAPON1,
WEAPON2,
WEAPON3,
HEADGEAR,
BODYGEAR,
LEGSGEAR,
HANDSGEAR,
FEETGEAR,
WAISTGEAR,
UNKNOWN1,
R_EAR,
L_EAR,
UNKNOWN2,
UNKNOWN3,
R_FINGER,
L_FINGER
}
public uint actorID;
public uint displayNameID;
public string customDisplayName;
public uint[] appearanceIDs;
public float positionX, positionY, positionZ;
public float rotation;
public ushort moveState;
public Actor(uint id)
{
actorID = id;
}
}
}

View file

@ -0,0 +1,314 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Lobby_Server.common;
using System.IO;
namespace FFXIVClassic_Lobby_Server.dataobjects
{
class CharaInfo
{
public uint tribe = 0;
public uint size = 0;
public uint voice = 0;
public ushort skinColor = 0;
public ushort hairStyle = 0;
public ushort hairColor = 0;
public ushort hairHighlightColor = 0;
public ushort eyeColor = 0;
public ushort characteristicsColor = 0;
public struct FaceInfo
{
[BitfieldLength(5)]
public uint characteristics;
[BitfieldLength(3)]
public uint characteristicsColor;
[BitfieldLength(6)]
public uint type;
[BitfieldLength(2)]
public uint ears;
[BitfieldLength(2)]
public uint mouth;
[BitfieldLength(2)]
public uint features;
[BitfieldLength(3)]
public uint nose;
[BitfieldLength(3)]
public uint eyeShape;
[BitfieldLength(1)]
public uint irisSize;
[BitfieldLength(3)]
public uint eyebrows;
[BitfieldLength(2)]
public uint unknown;
}
public uint faceType = 0;
public uint faceEyebrows = 0;
public uint faceEyeShape = 0;
public uint faceIrisSize = 0;
public uint faceNose = 0;
public uint faceMouth = 0;
public uint faceFeatures = 0;
public uint characteristics = 0;
public uint ears = 0;
public uint guardian = 0;
public uint birthMonth = 0;
public uint birthDay = 0;
public uint currentClass = 0;
public uint currentJob = 0;
public uint allegiance = 0;
public uint mainHand = 0;
public uint offHand = 0;
public uint headGear = 0;
public uint bodyGear = 0;
public uint legsGear = 0;
public uint handsGear = 0;
public uint feetGear = 0;
public uint waistGear = 0;
public uint rightEarGear = 0;
public uint leftEarGear = 0;
public uint rightFingerGear = 0;
public uint leftFingerGear = 0;
public uint currentLevel = 1;
public static CharaInfo getFromNewCharRequest(String encoded)
{
byte[] data = Convert.FromBase64String(encoded.Replace('-', '+').Replace('_', '/'));
CharaInfo info = new CharaInfo();
using (MemoryStream stream = new MemoryStream(data))
{
using (BinaryReader reader = new BinaryReader(stream))
{
uint version = reader.ReadUInt32();
uint unknown1 = reader.ReadUInt32();
info.tribe = reader.ReadByte();
info.size = reader.ReadByte();
info.hairStyle = reader.ReadUInt16();
info.hairHighlightColor = reader.ReadUInt16();
info.faceType = reader.ReadByte();
info.characteristics = reader.ReadByte();
info.characteristicsColor = reader.ReadByte();
reader.ReadUInt32();
info.faceEyebrows = reader.ReadByte();
info.faceIrisSize = reader.ReadByte();
info.faceEyeShape = reader.ReadByte();
info.faceNose = reader.ReadByte();
info.faceFeatures = reader.ReadByte();
info.faceMouth = reader.ReadByte();
info.ears = reader.ReadByte();
info.hairColor = reader.ReadUInt16();
reader.ReadUInt32();
info.skinColor = reader.ReadUInt16();
info.eyeColor = reader.ReadUInt16();
info.voice = reader.ReadByte();
info.guardian = reader.ReadByte();
info.birthMonth = reader.ReadByte();
info.birthDay = reader.ReadByte();
info.currentClass = reader.ReadUInt16();
reader.ReadUInt32();
reader.ReadUInt32();
reader.ReadUInt32();
reader.BaseStream.Seek(0x10, SeekOrigin.Current);
info.allegiance = reader.ReadByte();
}
}
return info;
}
public String buildForCharaList(Character chara)
{
byte[] data;
mainHand = 79707136;
offHand = 32509954;
headGear = 43008;
bodyGear = 43008;
legsGear = 43008;
handsGear = 43008;
feetGear = 43008;
using (MemoryStream stream = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stream))
{
//Build faceinfo for later
FaceInfo faceInfo = new FaceInfo();
faceInfo.characteristics = characteristics;
faceInfo.characteristicsColor = characteristicsColor;
faceInfo.type = faceType;
faceInfo.ears = ears;
faceInfo.features = faceFeatures;
faceInfo.eyebrows = faceEyebrows;
faceInfo.eyeShape = faceEyeShape;
faceInfo.irisSize = faceIrisSize;
faceInfo.mouth = faceMouth;
faceInfo.nose = faceNose;
string location1 = "prv0Inn01\0";
string location2 = "defaultTerritory\0";
writer.Write((UInt32)0x000004c0);
writer.Write((UInt32)0x232327ea);
writer.Write((UInt32)System.Text.Encoding.UTF8.GetBytes(chara.name + '\0').Length);
writer.Write(System.Text.Encoding.UTF8.GetBytes(chara.name + '\0'));
writer.Write((UInt32)0x1c);
writer.Write((UInt32)0x04);
writer.Write((UInt32)getTribeModel());
writer.Write((UInt32)size);
uint colorVal = skinColor | (uint)(hairColor << 10) | (uint)(eyeColor << 20);
writer.Write((UInt32)colorVal);
var bitfield = PrimitiveConversion.ToUInt32(faceInfo);
writer.Write((UInt32)bitfield); //FACE, Figure this out!
uint hairVal = hairHighlightColor | (uint)(hairStyle << 10) | (uint)(characteristicsColor << 20);
writer.Write((UInt32)hairVal);
writer.Write((UInt32)voice);
writer.Write((UInt32)mainHand);
writer.Write((UInt32)offHand);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)headGear);
writer.Write((UInt32)bodyGear);
writer.Write((UInt32)legsGear);
writer.Write((UInt32)handsGear);
writer.Write((UInt32)feetGear);
writer.Write((UInt32)waistGear);
writer.Write((UInt32)0);
writer.Write((UInt32)rightEarGear);
writer.Write((UInt32)leftEarGear);
writer.Write((UInt32)0);
writer.Write((UInt32)0);
writer.Write((UInt32)rightFingerGear);
writer.Write((UInt32)leftFingerGear);
for (int i = 0; i < 0x8; i++)
writer.Write((byte)0);
writer.Write((UInt32)1);
writer.Write((UInt32)1);
writer.Write((byte)currentClass);
writer.Write((UInt16)currentLevel);
writer.Write((byte)currentJob);
writer.Write((UInt16)1);
writer.Write((byte)tribe);
writer.Write((UInt32)0xe22222aa);
writer.Write((UInt32)System.Text.Encoding.UTF8.GetBytes(location1).Length);
writer.Write(System.Text.Encoding.UTF8.GetBytes(location1));
writer.Write((UInt32)System.Text.Encoding.UTF8.GetBytes(location2).Length);
writer.Write(System.Text.Encoding.UTF8.GetBytes(location2));
writer.Write((byte)guardian);
writer.Write((byte)birthMonth);
writer.Write((byte)birthDay);
writer.Write((UInt16)0x17);
writer.Write((UInt32)4);
writer.Write((UInt32)4);
writer.BaseStream.Seek(0x10, SeekOrigin.Current);
writer.Write((UInt32)allegiance);
writer.Write((UInt32)allegiance);
}
data = stream.GetBuffer();
}
return Convert.ToBase64String(data).Replace('+', '-').Replace('/', '_');
}
public static String debug()
{
byte[] bytes = File.ReadAllBytes("./packets/charaInfo.bin");
Console.WriteLine(Utils.ByteArrayToHex(bytes));
return Convert.ToBase64String(bytes).Replace('+', '-').Replace('/', '_');
}
public UInt32 getTribeModel()
{
switch (tribe)
{
//Hyur Midlander Male
case 1:
default:
return 1;
//Hyur Midlander Female
case 2:
return 2;
//Elezen Male
case 4:
case 6:
return 3;
//Elezen Female
case 5:
case 7:
return 4;
//Lalafell Male
case 8:
case 10:
return 5;
//Lalafell Female
case 9:
case 11:
return 6;
//Miqo'te Female
case 12:
case 13:
return 8;
//Roegadyn Male
case 14:
case 15:
return 7;
//Hyur Highlander Male
case 3:
return 9;
}
}
}
}

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Lobby_Server.dataobjects;
namespace FFXIVClassic_Lobby_Server
{
class Character
{
public uint id;
public ushort slot;
public ushort serverId;
public string name;
public ushort state;
public string charaInfo;
public bool isLegacy;
public bool doRename;
public uint currentZoneId;
public static CharaInfo EncodedToCharacter(String charaInfo)
{
charaInfo.Replace("+", "-");
charaInfo.Replace("/", "_");
byte[] data = System.Convert.FromBase64String(charaInfo);
Console.WriteLine("------------Base64 printout------------------");
Console.WriteLine(Utils.ByteArrayToHex(data));
Console.WriteLine("------------Base64 printout------------------");
CharaInfo chara = new CharaInfo();
return chara;
}
}
}

View file

@ -0,0 +1,102 @@
using FFXIVClassic_Lobby_Server;
using FFXIVClassic_Lobby_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.dataobjects
{
class Player
{
Actor playerActor;
ClientConnection conn1;
ClientConnection conn2;
public uint characterID = 0;
public uint actorID = 0;
uint currentZoneID = 0;
List<Actor> actorInstanceList = new List<Actor>();
bool isDisconnected;
public Player(uint actorId)
{
this.actorID = actorId;
createPlayerActor(actorId, null);
}
public void addConnection(ClientConnection conn)
{
if (conn1 == null && conn2 != null)
conn1 = conn;
else if (conn2 == null && conn1 != null)
conn2 = conn;
else
conn1 = conn;
}
public bool isClientConnectionsReady()
{
return (conn1 != null && conn2 != null);
}
public void disconnect()
{
isDisconnected = true;
conn1.disconnect();
conn2.disconnect();
}
public void setConnection1(ClientConnection conn)
{
conn1 = conn;
}
public void setConnection2(ClientConnection conn)
{
conn2 = conn;
}
public ClientConnection getConnection1()
{
return conn1;
}
public ClientConnection getConnection2()
{
return conn1;
}
public void createPlayerActor(uint actorId, Character chara)
{
playerActor = new Actor(actorId);
actorInstanceList.Add(playerActor);
}
public void updatePlayerActorPosition(float x, float y, float z, float rot, ushort moveState)
{
playerActor.positionX = x;
playerActor.positionY = y;
playerActor.positionZ = z;
playerActor.rotation = rot;
playerActor.moveState = moveState;
}
public void sendMotd()
{
World world = Database.getServer(ConfigConstants.DATABASE_WORLDID);
//sendChat(world.motd);
}
public void sendChat(Player sender, string message, int mode)
{
}
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Lobby_Server.dataobjects
{
class World
{
public ushort id;
public string address;
public ushort port;
public ushort listPosition;
public ushort population;
public string name;
public bool isActive;
public string motd;
}
}

View file

@ -0,0 +1,14 @@
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\FFXIVClassic Map Server.exe.config
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\obj\Debug\FFXIVClassic Map Server.csprojResolveAssemblyReference.cache
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\FFXIVClassic Map Server.exe
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\FFXIVClassic Map Server.pdb
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\Cyotek.Collections.Generic.CircularBuffer.dll
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\Dapper.dll
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\MySql.Data.dll
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\Newtonsoft.Json.dll
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\Cyotek.Collections.Generic.CircularBuffer.xml
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\Dapper.pdb
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\Dapper.xml
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\bin\Debug\Newtonsoft.Json.xml
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\obj\Debug\FFXIVClassic Map Server.exe
c:\users\filip\documents\visual studio 2013\Projects\FFXIVClassic Map Server\FFXIVClassic Map Server\obj\Debug\FFXIVClassic Map Server.pdb

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Cyotek.CircularBuffer" version="1.0.0.0" targetFramework="net45" />
<package id="Dapper" version="1.42" targetFramework="net45" />
<package id="MySql.Data" version="6.9.7" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages>

View file

@ -0,0 +1,289 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Diagnostics;
using FFXIVClassic_Lobby_Server.common;
using System.IO;
namespace FFXIVClassic_Lobby_Server.packets
{
[StructLayout(LayoutKind.Sequential)]
public struct BasePacketHeader
{
public byte isAuthenticated;
public byte isEncrypted;
public ushort reserved;
public ushort packetSize;
public ushort numSubpackets;
public uint unknown1; //Id?
public uint unknown2; //Usually 0x13B
}
public class BasePacket{
public const int BASEPACKET_SIZE = 0x10;
public BasePacketHeader header;
public byte[] data;
public unsafe BasePacket(String path)
{
byte[] bytes = File.ReadAllBytes(path);
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
if (bytes.Length < header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
int packetSize = header.packetSize;
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
}
public unsafe BasePacket(byte[] bytes)
{
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
if (bytes.Length < header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
int packetSize = header.packetSize;
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
}
public unsafe BasePacket(byte[] bytes, ref int offset)
{
if (bytes.Length < offset + BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[offset])
{
header = (BasePacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
int packetSize = header.packetSize;
if (bytes.Length < offset + header.packetSize)
throw new OverflowException("Packet Error: Packet size didn't equal given size");
data = new byte[packetSize - BASEPACKET_SIZE];
Array.Copy(bytes, offset + BASEPACKET_SIZE, data, 0, packetSize - BASEPACKET_SIZE);
offset += packetSize;
}
public BasePacket(BasePacketHeader header, byte[] data)
{
this.header = header;
this.data = data;
}
public List<SubPacket> getSubpackets()
{
List<SubPacket> subpackets = new List<SubPacket>(header.numSubpackets);
int offset = 0;
while (offset < data.Length)
subpackets.Add(new SubPacket(data, ref offset));
return subpackets;
}
public unsafe static BasePacketHeader getHeader(byte[] bytes)
{
BasePacketHeader header;
if (bytes.Length < BASEPACKET_SIZE)
throw new OverflowException("Packet Error: Packet was too small");
fixed (byte* pdata = &bytes[0])
{
header = (BasePacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(BasePacketHeader));
}
return header;
}
public byte[] getHeaderBytes()
{
int size = Marshal.SizeOf(header);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(header, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] getPacketBytes()
{
byte[] outBytes = new byte[header.packetSize];
Array.Copy(getHeaderBytes(), 0, outBytes, 0, BASEPACKET_SIZE);
Array.Copy(data, 0, outBytes, BASEPACKET_SIZE, data.Length);
return outBytes;
}
#region Utility Functions
public static BasePacket createPacket(List<SubPacket> subpackets, bool isAuthed, bool isEncrypted)
{
//Create Header
BasePacketHeader header = new BasePacketHeader();
byte[] data = null;
header.isAuthenticated = isAuthed?(byte)1:(byte)0;
header.isEncrypted = isEncrypted?(byte)1:(byte)0;
header.numSubpackets = (ushort)subpackets.Count;
header.packetSize = BASEPACKET_SIZE;
//Get packet size
foreach (SubPacket subpacket in subpackets)
header.packetSize += subpacket.header.subpacketSize;
data = new byte[header.packetSize-0x10];
//Add Subpackets
int offset = 0;
foreach (SubPacket subpacket in subpackets)
{
byte[] subpacketData = subpacket.getBytes();
Array.Copy(subpacketData, 0, data, offset, subpacketData.Length);
offset += (ushort)subpacketData.Length;
}
Debug.Assert(data != null && offset == data.Length && header.packetSize == 0x10 + offset);
BasePacket packet = new BasePacket(header, data);
return packet;
}
public static BasePacket createPacket(SubPacket subpacket, bool isAuthed, bool isEncrypted)
{
//Create Header
BasePacketHeader header = new BasePacketHeader();
byte[] data = null;
header.isAuthenticated = isAuthed ? (byte)1 : (byte)0;
header.isEncrypted = isEncrypted ? (byte)1 : (byte)0;
header.numSubpackets = (ushort)1;
header.packetSize = BASEPACKET_SIZE;
//Get packet size
header.packetSize += subpacket.header.subpacketSize;
data = new byte[header.packetSize - 0x10];
//Add Subpackets
byte[] subpacketData = subpacket.getBytes();
Array.Copy(subpacketData, 0, data, 0, subpacketData.Length);
Debug.Assert(data != null);
BasePacket packet = new BasePacket(header, data);
return packet;
}
public static BasePacket createPacket(byte[] data, bool isAuthed, bool isEncrypted)
{
Debug.Assert(data != null);
//Create Header
BasePacketHeader header = new BasePacketHeader();
header.isAuthenticated = isAuthed ? (byte)1 : (byte)0;
header.isEncrypted = isEncrypted ? (byte)1 : (byte)0;
header.numSubpackets = (ushort)1;
header.packetSize = BASEPACKET_SIZE;
//Get packet size
header.packetSize += (ushort)data.Length;
BasePacket packet = new BasePacket(header, data);
return packet;
}
public static unsafe void encryptPacket(Blowfish blowfish, BasePacket packet)
{
byte[] data = packet.data;
int size = packet.header.packetSize;
int offset = 0;
while (offset < data.Length) {
if (data.Length < offset + SubPacket.SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
SubPacketHeader header;
fixed (byte* pdata = &data[offset])
{
header = (SubPacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (data.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
blowfish.Encipher(data, offset + 0x10, header.subpacketSize-0x10);
offset += header.subpacketSize;
}
}
public static unsafe void decryptPacket(Blowfish blowfish, ref BasePacket packet)
{
byte[] data = packet.data;
int size = packet.header.packetSize;
int offset = 0;
while (offset < data.Length)
{
if (data.Length < offset + SubPacket.SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
SubPacketHeader header;
fixed (byte* pdata = &data[offset])
{
header = (SubPacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (data.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
blowfish.Decipher(data, offset + 0x10, header.subpacketSize-0x10);
offset += header.subpacketSize;
}
}
#endregion
public void debugPrintPacket()
{
#if DEBUG
Console.BackgroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("IsAuthed: {0}, IsEncrypted: {1}, Size: 0x{2:X}, Num Subpackets: {3}", header.isAuthenticated, header.isEncrypted, header.packetSize, header.numSubpackets);
Console.WriteLine("{0}", Utils.ByteArrayToHex(getHeaderBytes()));
foreach (SubPacket sub in getSubpackets())
sub.debugPrintSubPacket();
Console.BackgroundColor = ConsoleColor.Black;
#endif
}
}
}

View file

@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using FFXIVClassic_Lobby_Server;
using FFXIVClassic_Lobby_Server.common;
namespace FFXIVClassic_Lobby_Server.packets
{
[StructLayout(LayoutKind.Sequential)]
public struct SubPacketHeader
{
public ushort subpacketSize;
public ushort unknown0; //Always 0x03
public uint sourceId;
public uint targetId;
public uint unknown1;
public ushort unknown4; //Always 0x14
public ushort opcode;
public uint unknown5;
public uint timestamp;
public uint unknown6;
}
public class SubPacket
{
public const int SUBPACKET_SIZE = 0x20;
public SubPacketHeader header;
public byte[] data;
public unsafe SubPacket(byte[] bytes, ref int offset)
{
if (bytes.Length < offset + SUBPACKET_SIZE)
throw new OverflowException("Packet Error: Subpacket was too small");
fixed (byte* pdata = &bytes[offset])
{
header = (SubPacketHeader)Marshal.PtrToStructure(new IntPtr(pdata), typeof(SubPacketHeader));
}
if (bytes.Length < offset + header.subpacketSize)
throw new OverflowException("Packet Error: Subpacket size didn't equal subpacket data");
data = new byte[header.subpacketSize - SUBPACKET_SIZE];
Array.Copy(bytes, offset + SUBPACKET_SIZE, data, 0, data.Length);
offset += header.subpacketSize;
}
public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data)
{
this.header = new SubPacketHeader();
header.opcode = opcode;
header.sourceId = sourceId;
header.targetId = targetId;
header.timestamp = Utils.UnixTimeStampUTC();
header.unknown0 = 0x03;
header.unknown1 = 0x00;
header.unknown4 = 0x14;
header.unknown5 = 0x00;
header.unknown6 = 0x00;
this.data = data;
header.subpacketSize = (ushort)(0x20 + data.Length);
}
public byte[] getHeaderBytes()
{
int size = Marshal.SizeOf(header);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(header, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public byte[] getBytes()
{
byte[] outBytes = new byte[header.subpacketSize];
Array.Copy(getHeaderBytes(), 0, outBytes, 0, SUBPACKET_SIZE);
Array.Copy(data, 0, outBytes, SUBPACKET_SIZE, data.Length);
return outBytes;
}
public void debugPrintSubPacket()
{
#if DEBUG
Console.BackgroundColor = ConsoleColor.DarkRed;
Console.WriteLine("Size: 0x{0:X}, Opcode: 0x{1:X}", header.subpacketSize, header.opcode);
Console.WriteLine("{0}", Utils.ByteArrayToHex(getHeaderBytes()));
Console.BackgroundColor = ConsoleColor.DarkMagenta;
Console.WriteLine("{0}", Utils.ByteArrayToHex(data));
Console.BackgroundColor = ConsoleColor.Black;
#endif
}
}
}

View file

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.receive
{
class HandshakePacket
{
bool invalidPacket = false;
public uint actorID;
public HandshakePacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try{
binReader.BaseStream.Seek(4, SeekOrigin.Begin);
actorID = UInt32.Parse(Encoding.ASCII.GetString(binReader.ReadBytes(10)));
}
catch (Exception){
invalidPacket = true;
}
}
}
}
}
}

View file

@ -0,0 +1,33 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.receive
{
class PingPacket
{
bool invalidPacket = false;
public uint time;
public PingPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try{
time = binReader.ReadUInt32();
}
catch (Exception){
invalidPacket = true;
}
}
}
}
}
}

View file

@ -0,0 +1,41 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.receive
{
class UpdatePlayerPositionPacket
{
bool invalidPacket = false;
public ulong time;
public float x, y, z, rot;
public ushort moveState; //0: Standing, 1: Walking, 2: Running
public UpdatePlayerPositionPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try{
time = binReader.ReadUInt64();
x = binReader.ReadSingle();
y = binReader.ReadSingle();
z = binReader.ReadSingle();
rot = binReader.ReadSingle();
moveState = binReader.ReadUInt16();
}
catch (Exception){
invalidPacket = true;
}
}
}
}
}
}

View file

@ -0,0 +1,21 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor
{
class AddActorPacket
{
public const ushort OPCODE = 0x00CA;
public const uint PACKET_SIZE = 0x28;
public static SubPacket buildPacket(uint playerActorID, uint actorID)
{
return new SubPacket(OPCODE, playerActorID, actorID, new byte[8]);
}
}
}

View file

@ -0,0 +1,34 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor
{
class MoveActorToPositionPacket
{
public const ushort OPCODE = 0x00CF;
public const uint PACKET_SIZE = 0x48;
public static SubPacket buildPacket(uint playerActorID, uint actorID)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
}
data = mem.GetBuffer();
}
SubPacket packet = new SubPacket(OPCODE, playerActorID, actorID, data);
return packet;
}
}
}

View file

@ -0,0 +1,21 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor
{
class RemoveActorPacket
{
public const ushort OPCODE = 0x00CB;
public const uint PACKET_SIZE = 0x28;
public static SubPacket buildPacket(uint playerActorID, uint actorID)
{
return new SubPacket(OPCODE, playerActorID, actorID, new byte[8]);
}
}
}

View file

@ -0,0 +1,79 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor
{
class SetActorAppearancePacket
{
public const ushort OPCODE = 0x00D6;
public const uint PACKET_SIZE = 0x128;
public const int SIZE = 0;
public const int COLORINFO = 1;
public const int FACEINFO = 2;
public const int HIGHLIGHT_HAIR = 3;
public const int VOICE = 4;
public const int WEAPON1 = 5;
public const int WEAPON2 = 6;
public const int WEAPON3 = 7;
public const int HEADGEAR = 8;
public const int BODYGEAR = 9;
public const int LEGSGEAR = 10;
public const int HANDSGEAR = 11;
public const int FEETGEAR = 12;
public const int WAISTGEAR = 13;
public const int UNKNOWN1 = 14;
public const int R_EAR = 15;
public const int L_EAR = 16;
public const int UNKNOWN2 = 17;
public const int UNKNOWN3 = 18;
public const int R_FINGER = 19;
public const int L_FINGER = 20;
public uint modelID;
public uint[] appearanceIDs;
public SetActorAppearancePacket(uint monsterModelID)
{
modelID = monsterModelID;
appearanceIDs = new uint[22];
}
public SetActorAppearancePacket(uint[] appearanceTable)
{
appearanceIDs = appearanceTable;
}
public SubPacket buildPacket(uint playerActorID, uint actorID)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((uint)modelID);
for (int i = 0; i < 0x1A; i++)
{
binWriter.Write((uint)i);
binWriter.Write((uint)appearanceIDs[i]);
}
binWriter.Write((uint) 0x1B);
binWriter.Seek(0x20, SeekOrigin.Current);
binWriter.Write((uint) 0x1C);
binWriter.Write((uint) 0x00);
}
data = mem.GetBuffer();
}
SubPacket packet = new SubPacket(OPCODE, playerActorID, actorID, data);
return packet;
}
}
}

View file

@ -0,0 +1,34 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.actor
{
class SetActorPositionPacket
{
public const ushort OPCODE = 0x00CE;
public const uint PACKET_SIZE = 0x48;
public static SubPacket buildPacket(uint playerActorID, uint actorID)
{
byte[] data = new byte[PACKET_SIZE-0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
}
data = mem.GetBuffer();
}
SubPacket packet = new SubPacket(OPCODE, playerActorID, actorID, data);
return packet;
}
}
}

View file

@ -0,0 +1,35 @@
using FFXIVClassic_Lobby_Server.common;
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.receive
{
class PongPacket
{
public const ushort OPCODE = 0x0001;
public const uint PACKET_SIZE = 0x40;
public static SubPacket buildPacket(uint playerActorID, ulong pingTicks)
{
byte[] data = new byte[PACKET_SIZE-0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using(BinaryWriter binWriter = new BinaryWriter(mem))
{
ulong time = pingTicks;
binWriter.Write(time);
}
}
SubPacket subpacket = new SubPacket(OPCODE, playerActorID, playerActorID, data);
return subpacket;
}
}
}

View file

@ -0,0 +1,33 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send
{
class SetMapPacket
{
public const ushort OPCODE = 0x0005;
public const uint PACKET_SIZE = 0x30;
public static SubPacket buildPacket(uint playerActorID, uint mapID)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((uint)mapID);
binWriter.Write((uint)0x9B);
binWriter.Write((uint)0x28);
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View file

@ -0,0 +1,21 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send
{
class SetMusicPacket
{
public const ushort OPCODE = 0x000C;
public const uint PACKET_SIZE = 0x28;
public static SubPacket buildPacket(uint playerActorID, uint musicID, uint musicTrackMode)
{
ulong combined = musicID | (musicTrackMode << 32);
return new SubPacket(OPCODE, 0, playerActorID, BitConverter.GetBytes(combined));
}
}
}

View file

@ -0,0 +1,20 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send
{
class SetWeatherPacket
{
public const ushort OPCODE = 0x000D;
public const uint PACKET_SIZE = 0x28;
public static SubPacket buildPacket(uint playerActorID, long weatherID)
{
return new SubPacket(OPCODE, 0, playerActorID, BitConverter.GetBytes(weatherID));
}
}
}

View file

@ -0,0 +1,32 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.login
{
class _0x2Packet
{
public const ushort OPCODE = 0x0002;
public const uint PACKET_SIZE = 0x30;
public static SubPacket buildPacket(uint playerActorID)
{
byte[] data = new byte[PACKET_SIZE-0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.BaseStream.Seek(0x8, SeekOrigin.Begin);
binWriter.Write((uint)playerActorID);
}
}
return new SubPacket(OPCODE, playerActorID, playerActorID, data);
}
}
}

View file

@ -0,0 +1,41 @@
using FFXIVClassic_Lobby_Server.packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.send.login
{
class InitPacket
{
public static BasePacket buildPacket(uint unknown, uint time)
{
byte[] data = new byte[18];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
try
{
binWriter.Write((short)0x18);
binWriter.Write((short)0x7);
binWriter.Write((uint)0);
binWriter.Write((uint)0);
binWriter.Write((uint)0xFFFFFD7F);
binWriter.Write((uint)unknown);
binWriter.Write((uint)time);
}
catch (Exception)
{
}
}
}
return BasePacket.createPacket(data, false, false);
}
}
}

View file

@ -0,0 +1,274 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Cyotek.Collections.Generic.CircularBuffer</name>
</assembly>
<members>
<member name="T:Cyotek.Collections.Generic.CircularBuffer`1">
<summary>
Represents a first-in, first-out collection of objects using a fixed buffer and automatic overwrite support.
</summary>
<typeparam name="T">Specifies the type of elements in the buffer.</typeparam>
<remarks>
<para>The capacity of a <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> is the number of elements the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> can
hold. If an attempt is made to put more items in the buffer than available capacity, items at the start of the buffer are
automatically overwritten. This behavior can be modified via the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property.</para>
<para>CircularBuffer{T} accepts <c>null</c> as a valid value for reference types and allows duplicate elements.</para>
<para>The <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.Get"/> methods will remove the items that are returned from the CircularBuffer{T}. To view the contents of the CircularBuffer{T} without removing items, use the <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek"/> or <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.PeekLast"/> methods.</para>
</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.#ctor(System.Int32)">
<summary>
Initializes a new instance of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> class that is empty and has the specified initial capacity and default overwrite behavior.
</summary>
<param name="capacity">The maximum capcity of the buffer.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.#ctor(System.Int32,System.Boolean)">
<summary>
Initializes a new instance of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> class that is empty and has the specified initial capacity and overwrite behavior.
</summary>
<param name="capacity">The maximum capcity of the buffer.</param>
<param name="allowOverwrite">If set to <c>true</c> the buffer will automatically overwrite the oldest items when full.</param>
<exception cref="T:System.ArgumentException">Thown if the <paramref name="capacity"/> is less than zero.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Clear">
<summary>
Removes all items from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Contains(`0)">
<summary>
Determines whether the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> contains a specific value.
</summary>
<param name="item">The object to locate in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</param>
<returns><c>true</c> if <paramref name="item"/> is found in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>; otherwise, <c>false</c>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.CopyTo(`0[])">
<summary>
Copies the entire <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the beginning of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.CopyTo(`0[],System.Int32)">
<summary>
Copies the entire <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the specified index of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.CopyTo(System.Int32,`0[],System.Int32,System.Int32)">
<summary>
Copies a range of elements from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the specified index of the target array.
</summary>
<param name="index">The zero-based index in the source <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> at which copying begins.</param>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
<param name="count">The number of elements to copy.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get(System.Int32)">
<summary>
Removes and returns the specified number of objects from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="count">The number of elements to remove and return from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</param>
<returns>The objects that are removed from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get(`0[])">
<summary>
Copies and removes the specified number elements from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the beginning of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<returns>The actual number of elements copied into <paramref name="array"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get(`0[],System.Int32,System.Int32)">
<summary>
Copies and removes the specified number elements from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to a compatible one-dimensional array, starting at the specified index of the target array.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
<param name="count">The number of elements to copy.</param>
<returns>The actual number of elements copied into <paramref name="array"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Get">
<summary>
Removes and returns the object at the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<returns>The object that is removed from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
<remarks>This method is similar to the <see cref="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek"/> method, but <c>Peek</c> does not modify the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.GetEnumerator">
<summary>
Returns an enumerator that iterates through the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<returns>A <see cref="T:System.Collections.Generic.IEnumerator`1"/> for the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek">
<summary>
Returns the object at the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> without removing it.
</summary>
<returns>The object at the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Peek(System.Int32)">
<summary>
Returns the specified number of objects from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="count">The number of elements to return from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</param>
<returns>The objects that from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.PeekLast">
<summary>
Returns the object at the end of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> without removing it.
</summary>
<returns>The object at the end of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<exception cref="T:System.InvalidOperationException">Thrown if the buffer is empty.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Put(`0[])">
<summary>
Copies an entire compatible one-dimensional array to the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the source of the elements copied to <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<exception cref="T:System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
<remarks>If <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.Size"/> plus the size of <paramref name="array"/> exceeds the capacity of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> and the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> are overwritten with <paramref name="array"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Put(`0[],System.Int32,System.Int32)">
<summary>
Copies a range of elements from a compatible one-dimensional array to the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the source of the elements copied to <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
<param name="count">The number of elements to copy.</param>
<exception cref="T:System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
<remarks>If <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.Size"/> plus <paramref name="count"/> exceeds the capacity of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> and the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is <c>true</c>, the oldest items in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> are overwritten with <paramref name="array"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Put(`0)">
<summary>
Adds an object to the end of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="item">The object to add to the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>. The value can be <c>null</c> for reference types.</param>
<exception cref="T:System.InvalidOperationException">Thrown if buffer does not have sufficient capacity to put in new items.</exception>
<remarks>If <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.Size"/> already equals the capacity and the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is <c>true</c>, the oldest item in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> is overwritten with <paramref name="item"/>.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.Skip(System.Int32)">
<summary>
Increments the starting index of the data buffer in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<param name="count">The number of elements to increment the data buffer start index by.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.ToArray">
<summary>
Copies the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> elements to a new array.
</summary>
<returns>A new array containing elements copied from the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</returns>
<remarks>The <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> is not modified. The order of the elements in the new array is the same as the order of the elements from the beginning of the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> to its end.</remarks>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#CopyTo(System.Array,System.Int32)">
<summary>
Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
</summary>
<param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied from <see cref="T:System.Collections.ICollection"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param>
<param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#Add(`0)">
<summary>
Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1" />.
</summary>
<param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#Remove(`0)">
<summary>
Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
</summary>
<param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
<returns><c>true</c> if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, <c>false</c>. This method also returns <c>false</c> if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.</returns>
<exception cref="T:System.NotSupportedException">Cannot remove items from collection.</exception>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#IEnumerable{T}#GetEnumerator">
<summary>
Returns an enumerator that iterates through the collection.
</summary>
<returns>A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.</returns>
</member>
<member name="M:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#IEnumerable#GetEnumerator">
<summary>
Returns an enumerator that iterates through a collection.
</summary>
<returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite">
<summary>
Gets or sets a value indicating whether the buffer will automatically overwrite the oldest items in the buffer when the maximum capacity is reached.
</summary>
<value><c>true</c> if the oldest items in the buffer are automatically overwritten when the buffer is full; otherwise, <c>false</c>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Capacity">
<summary>
Gets or sets the total number of elements the internal data structure can hold.
</summary>
<value>The total number of elements that the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/> can contain.</value>
<exception cref="T:System.ArgumentOutOfRangeException">Thrown if the specified new capacity is smaller than the current contents of the buffer.</exception>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Head">
<summary>
Gets the index of the beginning of the buffer data.
</summary>
<value>The index of the first element in the buffer.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.IsEmpty">
<summary>
Gets a value indicating whether the buffer is empty.
</summary>
<value><c>true</c> if buffer is empty; otherwise, <c>false</c>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.IsFull">
<summary>
Gets a value indicating whether the buffer is full.
</summary>
<value><c>true</c> if the buffer is full; otherwise, <c>false</c>.</value>
<remarks>The <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.IsFull"/> property always returns <c>false</c> if the <see cref="P:Cyotek.Collections.Generic.CircularBuffer`1.AllowOverwrite"/> property is set to <c>true</c>.</remarks>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Size">
<summary>
Gets the number of elements contained in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.
</summary>
<value>The number of elements contained in the <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.Tail">
<summary>
Gets the index of the end of the buffer data.
</summary>
<value>The index of the last element in the buffer.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#Count">
<summary>
Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
</summary>
<value>The number of elements actually contained in the <see cref="T:System.Collections.ICollection"/>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#IsSynchronized">
<summary>
Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread safe).
</summary>
<value><c>true</c> if access to the <see cref="T:System.Collections.ICollection"/> is synchronized (thread safe); otherwise, <c>false</c>. In the default implementation of <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>, this property always returns <c>false</c>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#ICollection#SyncRoot">
<summary>
Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/>.
</summary>
<value>An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"/></value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#Count">
<summary>
Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
</summary>
<value>The number of elements actually contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</value>
</member>
<member name="P:Cyotek.Collections.Generic.CircularBuffer`1.System#Collections#Generic#ICollection{T}#IsReadOnly">
<summary>
Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
</summary>
<value><c>true</c> if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, <c>false</c>. In the default implementation of <see cref="T:Cyotek.Collections.Generic.CircularBuffer`1"/>, this property always returns <c>false</c>.</value>
</member>
</members>
</doc>

BIN
packages/Dapper.1.42/Dapper.1.42.nupkg vendored Normal file

Binary file not shown.

1149
packages/Dapper.1.42/lib/net35/Dapper.xml vendored Normal file

File diff suppressed because it is too large Load diff

1138
packages/Dapper.1.42/lib/net40/Dapper.xml vendored Normal file

File diff suppressed because it is too large Load diff

1412
packages/Dapper.1.42/lib/net45/Dapper.xml vendored Normal file

File diff suppressed because it is too large Load diff

64
packages/MySql.Data.6.9.7/CHANGES vendored Normal file
View file

@ -0,0 +1,64 @@
6.9.7
- Changed default SSL mode to Preferred in connection string. Now the server connections will be using SSL if server allows it by default but it's possible to override this configuration.
- Changed handshake process to use bytes instead of encoded strings.
- Fix for Fabric connections (Oracle Bug #20983968).
- Fix for Fabric plugin: fabric server selection is broken when master is faulty (Oracle Bug #21203824).
6.9.6
- Fix for Incorrect query result with Entity Framework 6 (MySql bug #74918, Oracle bug #20129927).
- Fix for GetTimeZoneOffset to use date and time to calculate timediff (MySQL Bug #74905, Oracle Bug #20065691).
- Fix for MySqlSimpleMembershipProvider keeps database connections open on some operations (MySQL Bug #74662, Oracle Bug #20109419)
- Fix for Any Call to RoleExists() returns true whether or not the role exists (MySql bug #75397, Oracle bug #20325391).
- Fix for all dateTimes set as UTC Kind (MySQL Bug #74134, Oracle Bug #20200662).
- Fix for Invalid SQL query when eager loading two nested collections (MySQL Bug #70941, Oracle bug #18049862).
- Fix for chinese characters used in the connection string when connecting to MySql Server (MySQL Bug #70041, Oracle Bug #18141356).
6.9.5
- Disabled installation on-demand in Installer (Oracle Bug #19670596).
- Fix for Generated SQL requests column that doesn't exist in LINQ to Entities (MySql bug #72004, Oracle bug #19681348).
- Fix for MySQL Connector/NET generates incorrect SQL for LINQ 'StartsWith' queries (MySql bug #72058, Oracle bug #19680236).
- Fix for Exception when using IEnumerable.Contains(model.property) in Where predicate (MySql bug #73643, Oracle bug #19690370).
- Fix for Generated Sql does not contain ORDER BY statement whose is requested by LINQ (MySql bug #73549, Oracle bug #19698010).
- Fix for Web providers registration in machine.config (removed v20 suffix) (MySQL Bug #74080, Oracle Bug #19715398)
- Fix for Error of "Every derived table must have an alias" in LINQ to Entities when using EF6 + DbFirst + View + Take
(MySql Bug #72148, Oracle bug #19356006).
- Fix for 'the method or operation is not implemented' when using linq with orderby (MySQL Bug #70722, Oracle Bug #19681723).
- Fix for Exception "The given key was not present in the dictionary" when using utf16le charset in a query. (MySql #72737, Oracle Bug #19355906)
- Fix for Memory leak in a loop opening a connection to the database and executing a command (MySql Bug #73122, Oracle Bug #19467233).
- Fix for Multiple issues caused by trailing and leading white space character in params using MySql Membership Provider (MySql Bug #73411, Oracle Bug #19453313)
- Fix for bad assumption leads to modify query adding CALL statement to the beginning of the sql query even when CommandType.Text is specified (MySql Bug #72736, Oracle Bug #19325120).
6.9.4
- Added a new plugin for MySql Fabric 1.5 support
6.9.3
- Fix for Web Parts Personalization provider
- Fix for changing the PK between two int columns (MySql Bug #71418, Oracle bug #18923294).
- Fix for Error when Calling MySqlConnection.GetSchema("PROCEDURES WITH PARAMETERS", ...) (Oracle bug #19285959).
- Fix for EF provider reports ManifestProviderToken = 5.6 for server 5.7 (Oracle bug #19453814).
- Fix for Fluent API DbModelBuilder.HasColumnType is ignored in EF6 (Oracle bug #19456229).
- Fix for Setting a PK GUID identity in Code First in EF6 no longer works in Server 5.7 (Oracle bug #19456452).
- Non PKs declared as Identity GUID have no GUID autogenerated (Oracle bug #19456415).
6.9.2
- Add async/await compatible methods
- Fix for Unable to read geometry column when it has been set with a SRID value. (MySql Bug #71869, Oracle Bug #19137999)
- Fix for Exception adding a new column to an existing model as identity and PK fails when applying the migration (MySql Bug #71418, Oracle bug #18923294).
- Added SiteMap and Personalization configuration web providers to MySql.Web Nuget Package.
6.9.1
- Fix for Exception of "duplicate entry" in MySqlSessionProvider (MySql Bug #70409, Oracle bug #18657550).
6.9.0
- Added implementation of MySQLPersonalizationProvider.
- Added SiteMap Web provider.
- Added Simple Membership Web Provider.
- Fix for open sockets connections left when connection open fails, the error happens when the client try to get a connection when the max number of connections is reached in the server. (MySql #72025, Oracle Bug #18665388).

Binary file not shown.

15
packages/MySql.Data.6.9.7/Readme.txt vendored Normal file
View file

@ -0,0 +1,15 @@
Connector/Net 6.9 Release Notes
------------------------------------
Welcome to the release notes for Connector/Net 6.9
What's new in 6.9
--------------------
- Simple Membership Web Provider
- Site Map Web Provider
- Personalization Web Provider
- MySql Fabric support
Be sure and check the documentation for more information on these new features.

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
</configuration>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
</configuration>

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
param($installPath, $toolsPath, $package, $project)
# open json.net splash page on package install
# don't open if json.net is installed as a dependency
try
{
$url = "http://www.newtonsoft.com/json/install?version=" + $package.Version
$dte2 = Get-Interface $dte ([EnvDTE80.DTE2])
if ($dte2.ActiveWindow.Caption -eq "Package Manager Console")
{
# user is installing from VS NuGet console
# get reference to the window, the console host and the input history
# show webpage if "install-package newtonsoft.json" was last input
$consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow])
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1
if ($prop -eq $null) { return }
$hostInfo = $prop.GetValue($consoleWindow)
if ($hostInfo -eq $null) { return }
$history = $hostInfo.WpfConsole.InputHistory.History
$lastCommand = $history | select -last 1
if ($lastCommand)
{
$lastCommand = $lastCommand.Trim().ToLower()
if ($lastCommand.StartsWith("install-package") -and $lastCommand.Contains("newtonsoft.json"))
{
$dte2.ItemOperations.Navigate($url) | Out-Null
}
}
}
else
{
# user is installing from VS NuGet dialog
# get reference to the window, then smart output console provider
# show webpage if messages in buffered console contains "installing...newtonsoft.json" in last operation
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor `
[System.Reflection.BindingFlags]::NonPublic)
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
if ($instanceField -eq $null -or $consoleField -eq $null) { return }
$instance = $instanceField.GetValue($null)
if ($instance -eq $null) { return }
$consoleProvider = $consoleField.GetValue($instance)
if ($consoleProvider -eq $null) { return }
$console = $consoleProvider.CreateOutputConsole($false)
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
if ($messagesField -eq $null) { return }
$messages = $messagesField.GetValue($console)
if ($messages -eq $null) { return }
$operations = $messages -split "=============================="
$lastOperation = $operations | select -last 1
if ($lastOperation)
{
$lastOperation = $lastOperation.ToLower()
$lines = $lastOperation -split "`r`n"
$installMatch = $lines | ? { $_.StartsWith("------- installing...newtonsoft.json ") } | select -first 1
if ($installMatch)
{
$dte2.ItemOperations.Navigate($url) | Out-Null
}
}
}
}
catch
{
try
{
$pmPane = $dte2.ToolWindows.OutputWindow.OutputWindowPanes.Item("Package Manager")
$selection = $pmPane.TextDocument.Selection
$selection.StartOfDocument($false)
$selection.EndOfDocument($true)
if ($selection.Text.StartsWith("Attempting to gather dependencies information for package 'Newtonsoft.Json." + $package.Version + "'"))
{
$dte2.ItemOperations.Navigate($url) | Out-Null
}
}
catch
{
# stop potential errors from bubbling up
# worst case the splash page won't open
}
}
# still yolo

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\FFXIVClassic Map Server\packages.config" />
</repositories>