├── .gitignore ├── GatewayServer ├── App.config ├── ClientContext.cs ├── Data │ └── Globals.cs ├── Gateway.cs ├── GatewayServer.csproj ├── PacketProcessor.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── Services │ ├── Launcher.cs │ ├── Patch.cs │ ├── Session.cs │ └── Shard.cs ├── README.md ├── SCommon ├── Database │ └── MSSQL.cs ├── Enumerations.cs ├── Geometry.cs ├── Logging.cs ├── Networking │ ├── SocketContext.cs │ └── TCPServer.cs ├── ObjectPool.cs ├── Opcode.cs ├── PooledList.cs ├── SCommon.projitems ├── SCommon.shproj ├── Security │ ├── Blowfish.cs │ ├── Packet.cs │ ├── PacketReader.cs │ ├── PacketWriter.cs │ ├── Security.cs │ └── TransferBuffer.cs └── Utility.cs ├── SCore.dll ├── SCore ├── SCore.sln └── SCore │ ├── AssemblyInfo.cpp │ ├── AsyncTimer.Native.cpp │ ├── AsyncTimer.Native.h │ ├── AsyncTimer.cpp │ ├── AsyncTimer.h │ ├── AutoCriticalSection.cpp │ ├── AutoCriticalSection.h │ ├── ReadMe.txt │ ├── SCore.cpp │ ├── SCore.h │ ├── SCore.vcxproj │ ├── SCore.vcxproj.filters │ ├── Stdafx.cpp │ ├── Stdafx.h │ ├── app.ico │ ├── app.rc │ └── resource.h ├── SR_GameServer ├── App.config ├── ClientContext.cs ├── Data │ ├── Enumarations.cs │ ├── Globals.cs │ ├── NavMesh │ │ ├── Collision.cs │ │ ├── JmxMesh.cs │ │ ├── JmxNavmesh.cs │ │ ├── JmxObj.cs │ │ ├── JmxRes.cs │ │ └── Structures.cs │ ├── RefData │ │ ├── RefCharGen.cs │ │ ├── RefDropGold.cs │ │ ├── RefFmnTidGroupMap.cs │ │ ├── RefLevel.cs │ │ ├── RefObj.cs │ │ ├── RefRegion.cs │ │ ├── RefShop.cs │ │ ├── RefSkill.cs │ │ ├── RefTeleport.cs │ │ └── Tab_Ref.cs │ └── Structures.cs ├── Enumarations.cs ├── Formula.cs ├── GObj.cs ├── GObjChar.cs ├── GObjItem.cs ├── GObjMob.cs ├── GObjNPC.cs ├── GameWorld │ ├── AIManager.cs │ └── GObjUtils.cs ├── PacketProcessor.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── SQLTableMapping.cs ├── SRGame.cs ├── SR_GameServer.csproj ├── Services │ └── UniqueID.cs └── Structures.cs ├── SharpDX.dll ├── SilkroadProject.sln └── clipper_library.dll /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | Output/ 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | build/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | *.cachefile 82 | 83 | # Visual Studio profiler 84 | *.psess 85 | *.vsp 86 | *.vspx 87 | 88 | # TFS 2012 Local Workspace 89 | $tf/ 90 | 91 | # Guidance Automation Toolkit 92 | *.gpState 93 | 94 | # ReSharper is a .NET coding add-in 95 | _ReSharper*/ 96 | *.[Rr]e[Ss]harper 97 | *.DotSettings.user 98 | 99 | # JustCode is a .NET coding add-in 100 | .JustCode 101 | 102 | # TeamCity is a build add-in 103 | _TeamCity* 104 | 105 | # DotCover is a Code Coverage Tool 106 | *.dotCover 107 | 108 | # NCrunch 109 | _NCrunch_* 110 | .*crunch*.local.xml 111 | 112 | # MightyMoose 113 | *.mm.* 114 | AutoTest.Net/ 115 | 116 | # Web workbench (sass) 117 | .sass-cache/ 118 | 119 | # Installshield output folder 120 | [Ee]xpress/ 121 | 122 | # DocProject is a documentation generator add-in 123 | DocProject/buildhelp/ 124 | DocProject/Help/*.HxT 125 | DocProject/Help/*.HxC 126 | DocProject/Help/*.hhc 127 | DocProject/Help/*.hhk 128 | DocProject/Help/*.hhp 129 | DocProject/Help/Html2 130 | DocProject/Help/html 131 | 132 | # Click-Once directory 133 | publish/ 134 | 135 | # Publish Web Output 136 | *.[Pp]ublish.xml 137 | *.azurePubxml 138 | ## TODO: Comment the next line if you want to checkin your 139 | ## web deploy settings but do note that will include unencrypted 140 | ## passwords 141 | #*.pubxml 142 | 143 | *.publishproj 144 | 145 | # NuGet Packages 146 | *.nupkg 147 | # The packages folder can be ignored because of Package Restore 148 | **/packages/* 149 | # except build/, which is used as an MSBuild target. 150 | !**/packages/build/ 151 | # Uncomment if necessary however generally it will be regenerated when needed 152 | #!**/packages/repositories.config 153 | 154 | # Windows Azure Build Output 155 | csx/ 156 | *.build.csdef 157 | 158 | # Windows Store app package directory 159 | AppPackages/ 160 | 161 | # Visual Studio cache files 162 | # files ending in .cache can be ignored 163 | *.[Cc]ache 164 | # but keep track of directories ending in .cache 165 | !*.[Cc]ache/ 166 | 167 | # Others 168 | ClientBin/ 169 | [Ss]tyle[Cc]op.* 170 | ~$* 171 | *~ 172 | *.dbmdl 173 | *.dbproj.schemaview 174 | *.pfx 175 | *.publishsettings 176 | node_modules/ 177 | orleans.codegen.cs 178 | 179 | # RIA/Silverlight projects 180 | Generated_Code/ 181 | 182 | # Backup & report files from converting an old project file 183 | # to a newer Visual Studio version. Backup files are not needed, 184 | # because we have git ;-) 185 | _UpgradeReport_Files/ 186 | Backup*/ 187 | UpgradeLog*.XML 188 | UpgradeLog*.htm 189 | 190 | # SQL Server files 191 | *.mdf 192 | *.ldf 193 | 194 | # Business Intelligence projects 195 | *.rdl.data 196 | *.bim.layout 197 | *.bim_*.settings 198 | 199 | # Microsoft Fakes 200 | FakesAssemblies/ 201 | 202 | # Node.js Tools for Visual Studio 203 | .ntvs_analysis.dat 204 | 205 | # Visual Studio 6 build log 206 | *.plg 207 | 208 | # Visual Studio 6 workspace options file 209 | *.opt 210 | 211 | # LightSwitch generated files 212 | GeneratedArtifacts/ 213 | _Pvt_Extensions/ 214 | ModelManifest.xml 215 | *.opendb 216 | *.metagen 217 | -------------------------------------------------------------------------------- /GatewayServer/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /GatewayServer/ClientContext.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer 2 | { 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | using SCore; 7 | 8 | using SCommon.Security; 9 | using SCommon.Networking; 10 | 11 | public class ClientContext : IDisposable 12 | { 13 | #region Private Properties and Fields 14 | 15 | /// 16 | /// Stores if the class has disposed 17 | /// 18 | private bool m_blDisposed; 19 | 20 | /// 21 | /// 22 | /// 23 | private bool m_blDisconnected; 24 | 25 | /// 26 | /// The context. 27 | /// 28 | private SocketContext m_SocketContext; 29 | 30 | /// 31 | /// The ping timer. 32 | /// 33 | private AsyncTimer m_PingTimer; 34 | 35 | #endregion 36 | 37 | #region Constructors & Destructors 38 | 39 | public ClientContext() 40 | { 41 | m_PingTimer = new AsyncTimer(PingTimerCallback); 42 | m_blDisconnected = false; 43 | } 44 | 45 | public ClientContext(SocketContext context) 46 | : this () 47 | { 48 | m_SocketContext = context; 49 | } 50 | 51 | ~ClientContext() 52 | { 53 | Dispose(false); 54 | } 55 | 56 | public void Dispose() 57 | { 58 | Dispose(true); 59 | GC.SuppressFinalize(this); 60 | } 61 | 62 | protected virtual void Dispose(bool disposing) 63 | { 64 | if (!m_blDisposed) 65 | { 66 | if (disposing) 67 | { 68 | // 69 | } 70 | m_PingTimer = null; 71 | m_blDisposed = true; 72 | } 73 | } 74 | #endregion 75 | 76 | #region Public Properties and Fields 77 | 78 | /// 79 | /// Gets the context. 80 | /// 81 | public SocketContext SocketContext => m_SocketContext; 82 | 83 | /// 84 | /// Gets the ping timer. 85 | /// 86 | public AsyncTimer PingTimer => m_PingTimer; 87 | 88 | /// 89 | /// Gets or sets the last ping tick. 90 | /// 91 | public int LastPingTick { get; set; } 92 | 93 | /// 94 | /// Gets or sets the last server list send tick 95 | /// 96 | public int LastServerListTick { get; set; } = Environment.TickCount; 97 | 98 | #endregion 99 | 100 | #region Public Methods 101 | 102 | /// 103 | /// Sets the socket context. 104 | /// 105 | /// The socket context. 106 | public void SetContext(SocketContext context) 107 | { 108 | m_SocketContext = context; 109 | m_blDisconnected = false; 110 | } 111 | 112 | #pragma warning disable 1998, 4014 113 | public async Task ProcessLoginResult(Services._shard_item shard, string id, string password) 114 | { 115 | using (var reader = await Data.Globals.AccountDB.ExecuteReaderAsync("exec _CertifyTB_User '{0}', '{1}'", id, password)) 116 | { 117 | await reader.ReadAsync(); 118 | 119 | Packet resp = new Packet(SCommon.Opcode.Gateway.Response.LOGIN); 120 | 121 | int type = await reader.GetFieldValueAsync(0); 122 | switch (type) 123 | { 124 | case 0: 125 | { 126 | int sid = await reader.GetFieldValueAsync(1); 127 | byte sec_content = await reader.GetFieldValueAsync(2); 128 | int session_id = -1; 129 | lock (shard.m_lock) 130 | { 131 | if (shard.CurrentUsers < shard.MaxUsers) 132 | session_id = Services.Session.Generate(); 133 | } 134 | 135 | if (session_id != -1) 136 | { 137 | Data.Globals.GlobalDB.ExecuteCommandAsync("INSERT INTO _ActiveSessions (UserSID, SessionID, Processed) VALUES ({0}, {1}, 0)", sid, session_id); 138 | 139 | resp.WriteByte(1); 140 | resp.WriteInt32(session_id); 141 | resp.WriteAscii(Data.Globals.GetConfigValue("GameServerIPAddress")); 142 | resp.WriteUInt16(Data.Globals.GetConfigValue("GameServerPort")); 143 | } 144 | else 145 | { 146 | resp.WriteByte(2); 147 | resp.WriteByte(5); 148 | } 149 | } 150 | break; 151 | case 1: 152 | { 153 | int sid = await reader.GetFieldValueAsync(1); 154 | string ban_reason = await reader.GetFieldValueAsync(2); 155 | DateTime ban_endTime = await reader.GetFieldValueAsync(3); 156 | 157 | resp.WriteByte(2); 158 | resp.WriteByte(2); 159 | resp.WriteByte(1); 160 | resp.WriteAscii(ban_reason); 161 | resp.WriteUInt16(ban_endTime.Year); 162 | resp.WriteUInt16(ban_endTime.Month); 163 | resp.WriteUInt16(ban_endTime.Day); 164 | resp.WriteUInt16(ban_endTime.Hour); 165 | resp.WriteUInt16(ban_endTime.Minute); 166 | resp.WriteUInt16(ban_endTime.Second); 167 | resp.WriteInt32(ban_endTime.Millisecond); 168 | } 169 | break; 170 | case 2: 171 | { 172 | resp.WriteByte(2); 173 | resp.WriteByte(1); 174 | 175 | if (Data.Globals.WrongPasswordTries.ContainsKey(id)) 176 | { 177 | var wrong = Data.Globals.WrongPasswordTries[id]; 178 | 179 | resp.WriteInt32(++wrong.Tries); 180 | 181 | wrong.LastTick = Environment.TickCount; 182 | Data.Globals.WrongPasswordTries[id] = wrong; 183 | } 184 | else 185 | { 186 | var wrong = new Data._wrongpass_item 187 | { 188 | LastTick = Environment.TickCount, 189 | Tries = 1 190 | }; 191 | Data.Globals.WrongPasswordTries.Add(id, wrong); 192 | 193 | resp.WriteInt32(1); 194 | } 195 | 196 | resp.WriteInt32(Data.Globals.MAX_WRONG_PASSWORD); 197 | } 198 | break; 199 | case 3: 200 | { 201 | //already in game packet 202 | } 203 | break; 204 | } 205 | 206 | m_SocketContext.Send(resp); 207 | Disconnect(); 208 | } 209 | } 210 | 211 | /// 212 | /// Disconnects the client 213 | /// 214 | /// if true, the function won't call Socket.Disconnect 215 | public void Disconnect(bool disconnecting = false) 216 | { 217 | lock (this) 218 | { 219 | if (!disconnecting) 220 | m_SocketContext.Disconnect(); 221 | 222 | if (!m_blDisconnected) 223 | { 224 | if (m_PingTimer.IsRunning) 225 | m_PingTimer.Stop(); 226 | m_blDisconnected = true; 227 | } 228 | } 229 | } 230 | 231 | #endregion 232 | 233 | #region Private Methods 234 | 235 | /// 236 | /// The ping timer's callback. 237 | /// 238 | /// The sender. 239 | /// The state. 240 | private void PingTimerCallback(object sender, object state) 241 | { 242 | if (Environment.TickCount - LastPingTick >= 10000) 243 | { 244 | LastPingTick = Environment.TickCount; 245 | Console.WriteLine("client timeout, disconnecting (last: {0}, elapsed: {1})", LastPingTick, Environment.TickCount - LastPingTick); 246 | m_PingTimer.Reset(-1, 0); 247 | Disconnect(); 248 | } 249 | } 250 | 251 | #endregion 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /GatewayServer/Data/Globals.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer.Data 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | using SCommon.Database; 7 | 8 | public struct _wrongpass_item 9 | { 10 | public int Tries; 11 | public int LastTick; 12 | } 13 | 14 | internal static class Globals 15 | { 16 | public const int MAX_WRONG_PASSWORD = 3; 17 | 18 | public static Gateway GatewayService; 19 | public static Dictionary Config; 20 | public static Dictionary WrongPasswordTries; 21 | public static MSSQL GlobalDB; 22 | public static MSSQL AccountDB; 23 | 24 | public static bool ConnectGlobalDB() 25 | { 26 | try 27 | { 28 | GlobalDB = new MSSQL("SR_Global Connection String"); 29 | return true; 30 | } 31 | #if DEBUG 32 | catch (Exception ex) 33 | #else 34 | catch (Exception) 35 | #endif 36 | { 37 | #if DEBUG 38 | Console.WriteLine(ex); 39 | #endif 40 | return false; 41 | } 42 | } 43 | 44 | public static bool ConnectAccountDB() 45 | { 46 | try 47 | { 48 | AccountDB = new MSSQL("SR_Account Connection String"); 49 | return true; 50 | } 51 | #if DEBUG 52 | catch (Exception ex) 53 | #else 54 | catch (Exception) 55 | #endif 56 | { 57 | #if DEBUG 58 | Console.WriteLine(ex); 59 | #endif 60 | return false; 61 | } 62 | } 63 | 64 | public static bool LoadConfigTable() 65 | { 66 | try 67 | { 68 | Config = new Dictionary(); 69 | using (var reader = GlobalDB.ExecuteReader("SELECT * FROM _ServerConfig")) 70 | { 71 | while (reader.Read()) 72 | Data.Globals.Config.Add(Convert.ToString(reader["Key"]), Convert.ToString(reader["Value"])); 73 | } 74 | return true; 75 | } 76 | #if DEBUG 77 | catch (Exception ex) 78 | #else 79 | catch (Exception) 80 | #endif 81 | { 82 | #if DEBUG 83 | Console.WriteLine(ex); 84 | #endif 85 | return false; 86 | } 87 | } 88 | 89 | public static T GetConfigValue(string key) 90 | { 91 | return (T)Convert.ChangeType(Config[key], typeof(T)); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /GatewayServer/Gateway.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer 2 | { 3 | using System; 4 | using System.Threading; 5 | 6 | using SCommon; 7 | using SCommon.Networking; 8 | using SCommon.Security; 9 | 10 | internal class Gateway 11 | { 12 | #region Private Properties and Fields 13 | 14 | /// 15 | /// The server's ip address 16 | /// 17 | private string m_IPAddress; 18 | 19 | /// 20 | /// The server's port 21 | /// 22 | private int m_Port; 23 | 24 | /// 25 | /// The tcp server 26 | /// 27 | private TCPServer m_Server; 28 | 29 | /// 30 | /// The pool for class 31 | /// 32 | private ObjectPool m_ClientContextPool; 33 | 34 | #endregion 35 | 36 | #region Constructors and Destructors 37 | 38 | public Gateway(string ip, int port) 39 | { 40 | m_IPAddress = ip; 41 | m_Port = port; 42 | m_ClientContextPool = new ObjectPool(() => new ClientContext(), () => m_ClientContextPool.Count > 200); 43 | 44 | Services.Patch.Initialize(); 45 | Services.Shard.Initialize(); 46 | Services.Launcher.Initialize(); 47 | Services.Session.Initialize(); 48 | } 49 | 50 | #endregion 51 | 52 | #region Public Properties and Fileds 53 | 54 | public int ActiveConnectionCount => Interlocked.Exchange(ref m_Server.m_ConnectionCount, m_Server.m_ConnectionCount); 55 | 56 | #endregion 57 | 58 | #region Public Methods 59 | 60 | /// 61 | /// Updates the gateway service's state 62 | /// 63 | /// 64 | public void UpdateServiceState(bool state) 65 | { 66 | if (state) 67 | { 68 | //initialize the server and start the tcp service 69 | if (m_Server == null) 70 | { 71 | m_Server = new TCPServer(m_IPAddress, m_Port, SecurityFlags.Blowfish | SecurityFlags.SecurityBytes); 72 | TCPServer.OnNewConnection += Gateway_NewConnection; 73 | SocketContext.OnPacketReceived += SocketContext_PacketReceived; 74 | SocketContext.OnLostConnection += SocketContext_ConnectionLost; 75 | m_Server.StartService(); 76 | } 77 | } 78 | else 79 | { 80 | // 81 | } 82 | } 83 | 84 | #endregion 85 | 86 | #region Private Methods 87 | 88 | /// 89 | /// The OnNewConnection event. 90 | /// 91 | /// The client context. 92 | /// The socket context. 93 | private void Gateway_NewConnection(object sender, SocketContext context) 94 | { 95 | #if DEBUG 96 | Logging.Log()(String.Format("A new connection has arrived. (SocketContext Hash Code:{0:X8})", context.GetHashCode()), LogLevel.Info); 97 | #endif 98 | ClientContext client = m_ClientContextPool.GetObject(); 99 | client.SetContext(context); 100 | 101 | context.SetContext(client); 102 | } 103 | 104 | /// 105 | /// The OnPacketReceived event. 106 | /// 107 | /// The client context. 108 | /// The socket context. 109 | private void SocketContext_PacketReceived(object sender, Packet packet) 110 | { 111 | Func fn; 112 | ClientContext client = (ClientContext)((SocketContext)sender).Context; 113 | 114 | client.LastPingTick = Environment.TickCount; 115 | 116 | if (PacketProcessor.OpcodeMap[packet.Opcode] != null) 117 | fn = PacketProcessor.OpcodeMap[packet.Opcode]; 118 | else 119 | fn = PacketProcessor.OpcodeMap[0]; 120 | 121 | if (!fn(client, packet)) 122 | client.Disconnect(); 123 | } 124 | 125 | /// 126 | /// The OnLostConnection event. 127 | /// 128 | /// The client context. 129 | /// The event args. 130 | private void SocketContext_ConnectionLost(object sender, EventArgs args) 131 | { 132 | #if DEBUG 133 | Logging.Log()(String.Format("A connection has dropped. (SocketContext Hash Code:{0:X8})", sender.GetHashCode()), LogLevel.Info); 134 | #endif 135 | ClientContext client = (ClientContext)((SocketContext)sender).Context; 136 | client.Disconnect(true); 137 | m_ClientContextPool.PutObject(client); 138 | } 139 | 140 | #endregion 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /GatewayServer/GatewayServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {422E556D-B2C7-4607-A485-3B1C6EED41EB} 8 | Exe 9 | Properties 10 | GatewayServer 11 | GatewayServer 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | ..\Output\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | true 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | ..\Output\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | true 38 | bin\x86\Debug\ 39 | DEBUG;TRACE 40 | full 41 | x86 42 | prompt 43 | MinimumRecommendedRules.ruleset 44 | true 45 | 46 | 47 | bin\x86\Release\ 48 | TRACE 49 | true 50 | pdbonly 51 | x86 52 | prompt 53 | MinimumRecommendedRules.ruleset 54 | true 55 | true 56 | 57 | 58 | true 59 | bin\x64\Debug\ 60 | DEBUG;TRACE 61 | true 62 | full 63 | x64 64 | prompt 65 | MinimumRecommendedRules.ruleset 66 | true 67 | 68 | 69 | bin\x64\Release\ 70 | TRACE 71 | true 72 | pdbonly 73 | x64 74 | prompt 75 | MinimumRecommendedRules.ruleset 76 | true 77 | 78 | 79 | 80 | ..\clipper_library.dll 81 | 82 | 83 | ..\..\..\..\..\Downloads\LeagueSharp\System\SharpDX.dll 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | {a0e9c09c-cc53-474f-bdd5-a641f57e2215} 112 | SCore 113 | 114 | 115 | 116 | 117 | 124 | -------------------------------------------------------------------------------- /GatewayServer/PacketProcessor.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer 2 | { 3 | using System; 4 | using System.Linq; 5 | 6 | using SCommon.Security; 7 | 8 | using Opcode = SCommon.Opcode; 9 | 10 | public static class PacketProcessor 11 | { 12 | #region Private Properties and Fields 13 | 14 | /// 15 | /// The opcode map. 16 | /// 17 | private static Func[] s_OpcodeMap = new Func[256 * 256]; 18 | 19 | #endregion 20 | 21 | #region Public Properties and Fields 22 | 23 | /// 24 | /// Gets the opcode map. 25 | /// 26 | public static Func[] OpcodeMap => s_OpcodeMap; 27 | 28 | #endregion 29 | 30 | #region Public Methods 31 | 32 | /// 33 | /// Fills the opcode map. 34 | /// 35 | public static void FillTable() 36 | { 37 | s_OpcodeMap[0] = Unhandled; 38 | s_OpcodeMap[Opcode.General.PING] = Ping; 39 | s_OpcodeMap[Opcode.General.IDENTITY] = Identity; 40 | s_OpcodeMap[Opcode.Gateway.Request.PATCH] = Patch; 41 | s_OpcodeMap[Opcode.Gateway.Request.SERVERLIST] = ServerList; 42 | s_OpcodeMap[Opcode.Gateway.Request.LOGIN] = Login; 43 | s_OpcodeMap[Opcode.Gateway.Request.LAUNCHER] = Launcher; 44 | } 45 | 46 | #endregion 47 | 48 | #region Private Methods 49 | 50 | private static bool Unhandled(ClientContext Me, Packet packet) 51 | { 52 | Console.WriteLine("Unhandled msg 0x{0:X4}", packet.Opcode); 53 | #if DEBUG 54 | return true; 55 | #endif 56 | return false; 57 | } 58 | 59 | private static bool Ping(ClientContext Me, Packet packet) 60 | { 61 | return true; 62 | } 63 | 64 | private static bool Identity(ClientContext Me, Packet packet) 65 | { 66 | if (packet.ReadAscii() == "SR_Client") 67 | { 68 | Packet resp = new Packet(Opcode.General.IDENTITY); 69 | resp.WriteAscii("GatewayServer"); 70 | resp.WriteByte(0); 71 | Me.SocketContext.Send(resp); 72 | 73 | return true; 74 | } 75 | 76 | return false; 77 | } 78 | 79 | private static bool Patch(ClientContext Me, Packet packet) 80 | { 81 | bool ret = true; 82 | 83 | byte locale = packet.ReadByte(); 84 | string identity_name = packet.ReadAscii(); 85 | uint version = packet.ReadUInt32(); 86 | 87 | Packet seed1 = new Packet(Opcode.General.SEED_1, false, true, new byte[] { 0x01, 0x00, 0x01, 0x47, 0x01, 0x05, 0x00, 0x00, 0x00, 0x02 }); 88 | Packet seed2 = new Packet(Opcode.General.SEED_2, false, true, new byte[] { 0x03, 0x00, 0x02, 0x00, 0x02 }); 89 | 90 | Me.SocketContext.EnqueuePacket(seed1); 91 | Me.SocketContext.EnqueuePacket(seed2); 92 | 93 | if (identity_name == "SR_Client") 94 | { 95 | uint current_version = Data.Globals.GetConfigValue("CurrentVersion"); 96 | uint latest_version = Data.Globals.GetConfigValue("LatestVersion"); 97 | 98 | Packet resp = new Packet(Opcode.Gateway.Response.PATCH, false, true); 99 | 100 | if (version == current_version) //no patches 101 | resp.WriteByte(1); 102 | else 103 | { 104 | resp.WriteByte(2); 105 | 106 | if (version < latest_version) //too old client, cannot update 107 | resp.WriteByte(5); 108 | else if (version > current_version) //too new client ? its illegal operation ! 109 | { 110 | resp.WriteByte(1); 111 | ret = false; 112 | Console.WriteLine("Illegal operation ! Current Version: {0}, Requested: {1}", current_version, version); 113 | } 114 | else //send patches 115 | { 116 | resp.WriteByte(2); 117 | resp.WriteAscii(Data.Globals.GetConfigValue("DownloadServerIPAddress")); 118 | resp.WriteUInt32(Data.Globals.GetConfigValue("DownloadServerPort")); 119 | resp.WriteUInt32(current_version); 120 | foreach(var file in Services.Patch.Items) 121 | { 122 | resp.WriteByte(1); 123 | resp.WriteUInt32(file.ID); 124 | resp.WriteAscii(file.FileName); 125 | resp.WriteAscii(file.Path); 126 | resp.WriteUInt32(file.FileSize); 127 | resp.WriteByte(file.ToBePacked); 128 | } 129 | resp.WriteByte(0); 130 | } 131 | } 132 | 133 | Me.SocketContext.EnqueuePacket(resp); 134 | Me.SocketContext.ProcessSendQueue(); 135 | } 136 | else 137 | return false; 138 | 139 | if (ret) 140 | Me.PingTimer.Start(10000, 10000); 141 | 142 | return ret; 143 | } 144 | 145 | private static bool ServerList(ClientContext Me, Packet packet) 146 | { 147 | if (Environment.TickCount - Me.LastServerListTick >= 4000) 148 | { 149 | Packet resp = new Packet(Opcode.Gateway.Response.SERVERLIST); 150 | resp.WriteByte(1); 151 | resp.WriteByte(0x15); 152 | resp.WriteAscii("SRO_Global_TestBed"); 153 | resp.WriteByte(0); 154 | foreach(var shard in Services.Shard.Items) 155 | { 156 | resp.WriteUInt8(1); 157 | resp.WriteUInt16(shard.ID); 158 | resp.WriteAscii(shard.Name); 159 | resp.WriteUInt16(shard.CurrentUsers); 160 | resp.WriteUInt16(shard.MaxUsers); 161 | resp.WriteUInt8(shard.State); 162 | } 163 | resp.WriteByte(0); 164 | 165 | Me.SocketContext.Send(resp); 166 | return true; 167 | } 168 | 169 | //too much requests, disconnect the client 170 | return false; 171 | } 172 | 173 | #pragma warning disable 4014 174 | private static bool Login(ClientContext Me, Packet packet) 175 | { 176 | byte locale = packet.ReadByte(); 177 | string id = packet.ReadAscii(); 178 | string password = SCommon.Utility.MD5Hash(packet.ReadAscii(), true); 179 | ushort server = packet.ReadUInt16(); 180 | Data._wrongpass_item wrong; 181 | 182 | Packet resp = new Packet(Opcode.Gateway.Response.LOGIN); 183 | 184 | if (Services.Shard.Items.Exists(p => p.ID == server)) 185 | { 186 | var shard = Services.Shard.Items.FirstOrDefault(p => p.ID == server); 187 | resp.WriteByte(2); 188 | if (shard.State != 1) 189 | { 190 | resp.WriteByte(2); 191 | resp.WriteByte(2); 192 | } 193 | else if (shard.ContentID != locale) 194 | { 195 | resp.WriteByte(7); 196 | } 197 | else if (id.Contains('\'')) 198 | { 199 | resp.WriteByte(6); 200 | } 201 | else if (Data.Globals.WrongPasswordTries.ContainsKey(id) && (wrong = Data.Globals.WrongPasswordTries[id]).Tries >= Data.Globals.MAX_WRONG_PASSWORD) 202 | { 203 | if (Environment.TickCount - wrong.LastTick < 5 * 60 * 1000) 204 | { 205 | resp.WriteByte(1); 206 | resp.WriteInt32(wrong.Tries); 207 | resp.WriteInt32(Data.Globals.MAX_WRONG_PASSWORD); 208 | } 209 | else 210 | Data.Globals.WrongPasswordTries.Remove(id); 211 | } 212 | else 213 | { 214 | Me.ProcessLoginResult(shard, id, password); 215 | return true; 216 | } 217 | 218 | Me.SocketContext.Send(resp); 219 | } 220 | else 221 | return false; 222 | 223 | return true; 224 | } 225 | 226 | private static bool Launcher(ClientContext Me, Packet packet) 227 | { 228 | byte locale = packet.ReadByte(); 229 | byte written_news = 0; 230 | 231 | Packet resp = new Packet(Opcode.Gateway.Response.LAUNCHER, false, true); 232 | resp.WriteByte(0); //news count 233 | foreach(var news in Services.Launcher.Items) 234 | { 235 | if (news.ContentID == locale) 236 | { 237 | resp.WriteAscii(news.Subject); 238 | resp.WriteAscii(news.Article); 239 | resp.WriteUInt16(news.EditDate.Year); 240 | resp.WriteUInt16(news.EditDate.Month); 241 | resp.WriteUInt16(news.EditDate.Day); 242 | resp.WriteUInt16(news.EditDate.Hour); 243 | resp.WriteUInt16(news.EditDate.Minute); 244 | resp.WriteUInt16(news.EditDate.Second); 245 | resp.WriteUInt32(news.EditDate.Millisecond); 246 | 247 | written_news++; 248 | } 249 | } 250 | resp.ReWriteAt(0, written_news); 251 | 252 | Me.SocketContext.Send(resp); 253 | 254 | return true; 255 | } 256 | 257 | #endregion 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /GatewayServer/Program.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer 2 | { 3 | using System; 4 | using System.Threading; 5 | using System.Collections.Generic; 6 | 7 | using SCore; 8 | 9 | using SCommon; 10 | 11 | internal class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | #region Assert Debug Mode 16 | #if DEBUG 17 | Logging.Log()("Debug mode is active", LogLevel.Info); 18 | #endif 19 | #endregion 20 | 21 | #region Initialize Services 22 | 23 | TimerService.Initialize(); 24 | Logging.Log()("Timer service has initialized", LogLevel.Success); 25 | 26 | PacketProcessor.FillTable(); 27 | Logging.Log()("Packet Processor has initialized", LogLevel.Success); 28 | 29 | #endregion 30 | 31 | #region Connect to Database Services 32 | 33 | if (Data.Globals.ConnectGlobalDB()) 34 | Logging.Log()("Connected to global db", LogLevel.Notify); 35 | else 36 | Logging.Log()("Cannot connect to global db", LogLevel.Error); 37 | 38 | if (Data.Globals.ConnectAccountDB()) 39 | Logging.Log()("Connected to account db", LogLevel.Notify); 40 | else 41 | Logging.Log()("Cannot connect to account db", LogLevel.Error); 42 | 43 | //truncate the sessions 44 | Data.Globals.GlobalDB.ExecuteCommand("TRUNCATE TABLE _ActiveSessions"); 45 | 46 | #endregion 47 | 48 | #region Load Configs 49 | 50 | if (Data.Globals.LoadConfigTable()) 51 | Logging.Log()("Server config has loaded", LogLevel.Notify); 52 | else 53 | Logging.Log()("Cannot load server config", LogLevel.Error); 54 | 55 | Data.Globals.WrongPasswordTries = new Dictionary(); 56 | 57 | #endregion 58 | 59 | #region Start Service 60 | 61 | Data.Globals.GatewayService = new Gateway(Data.Globals.GetConfigValue("GatewayServerIPAddress"), Data.Globals.GetConfigValue("GatewayServerPort")); 62 | Data.Globals.GatewayService.UpdateServiceState(true); 63 | Logging.Log()("Gateway Service has started", LogLevel.Info); 64 | 65 | #endregion 66 | 67 | #region Start GC CollectorThread 68 | 69 | new Thread(new ThreadStart(() => 70 | { 71 | while (true) 72 | { 73 | GC.Collect(); 74 | Thread.Sleep(10000); 75 | } 76 | })).Start(); 77 | 78 | #endregion 79 | 80 | #region Console command helper 81 | 82 | while (true) 83 | { 84 | Console.Write("gateway@{0}:~# ", Data.Globals.GetConfigValue("GatewayServerIPAddress")); 85 | var commands = Console.ReadLine().ToLower().Split(' '); 86 | switch(commands[0]) 87 | { 88 | case "exit": 89 | Environment.Exit(0); 90 | break; 91 | case "clear": 92 | Console.Clear(); 93 | break; 94 | case "enablepacketlogging": 95 | Logging.EnablePacketLogging = Convert.ToBoolean(commands[1]); 96 | Logging.Log()(String.Format("Set EnablePacketLogging = {0}", Logging.EnablePacketLogging ? "TRUE" : "FALSE"), LogLevel.Success); 97 | break; 98 | case "connectioncount": 99 | Logging.Log()(String.Format("Current Active Connections Count is {0}", Data.Globals.GatewayService.ActiveConnectionCount), LogLevel.Info); 100 | break; 101 | } 102 | Thread.Sleep(1); 103 | } 104 | 105 | #endregion 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /GatewayServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GatewayServer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GatewayServer")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("422e556d-b2c7-4607-a485-3b1c6eed41eb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /GatewayServer/Services/Launcher.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer.Services 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | /// 7 | /// The launcher news item structure 8 | /// 9 | public struct _news_item 10 | { 11 | public uint ID; 12 | public byte ContentID; 13 | public string Subject; 14 | public string Article; 15 | public DateTime EditDate; 16 | } 17 | 18 | /// 19 | /// The launcher service class. 20 | /// 21 | public static class Launcher 22 | { 23 | #region Private Properties and Fields 24 | 25 | /// 26 | /// The launcher news items. 27 | /// 28 | private static List<_news_item> s_Items; 29 | 30 | #endregion 31 | 32 | #region Initializer Method 33 | 34 | public static void Initialize() 35 | { 36 | s_Items = new List<_news_item>(); 37 | using (var reader = Data.Globals.AccountDB.ExecuteReader("SELECT TOP 4 * FROM _Notice ORDER BY EditDate DESC")) 38 | { 39 | while(reader.Read()) 40 | { 41 | _news_item item = new _news_item 42 | { 43 | ID = (uint)(int)reader["ID"], 44 | ContentID = (byte)reader["ContentID"], 45 | Subject = (string)reader["Subject"], 46 | Article = (string)reader["Article"], 47 | EditDate = (DateTime)reader["EditDate"] 48 | }; 49 | 50 | s_Items.Add(item); 51 | } 52 | } 53 | } 54 | 55 | #endregion 56 | 57 | #region Public Properties and Fields 58 | 59 | /// 60 | /// Gets the launcher news item list 61 | /// 62 | public static List<_news_item> Items => s_Items; 63 | 64 | #endregion 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /GatewayServer/Services/Patch.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer.Services 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | /// 7 | /// The patch item structure 8 | /// 9 | public struct _patch_item 10 | { 11 | public uint ID; 12 | public uint Version; 13 | public uint ModuleID; 14 | public string FileName; 15 | public string Path; 16 | public uint FileSize; 17 | public byte FileType; 18 | public uint FileTypeVersion; 19 | public bool ToBePacked; 20 | public DateTime TimeModified; 21 | public bool IsValid; 22 | } 23 | 24 | /// 25 | /// The patch service class 26 | /// 27 | public static class Patch 28 | { 29 | #region Private Properties and Fields 30 | 31 | /// 32 | /// The patch file items. 33 | /// 34 | private static List<_patch_item> s_Items; 35 | 36 | #endregion 37 | 38 | #region Initializer Method 39 | 40 | public static void Initialize() 41 | { 42 | s_Items = new List<_patch_item>(); 43 | using (var reader = Data.Globals.AccountDB.ExecuteReader("SELECT * FROM _ModuleVersionFile WHERE nVersion > {0} AND nValid = 1 AND nModuleID = '{1}' ORDER BY nID", Data.Globals.GetConfigValue("LatestVersion"), 9)) 44 | { 45 | while(reader.Read()) 46 | { 47 | _patch_item item = new _patch_item 48 | { 49 | ID = (uint)reader["nID"], 50 | Version = (uint)reader["nVersion"], 51 | ModuleID = (uint)reader["nModuleID"], 52 | FileName = (string)reader["szFilename"], 53 | Path = ((string)reader["szPath"]).Replace(".", ""), 54 | FileSize = (uint)reader["nFileSize"], 55 | FileType = (byte)reader["nFileType"], 56 | FileTypeVersion = (uint)reader["nFileTypeVersion"], 57 | ToBePacked = Convert.ToBoolean(reader["nToBePacked"]), 58 | TimeModified = (DateTime)reader["timeModified"], 59 | IsValid = Convert.ToBoolean(reader["nValid"]) 60 | }; 61 | 62 | s_Items.Add(item); 63 | } 64 | } 65 | } 66 | 67 | #endregion 68 | 69 | #region Public Properties and Fields 70 | 71 | /// 72 | /// Gets the patch file items list. 73 | /// 74 | public static List<_patch_item> Items => s_Items; 75 | 76 | #endregion 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /GatewayServer/Services/Session.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer.Services 2 | { 3 | using System.Threading; 4 | 5 | public static class Session 6 | { 7 | #region Private Properties and Fields 8 | 9 | /// 10 | /// Stores the last generated session id 11 | /// 12 | private static volatile int s_LastSessionID; 13 | 14 | #endregion 15 | 16 | #region Initializer Methods 17 | 18 | public static void Initialize() 19 | { 20 | s_LastSessionID = int.MinValue; 21 | } 22 | 23 | #endregion 24 | 25 | #region Public Methods 26 | 27 | /// 28 | /// Generates the new session id 29 | /// 30 | /// 31 | public static int Generate() 32 | { 33 | if (PreventOverflows()) 34 | return int.MinValue; 35 | 36 | return Interlocked.Increment(ref s_LastSessionID); 37 | } 38 | 39 | #endregion 40 | 41 | #region Private Methods 42 | 43 | /// 44 | /// Checks for the overflows 45 | /// 46 | /// 47 | private static bool PreventOverflows() 48 | { 49 | return Interlocked.CompareExchange(ref s_LastSessionID, int.MinValue, int.MaxValue) == int.MaxValue; 50 | } 51 | 52 | #endregion 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /GatewayServer/Services/Shard.cs: -------------------------------------------------------------------------------- 1 | namespace GatewayServer.Services 2 | { 3 | using System.Collections.Generic; 4 | 5 | /// 6 | /// The shard item structure 7 | /// 8 | public struct _shard_item 9 | { 10 | public int ID; 11 | public string Name; 12 | public byte ContentID; 13 | public ushort CurrentUsers; 14 | public ushort MaxUsers; 15 | public byte State; 16 | public object m_lock; 17 | } 18 | 19 | 20 | /// 21 | /// The shard service class 22 | /// 23 | public static class Shard 24 | { 25 | #region Private Properties and Fields 26 | 27 | /// 28 | /// The shard list. 29 | /// 30 | private static List<_shard_item> s_Items; 31 | 32 | #endregion 33 | 34 | #region Initializer Method 35 | 36 | public static void Initialize() 37 | { 38 | s_Items = new List<_shard_item>(); 39 | using (var reader = Data.Globals.AccountDB.ExecuteReader("SELECT * FROM _Shard")) 40 | { 41 | while(reader.Read()) 42 | { 43 | _shard_item item = new _shard_item 44 | { 45 | ID = (int)reader["ID"], 46 | Name = (string)reader["Name"], 47 | ContentID = (byte)reader["ContentID"], 48 | CurrentUsers = 0, 49 | MaxUsers = (ushort)(short)reader["MaxUsers"], 50 | State = (byte)reader["State"], 51 | m_lock = new object() 52 | }; 53 | 54 | s_Items.Add(item); 55 | } 56 | } 57 | } 58 | 59 | #endregion 60 | 61 | #region Public Properties and Fields 62 | 63 | /// 64 | /// Gets the shard list 65 | /// 66 | public static List<_shard_item> Items => s_Items; 67 | 68 | #endregion 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SilkroadProject 2 | Silkroad Online Emulator for Open Beta Client 3 | 4 | ### Requirements 5 | - Visual Studio 2015 6 | - Microsoft SQL Server 2008 or above 7 | - Asio 1.10.6 for SCore (our AsyncTimer uses asio) 8 | 9 | ### How To Setup Server 10 | - Restore database dumps 11 | - Edit _ServerConfig table in SR_Global 12 | - Extract your data.pk2 to data/ folder 13 | - Edit GatewayServer/Data/Globals.cs and SR_GameServer/Data/Globals.cs for connection strings 14 | - Compile project with visual studio and run 15 | 16 | ### How To Setup Client 17 | - Open Media.pk2 with pk2 extractor and export GATEIP.txt 18 | - Open GATEIP.txt with a hex editor and edit ip address (fill with zeroes remaining) 19 | - Open client with IP Input change ip address again (aka change DIVISIONINFO.txt) 20 | 21 | ### How To Contribute Project 22 | - You can make pull requests to contribute project. 23 | 1. Your code must match projects design. 24 | 2. Prevent deadlocks when interacting another client. 25 | 3. Use Interlocked operations when accessing volatile variables 26 | 4. Use async Task for heavy operations 27 | 5. Test your code carefully. 28 | 29 | ### Links for projects 30 | Description | Link 31 | ------------ | ------------- 32 | Database Dumps | https://mega.nz/#!UAIRWJTK!66r4XsTFAbfazIP5CvrYqQYHGyuXpLWyaH36cNWVRRc 33 | Client | https://mega.nz/#!sRBiBaLY!RQnCfHfr8HfBIRxRJctf0-5_MVC8W8OXd51pH558mm8 34 | Client Dll (Aqua.dll) source | https://mega.nz/#!MAZQUZpY!4frt9k4PDnDVFvrV02KBbx4K0xCcnZ2aUZ5W4uSfeTo 35 | -------------------------------------------------------------------------------- /SCommon/Database/MSSQL.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon.Database 2 | { 3 | using System; 4 | using System.Data.SqlClient; 5 | using System.Threading.Tasks; 6 | 7 | public class MSSQL : IDisposable 8 | { 9 | #region Private Properties and Fields 10 | 11 | /// 12 | /// The handle 13 | /// 14 | private SqlConnection m_Connection; 15 | 16 | #endregion 17 | 18 | #region Constructors & Destructors 19 | 20 | public MSSQL(string connectionStr) 21 | { 22 | m_Connection = new SqlConnection(connectionStr); 23 | m_Connection.Open(); 24 | } 25 | 26 | public MSSQL(string Server, string DBName, string UserID, string Password, bool MultipleActiveResultSets) 27 | : this(String.Format("Server={0};Database={1};User Id={2};Password={3};MultipleActiveResultSets={4}", Server, DBName, UserID, Password, MultipleActiveResultSets)) 28 | { 29 | 30 | } 31 | 32 | public void Dispose() 33 | { 34 | m_Connection.Close(); 35 | m_Connection.Dispose(); 36 | } 37 | 38 | #endregion 39 | 40 | #region Public Methods 41 | 42 | /// 43 | /// Executes the query. 44 | /// 45 | /// The query string. 46 | /// The args. 47 | /// The number of affected rows by query execution. 48 | public int ExecuteCommand(string SQLCommand, params object[] args) 49 | { 50 | SQLCommand = ReplaceArgs(SQLCommand, args); 51 | using (var cmd = new SqlCommand(SQLCommand, m_Connection)) 52 | return cmd.ExecuteNonQuery(); 53 | } 54 | 55 | /// 56 | /// Executes the query as async. 57 | /// 58 | /// The query string. 59 | /// The args. 60 | /// The number of affected rows by query execution. 61 | public Task ExecuteCommandAsync(string SQLCommand, params object[] args) 62 | { 63 | SQLCommand = ReplaceArgs(SQLCommand, args); 64 | using (var cmd = new SqlCommand(SQLCommand, m_Connection)) 65 | return cmd.ExecuteNonQueryAsync(); 66 | } 67 | 68 | /// 69 | /// Executes query and returns the query result reader 70 | /// 71 | /// The query string. 72 | /// The args. 73 | /// returned by the query execution. 74 | public SqlDataReader ExecuteReader(string SQLCommand, params object[] args) 75 | { 76 | try 77 | { 78 | SQLCommand = ReplaceArgs(SQLCommand, args); 79 | using (var cmd = new SqlCommand(SQLCommand, m_Connection)) 80 | return cmd.ExecuteReader(); 81 | } 82 | catch { return null; } 83 | } 84 | 85 | /// 86 | /// Executes query as async and returns the query result reader 87 | /// 88 | /// The query string. 89 | /// The args. 90 | /// returned by the query execution. 91 | public Task ExecuteReaderAsync(string SQLCommand, params object[] args) 92 | { 93 | try 94 | { 95 | SQLCommand = ReplaceArgs(SQLCommand, args); 96 | using (var cmd = new SqlCommand(SQLCommand, m_Connection)) 97 | return cmd.ExecuteReaderAsync(); 98 | } 99 | catch { return null; } 100 | } 101 | 102 | /// 103 | /// Executes query and gets the result of query (row 0 column 0) 104 | /// 105 | /// The return type. 106 | /// The query string. 107 | /// The args. 108 | /// Data returned by query 109 | public T Result(string SQLCommand, params object[] args) 110 | { 111 | try 112 | { 113 | SQLCommand = ReplaceArgs(SQLCommand, args); 114 | using (var cmd = new SqlCommand(SQLCommand, m_Connection)) 115 | return (T)cmd.ExecuteScalar(); 116 | } 117 | catch { return default(T); } 118 | } 119 | 120 | /// 121 | /// Executes query as async and gets the result of query (row 0 column 0) 122 | /// 123 | /// The return type. 124 | /// The query string. 125 | /// The args. 126 | /// Data returned by query 127 | public Task ResultAsync(string SQLCommand, params object[] args) 128 | { 129 | try 130 | { 131 | SQLCommand = ReplaceArgs(SQLCommand, args); 132 | using (var cmd = new SqlCommand(SQLCommand, m_Connection)) 133 | return cmd.ExecuteScalarAsync(); 134 | } 135 | catch { return null; } 136 | } 137 | 138 | /// 139 | /// Returns the count of rows returned by query 140 | /// 141 | /// the query string 142 | /// the args 143 | /// The number of rows returned by query 144 | public int Count(string SQLCommand, params object[] args) 145 | { 146 | try 147 | { 148 | var tmp = ExecuteReader(SQLCommand, args); 149 | int cnt = 0; 150 | while (tmp.Read()) 151 | cnt++; 152 | return cnt; 153 | } 154 | catch { return 0; } 155 | } 156 | 157 | #endregion 158 | 159 | #region Private Methods 160 | 161 | /// 162 | /// Replaces the possible injection args 163 | /// 164 | /// the query string. 165 | /// the args 166 | /// The true query string 167 | private string ReplaceArgs(string SQLCommand, params object[] args) 168 | { 169 | for (int i = 0; i < args.Length; i++) args[i] = args[i].ToString().Replace("'", "''"); 170 | #if DEBUG 171 | Logging.Log()(String.Format(SQLCommand, args), LogLevel.Warning); 172 | #endif 173 | return String.Format(SQLCommand, args); 174 | } 175 | 176 | #endregion 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /SCommon/Enumerations.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon 2 | { 3 | /// 4 | /// The SecurityFlags enum used for class 5 | /// 6 | public enum SecurityFlags 7 | { 8 | None = 0, 9 | Handshake = 1, 10 | Blowfish = 2, 11 | SecurityBytes = 4, 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SCommon/Geometry.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon 2 | { 3 | using System; 4 | 5 | using SharpDX; 6 | 7 | public static class Geometry 8 | { 9 | public static Vector2 ToVector2(this Vector3 v) 10 | { 11 | return new Vector2(v.X, v.Z); 12 | } 13 | 14 | public static Vector3 ToVector3(this Vector2 v) 15 | { 16 | return new Vector3(v.X, 0f, v.Y); //TO DO: navmesh height for y position 17 | } 18 | 19 | public static Vector3 ToVector3(this Vector2 v, float y) 20 | { 21 | return new Vector3(v.X, y, v.Y); 22 | } 23 | 24 | public static Vector2 Normalized(this Vector2 v) 25 | { 26 | v.Normalize(); 27 | return v; 28 | } 29 | 30 | public static Vector3 Normalized(this Vector3 v) 31 | { 32 | v.Normalize(); 33 | return v; 34 | } 35 | 36 | public static Vector2 Perpendicular(this Vector2 v) 37 | { 38 | return new Vector2(-v.Y, v.X); 39 | } 40 | 41 | public static Vector2 Rotated(this Vector2 v, float angle) 42 | { 43 | var c = Math.Cos(angle); 44 | var s = Math.Sin(angle); 45 | 46 | return new Vector2((float)(v.X * c - v.Y * s), (float)(v.Y * c + v.X * s)); 47 | } 48 | 49 | public static float CrossProduct(this Vector2 self, Vector2 other) 50 | { 51 | return other.Y * self.X - other.X * self.Y; 52 | } 53 | 54 | public static float RadianToDegree(double angle) 55 | { 56 | return (float)(angle * (180.0 / Math.PI)); 57 | } 58 | 59 | 60 | public static float DegreeToRadian(double angle) 61 | { 62 | return (float)(Math.PI * angle / 180.0); 63 | } 64 | 65 | public static bool Close(float a, float b, float eps) 66 | { 67 | if (Math.Abs(eps) < float.Epsilon) 68 | { 69 | eps = (float)1e-9; 70 | } 71 | return Math.Abs(a - b) <= eps; 72 | } 73 | 74 | public static float Polar(this Vector2 v1) 75 | { 76 | if (Close(v1.X, 0, 0)) 77 | { 78 | if (v1.Y > 0) 79 | { 80 | return 90; 81 | } 82 | return v1.Y < 0 ? 270 : 0; 83 | } 84 | 85 | var theta = RadianToDegree(Math.Atan((v1.Y) / v1.X)); 86 | if (v1.X < 0) 87 | { 88 | theta = theta + 180; 89 | } 90 | if (theta < 0) 91 | { 92 | theta = theta + 360; 93 | } 94 | return theta; 95 | } 96 | 97 | 98 | public static float AngleBetween(this Vector2 p1, Vector2 p2) 99 | { 100 | var theta = p1.Polar() - p2.Polar(); 101 | if (theta < 0) 102 | { 103 | theta = theta + 360; 104 | } 105 | if (theta > 180) 106 | { 107 | theta = 360 - theta; 108 | } 109 | return theta; 110 | } 111 | 112 | 113 | public static Vector2 RotateAroundPoint(this Vector2 rotated, Vector2 around, float angle) 114 | { 115 | var sin = Math.Sin(angle); 116 | var cos = Math.Cos(angle); 117 | 118 | var x = cos * (rotated.X - around.X) - sin * (rotated.Y - around.Y) + around.X; 119 | var y = sin * (rotated.X - around.X) + cos * (rotated.Y - around.Y) + around.Y; 120 | 121 | return new Vector2((float)x, (float)y); 122 | } 123 | 124 | public static float Distance(this Vector2 from, Vector2 to, bool squared = false) 125 | { 126 | if (squared) 127 | return Vector2.DistanceSquared(from, to); 128 | 129 | return Vector2.Distance(from, to); 130 | } 131 | 132 | public static float Distance(this Vector3 from, Vector3 to, bool squared = false) 133 | { 134 | if (squared) 135 | return Vector3.DistanceSquared(from, to); 136 | 137 | return Vector3.Distance(from, to); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /SCommon/Logging.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon 2 | { 3 | using System; 4 | 5 | public enum LogType 6 | { 7 | Console, 8 | File, 9 | Packet, 10 | } 11 | 12 | public enum LogLevel 13 | { 14 | Notify, 15 | Warning, 16 | Error, 17 | Info, 18 | Success, 19 | } 20 | 21 | 22 | public static class Logging 23 | { 24 | #region Public Properties and Fields 25 | 26 | public delegate void LogDelegateT(string arg1, LogLevel arg2 = LogLevel.Notify); 27 | 28 | public static bool EnablePacketLogging { get; set; } 29 | 30 | #endregion 31 | 32 | #region Public Methods 33 | 34 | public static LogDelegateT Log(LogType type = LogType.Console) 35 | { 36 | switch(type) 37 | { 38 | case LogType.Console: 39 | return LogToConsole; 40 | case LogType.File: 41 | return LogToFile; 42 | case LogType.Packet: 43 | return LogPacket; 44 | } 45 | return null; 46 | } 47 | 48 | #endregion 49 | 50 | #region Private Methods 51 | 52 | private static void LogToConsole(string str, LogLevel level) 53 | { 54 | var backupcolor = Console.ForegroundColor; 55 | Console.ForegroundColor = GetConsoleColor(level); 56 | Console.WriteLine("[{0}]{1}", level, str); 57 | Console.ForegroundColor = backupcolor; 58 | } 59 | 60 | private static void LogToFile(string str, LogLevel level) 61 | { 62 | //log to file 63 | } 64 | 65 | private static void LogPacket(string str, LogLevel level = LogLevel.Notify) 66 | { 67 | //if not enabled 68 | if (!EnablePacketLogging) 69 | return; 70 | 71 | //for level if notify/info to console if error/warning to file & console etc. 72 | //for now not supported only log to console 73 | Console.WriteLine(str); 74 | } 75 | 76 | private static ConsoleColor GetConsoleColor(LogLevel level) 77 | { 78 | switch(level) 79 | { 80 | case LogLevel.Warning: 81 | return ConsoleColor.DarkMagenta; 82 | case LogLevel.Error: 83 | return ConsoleColor.Red; 84 | case LogLevel.Info: 85 | return ConsoleColor.Cyan; 86 | case LogLevel.Success: 87 | return ConsoleColor.Green; 88 | case LogLevel.Notify: 89 | default: 90 | return ConsoleColor.Gray; 91 | } 92 | } 93 | 94 | #endregion 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /SCommon/Networking/TCPServer.cs: -------------------------------------------------------------------------------- 1 | #define SOCKETTHREADPOOL 2 | namespace SCommon.Networking 3 | { 4 | using System; 5 | using System.Net; 6 | using System.Net.Sockets; 7 | using System.Threading; 8 | 9 | using SCommon; 10 | 11 | public class TCPServer 12 | { 13 | #region Private Properties and Fields 14 | 15 | /// 16 | /// The TCP server socket. 17 | /// 18 | private Socket m_Socket; 19 | 20 | /// 21 | /// The connection allowed field. 22 | /// 23 | private bool m_blConnectionAllowed; 24 | 25 | /// 26 | /// The security flags field for class 27 | /// 28 | private SecurityFlags m_SecurityFlags; 29 | 30 | /// 31 | /// The pool for class 32 | /// 33 | private ObjectPool m_SocketContextPool; 34 | 35 | #endregion 36 | 37 | #region Public Properties and Fields 38 | 39 | /// 40 | /// Stores the current connection count 41 | /// 42 | public volatile int m_ConnectionCount; 43 | 44 | /// 45 | /// Gets the SocketContextPool. 46 | /// 47 | public ObjectPool SocketContextPool => m_SocketContextPool; 48 | 49 | /// 50 | /// The event fired when new connection has arrived. 51 | /// 52 | public static EventHandler OnNewConnection; 53 | 54 | #endregion 55 | 56 | #region Constructors & Destructors 57 | 58 | public TCPServer(string ip, int port, SecurityFlags flags) 59 | { 60 | m_blConnectionAllowed = false; 61 | m_SecurityFlags = flags; 62 | m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 63 | m_SocketContextPool = new ObjectPool(() => new SocketContext(), () => m_SocketContextPool.Count > 200); 64 | try 65 | { 66 | IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ip), port); 67 | m_Socket.Bind(endPoint); 68 | m_Socket.Listen(1000); 69 | } 70 | catch (SocketException) 71 | { 72 | Console.WriteLine("Cannot listen socket ({0}:{1})", ip, port); 73 | } 74 | } 75 | 76 | #endregion 77 | 78 | #region Public Methods 79 | 80 | /// 81 | /// Begins accept sockets to the TCP Server. 82 | /// 83 | public void StartService(int acceptThreadCount = 8) 84 | { 85 | for(int i = 0; i < acceptThreadCount; i++) 86 | m_Socket.BeginAccept(AsyncAccept, i); 87 | 88 | m_blConnectionAllowed = true; 89 | } 90 | 91 | #endregion 92 | 93 | #region Private Methods 94 | 95 | /// 96 | /// The event fired when the new connection arrived 97 | /// 98 | /// The result as 99 | private void AsyncAccept(IAsyncResult res) 100 | { 101 | try 102 | { 103 | //extract the pending socket 104 | Socket pending = m_Socket.EndAccept(res); 105 | 106 | if (pending != null) //if socket is valid 107 | { 108 | if (!m_blConnectionAllowed || !pending.Connected) //if it isnt allowed to connect server or pending client has disconnected 109 | { 110 | pending.Disconnect(true); 111 | return; 112 | } 113 | 114 | //if there is nothing wrong with new connection; 115 | //notify the event subscribers so we can create a real context between socket & user 116 | FireOnNewConnection(pending); 117 | } 118 | } 119 | catch(Exception) 120 | { 121 | Console.WriteLine("cannot accept socket"); 122 | } 123 | finally 124 | { 125 | //begin async accepting again 126 | m_Socket.BeginAccept(AsyncAccept, null); 127 | } 128 | } 129 | 130 | /// 131 | /// Fires the OnNewConnectionEvent 132 | /// 133 | /// The client socket. 134 | private void FireOnNewConnection(Socket client) 135 | { 136 | //build context 137 | SocketContext context = m_SocketContextPool.GetObject(); 138 | context.SetSocket(client); 139 | context.SetOwner(this); 140 | context.SetSecurity(m_SecurityFlags); 141 | 142 | //notify the event subscribers 143 | OnNewConnection(this, context); 144 | 145 | //begin async receiving from context's socket 146 | context.Begin(); 147 | 148 | Interlocked.Increment(ref m_ConnectionCount); 149 | } 150 | 151 | #endregion 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /SCommon/ObjectPool.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon 2 | { 3 | using System; 4 | using System.Collections.Concurrent; 5 | 6 | public class ObjectPool where T : IDisposable 7 | { 8 | private ConcurrentBag _objects; 9 | private Func _objectGenerator; 10 | private Func _disposeCondition; 11 | 12 | public int Count => _objects.Count; 13 | 14 | public ObjectPool(Func objectGenerator, Func disposeCondition) 15 | { 16 | if (objectGenerator == null) throw new ArgumentNullException("objectGenerator"); 17 | _objects = new ConcurrentBag(); 18 | _objectGenerator = objectGenerator; 19 | _disposeCondition = disposeCondition; 20 | } 21 | 22 | public T GetObject() 23 | { 24 | T item; 25 | if (_objects.TryTake(out item)) return item; 26 | return _objectGenerator(); 27 | } 28 | 29 | public void PutObject(T item) 30 | { 31 | if (_disposeCondition()) 32 | item.Dispose(); 33 | else 34 | _objects.Add(item); 35 | } 36 | 37 | public void Reserve(int num) 38 | { 39 | for (int i = 0; i < num; i++) 40 | _objects.Add(_objectGenerator()); 41 | } 42 | 43 | public void Shrink(int fitSize) 44 | { 45 | if (_objects.Count > fitSize) 46 | { 47 | for (int i = 0; i < _objects.Count - fitSize; i++) 48 | { 49 | T item; 50 | if(_objects.TryTake(out item)) 51 | item.Dispose(); 52 | } 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /SCommon/Opcode.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon.Opcode 2 | { 3 | public struct General 4 | { 5 | public const ushort HANDSHAKE = 0x5000; 6 | public const ushort HANDSHAKE_ACCEPT = 0x9000; 7 | public const ushort IDENTITY = 0x2001; 8 | public const ushort SEED_1 = 0x2005; 9 | public const ushort SEED_2 = 0x6005; 10 | public const ushort PING = 0x2002; 11 | } 12 | 13 | public struct Gateway 14 | { 15 | public const ushort CHECKVERSION = 0x6000; 16 | 17 | public struct Request 18 | { 19 | public const ushort PATCH = 0x6100; 20 | public const ushort LAUNCHER = 0x6104; 21 | public const ushort SERVERLIST = 0x6101; 22 | public const ushort LOGIN = 0x6102; 23 | } 24 | 25 | public struct Response 26 | { 27 | public const ushort PATCH = 0xA100; 28 | public const ushort LAUNCHER = 0xA104; 29 | public const ushort SERVERLIST = 0xA101; 30 | public const ushort LOGIN = 0xA102; 31 | } 32 | } 33 | 34 | public struct Download 35 | { 36 | public struct Request 37 | { 38 | public const ushort FILE = 0x6004; 39 | } 40 | 41 | public struct Response 42 | { 43 | public const ushort FILE = 0x1001; 44 | public const ushort SUCCEEDED = 0xA004; 45 | } 46 | } 47 | 48 | public struct Agent 49 | { 50 | public struct Request 51 | { 52 | public const ushort CONNECTION = 0x6103; 53 | public const ushort INGAME = 0x7001; 54 | public const ushort CHARACTER_SCREEN = 0x7007; 55 | public const ushort CHARACTER_SELECT = 0x7001; 56 | public const ushort CHARACTER_ENTERWORLD = 0x3012; 57 | public const ushort GAMEOBJECT_MOVEMENT = 0x7021; 58 | public const ushort GAMEOBJECT_STOP = 0x7023; 59 | public const ushort GAMEOBJECT_SET_ANGLE = 0x7024; 60 | public const ushort SELECT_GAMEOBJECT = 0x7045; 61 | public const ushort TELEPORT = 0x705A; 62 | public const ushort TELEPORT_LOADING = 0x34B6; 63 | public const ushort CHAT = 0x7025; 64 | public const ushort INVENTORY_OPERATION = 0x7034; 65 | public const ushort SHOP_OPEN = 0x7046; 66 | public const ushort SHOP_CLOSE = 0x704B; 67 | public const ushort TELEPORT_APPOINT = 0x7059; 68 | public const ushort GAMEGUIDE = 0x70EA; 69 | public const ushort GM_COMMAND = 0x7010; 70 | } 71 | 72 | public struct Response 73 | { 74 | public const ushort CONNECTION = 0xA103; 75 | public const ushort INGAME = 0xB001; 76 | public const ushort CHARACTER_SCREEN = 0xB007; 77 | public const ushort CHARACTER_SELECT = 0xB001; 78 | public const ushort GAMEOBJECT_SET_ANGLE = 0xB024; 79 | public const ushort SELECT_GAMEOBJECT = 0xB045; 80 | public const ushort CHAT = 0xB025; 81 | public const ushort INVENTORY_OPERATION = 0xB034; 82 | public const ushort UPDATE_INVENTORY_SLOT = 0xB04C; 83 | public const ushort SHOP_OPEN = 0xB046; 84 | public const ushort SHOP_CLOSE = 0xB04B; 85 | public const ushort TELEPORT_APPOINT = 0xB059; 86 | public const ushort GAMEGUIDE = 0xB0EA; 87 | } 88 | 89 | public const ushort CHARACTER_LOAD_START = 0x34A5; 90 | public const ushort CHARACTER_LOAD_DATA = 0x3013; 91 | public const ushort CHARACTER_LOAD_END = 0x34A6; 92 | public const ushort CHARACTER_CELESTICAL_POS = 0x3020; 93 | public const ushort CHARACTER_STAT = 0x303D; 94 | public const ushort CHARACTER_ENTERWORLD = 0x3077; 95 | public const ushort GAMEOBJECT_SPAWN_SINGLE = 0x3015; 96 | public const ushort GAMEOBJECT_DESPAWN_SINGLE = 0x3016; 97 | public const ushort GAMEOBJECT_SPAWN_GROUP_START = 0x3017; 98 | public const ushort GAMEOBJECT_SPAWN_GROUP_DATA = 0x3019; 99 | public const ushort GAMEOBJECT_SPAWN_GROUP_END = 0x3018; 100 | public const ushort GAMEOBJECT_WARP = 0xB023; 101 | public const ushort GAMEOBJECT_MOVEMENT = 0xB021; 102 | public const ushort GAMEOBJECT_EMOTE = 0x3091; 103 | public const ushort TELEPORT_SCREEN = 0x3055; 104 | public const ushort SEND_MESSAGE = 0x3026; 105 | public const ushort EQUIP_ITEM = 0x3038; 106 | public const ushort UNEQUIP_ITEM = 0x3039; 107 | public const ushort DROP_ITEM = 0x304D; 108 | public const ushort UPDATE_PC = 0x304E; 109 | } 110 | } -------------------------------------------------------------------------------- /SCommon/PooledList.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon 2 | { 3 | /* 4 | PooledList provides Thread-Safe non-circular doubly linked list 5 | Created by Shine for SilkroadProject 6 | */ 7 | using System; 8 | using System.Threading; 9 | using System.Collections.Generic; 10 | using System.Collections.Concurrent; 11 | 12 | public class node where T : class 13 | { 14 | public T value_; 15 | public node next_; 16 | public node prev_; 17 | public PooledList list_; 18 | public bool queueable_; 19 | public object locker_; 20 | 21 | public node() 22 | { 23 | locker_ = new object(); 24 | } 25 | } 26 | 27 | /// 28 | /// Thread-Safe non-circular doubly linked list 29 | /// 30 | /// Item type which will be stored in the list 31 | public class PooledList : IEnumerable where T : class 32 | { 33 | #region Public Properties and Fields 34 | 35 | /// 36 | /// The queue stores the freed nodes 37 | /// 38 | private ConcurrentQueue> m_queue; 39 | 40 | /// 41 | /// The head, always value = null its a start point for iterations 42 | /// 43 | private node m_head; 44 | 45 | /// 46 | /// The tail, last node of the cycle 47 | /// 48 | private node m_tail; 49 | 50 | /// 51 | /// The count of active nodes (which count of nodes that node.value != null) 52 | /// 53 | private long m_count; 54 | 55 | /// 56 | /// The count of allocated nodes (which count of nodes that both node.value != null & node.value == null) 57 | /// 58 | private long m_nodes; 59 | 60 | /// 61 | /// Gets the head 62 | /// 63 | public node Head => m_head; 64 | 65 | /// 66 | /// Gets the tail 67 | /// 68 | public node Tail => m_tail; 69 | 70 | /// 71 | /// Gets the if list is empty 72 | /// 73 | public bool IsEmpty => Interlocked.Read(ref m_count) == 0; 74 | 75 | /// 76 | /// GEts the element count in list 77 | /// 78 | public long Count => Interlocked.Read(ref m_count); 79 | 80 | #endregion 81 | 82 | #region Constructors and Destructors 83 | 84 | public PooledList() 85 | { 86 | m_queue = new ConcurrentQueue>(); 87 | m_head = new node() { list_ = this }; 88 | m_tail = new node() { list_ = this }; 89 | m_head.next_ = m_tail; 90 | m_count = 0; 91 | m_nodes = 2; //head + tail 92 | } 93 | 94 | #endregion 95 | 96 | #region Public Methods 97 | 98 | public node push(T item) 99 | { 100 | node node; 101 | if (m_queue.TryDequeue(out node)) //if we have freed node in the queue 102 | { 103 | //change value of freed node 104 | //we dont need change next/prev because this node is part of chain already 105 | lock (node.locker_) 106 | node.value_ = item; 107 | 108 | //increase the count 109 | Interlocked.Increment(ref m_count); 110 | 111 | return node; 112 | } 113 | else 114 | { 115 | //lock the tail 116 | lock (m_tail.locker_) 117 | { 118 | if (m_tail.value_ == null) //if tail freed while we waiting or already free 119 | { 120 | //only change the value of tail 121 | m_tail.value_ = item; 122 | 123 | //increase the count 124 | Interlocked.Increment(ref m_count); 125 | 126 | return m_tail; 127 | } 128 | else 129 | { 130 | //if the tail is okay allocate the new node 131 | //as the tail (next = null) 132 | node = new node() { list_ = this, queueable_ = true }; 133 | node.value_ = item; 134 | node.next_ = null; 135 | 136 | //push allocated node to back so we must 137 | //set node->prev = current_tail, current_tail = node 138 | //also we must set current_tail->next = node before setting current_tail = node 139 | //to ensure the cycle 140 | node.prev_ = m_tail; 141 | m_tail.next_ = node; 142 | m_tail = node; 143 | 144 | //increase the count 145 | Interlocked.Increment(ref m_count); 146 | //increse the node count 147 | Interlocked.Increment(ref m_nodes); 148 | 149 | return m_tail; 150 | } 151 | } 152 | } 153 | } 154 | 155 | public bool pop(node node) 156 | { 157 | ValidateNode(node); 158 | 159 | //lock the node and free node with 160 | //setting value as null 161 | lock (node.locker_) 162 | { 163 | if (node.value_ == null) //already freed 164 | return false; 165 | 166 | node.value_ = null; 167 | } 168 | 169 | //if node is queueable (if it isnt head or tail) 170 | //queue the freed node so we can dequeue next time for use 171 | if (node.queueable_) 172 | m_queue.Enqueue(node); 173 | 174 | Interlocked.Decrement(ref m_count); 175 | 176 | return true; 177 | } 178 | 179 | public node first() 180 | { 181 | return this.Head.next_; 182 | } 183 | 184 | public void ForEach(Action action) 185 | { 186 | node node = m_head.next_; 187 | while (node != null) 188 | { 189 | lock (node.locker_) 190 | { 191 | if (node.value_ != null) 192 | action(node.value_); 193 | 194 | node = node.next_; 195 | } 196 | } 197 | } 198 | 199 | public Enumarator GetEnumerator() 200 | { 201 | return new Enumarator(this); 202 | } 203 | 204 | IEnumerator IEnumerable.GetEnumerator() 205 | { 206 | return GetEnumerator(); 207 | } 208 | 209 | #endregion 210 | 211 | #region Private Methods 212 | 213 | private void ValidateNode(node node) 214 | { 215 | if (node == null) 216 | throw new ArgumentNullException("node"); 217 | 218 | if (node.list_ != this) 219 | throw new InvalidOperationException("invalid node for list"); 220 | } 221 | 222 | 223 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 224 | { 225 | return GetEnumerator(); 226 | } 227 | 228 | #endregion 229 | 230 | #region Enumerator class for Thread-Safe looping the list 231 | 232 | public struct Enumarator : IEnumerator, System.Collections.IEnumerator 233 | { 234 | private PooledList list; 235 | private node node; 236 | private T current; 237 | private object lastlock; 238 | 239 | internal Enumarator(PooledList list) 240 | { 241 | this.list = list; 242 | this.node = list.first(); 243 | this.current = null; 244 | this.lastlock = null; 245 | } 246 | 247 | public T Current => current; 248 | 249 | object System.Collections.IEnumerator.Current => current; 250 | 251 | public bool MoveNext() 252 | { 253 | if (lastlock != null) 254 | Monitor.Exit(lastlock); 255 | 256 | if (node == null) 257 | { 258 | lastlock = null; 259 | return false; 260 | } 261 | 262 | Monitor.Enter(node.locker_); 263 | lastlock = node.locker_; 264 | 265 | current = node.value_; 266 | node = node.next_; 267 | 268 | if (current == null) 269 | return MoveNext(); 270 | 271 | return true; 272 | } 273 | 274 | void System.Collections.IEnumerator.Reset() 275 | { 276 | if (lastlock != null) 277 | Monitor.Exit(lastlock); 278 | 279 | this.node = this.list.Head; 280 | this.current = null; 281 | lastlock = null; 282 | } 283 | 284 | public void Dispose() 285 | { 286 | if (lastlock != null) 287 | Monitor.Exit(lastlock); 288 | } 289 | } 290 | 291 | #endregion 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /SCommon/SCommon.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 1ced3d69-af5c-44f5-985c-33f28c7f521a 7 | 8 | 9 | SCommon 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SCommon/SCommon.shproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 1ced3d69-af5c-44f5-985c-33f28c7f521a 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SCommon/Security/PacketReader.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon.Security 2 | { 3 | using System.IO; 4 | 5 | public class PacketReader : System.IO.BinaryReader 6 | { 7 | byte[] m_input; 8 | 9 | public PacketReader(byte[] input) 10 | : base(new MemoryStream(input, false)) 11 | { 12 | m_input = input; 13 | } 14 | 15 | public PacketReader(byte[] input, int index, int count) 16 | : base(new MemoryStream(input, index, count, false)) 17 | { 18 | m_input = input; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /SCommon/Security/PacketWriter.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon.Security 2 | { 3 | using System.IO; 4 | 5 | public class PacketWriter : BinaryWriter 6 | { 7 | MemoryStream m_ms; 8 | 9 | public PacketWriter() 10 | { 11 | m_ms = new MemoryStream(); 12 | this.OutStream = m_ms; 13 | } 14 | 15 | public byte[] GetBytes() 16 | { 17 | return m_ms.ToArray(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SCommon/Security/TransferBuffer.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon.Security 2 | { 3 | public class TransferBuffer 4 | { 5 | byte[] m_buffer; 6 | int m_offset; 7 | int m_size; 8 | object m_lock; 9 | 10 | public byte[] Buffer 11 | { 12 | get { return m_buffer; } 13 | set { lock (m_lock) { m_buffer = value; } } 14 | } 15 | 16 | public int Offset 17 | { 18 | get { return m_offset; } 19 | set { lock (m_lock) { m_offset = value; } } 20 | } 21 | 22 | public int Size 23 | { 24 | get { return m_size; } 25 | set { lock (m_lock) { m_size = value; } } 26 | } 27 | 28 | public TransferBuffer(TransferBuffer rhs) 29 | { 30 | lock (rhs.m_lock) 31 | { 32 | m_buffer = new byte[rhs.m_buffer.Length]; 33 | System.Buffer.BlockCopy(rhs.m_buffer, 0, m_buffer, 0, m_buffer.Length); 34 | m_offset = rhs.m_offset; 35 | m_size = rhs.m_size; 36 | m_lock = new object(); 37 | } 38 | } 39 | 40 | public TransferBuffer() 41 | { 42 | m_buffer = null; 43 | m_offset = 0; 44 | m_size = 0; 45 | m_lock = new object(); 46 | } 47 | 48 | public TransferBuffer(int length, int offset, int size) 49 | { 50 | m_buffer = new byte[length]; 51 | m_offset = offset; 52 | m_size = size; 53 | m_lock = new object(); 54 | } 55 | 56 | public TransferBuffer(int length) 57 | { 58 | m_buffer = new byte[length]; 59 | m_offset = 0; 60 | m_size = 0; 61 | m_lock = new object(); 62 | } 63 | 64 | public TransferBuffer(byte[] buffer, int offset, int size, bool assign) 65 | { 66 | if (assign) 67 | { 68 | m_buffer = buffer; 69 | } 70 | else 71 | { 72 | m_buffer = new byte[buffer.Length]; 73 | System.Buffer.BlockCopy(buffer, 0, m_buffer, 0, buffer.Length); 74 | } 75 | m_offset = offset; 76 | m_size = size; 77 | m_lock = new object(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /SCommon/Utility.cs: -------------------------------------------------------------------------------- 1 | namespace SCommon 2 | { 3 | using System; 4 | using System.Text; 5 | using System.IO; 6 | using System.Security.Cryptography; 7 | 8 | using SCommon.Security; 9 | 10 | using SharpDX; 11 | 12 | public static class Utility 13 | { 14 | #region Private Properties and Fields 15 | 16 | /// 17 | /// The md5 cipher 18 | /// 19 | private static MD5 s_Cipher; 20 | 21 | #endregion 22 | 23 | #region Constructors & Destructors 24 | 25 | static Utility() 26 | { 27 | s_Cipher = MD5.Create(); 28 | } 29 | 30 | #endregion 31 | 32 | #region Public Methods 33 | 34 | /// 35 | /// Computes the hash of the given text. 36 | /// 37 | /// The text in ASCII encoding. 38 | /// The MD5 hash 39 | public static byte[] MD5Hash(string text) 40 | { 41 | return s_Cipher.ComputeHash(Encoding.ASCII.GetBytes(text)); 42 | } 43 | 44 | /// 45 | /// Computes the hash of the given text. 46 | /// 47 | /// The text in ASCII encoding. 48 | /// if true, returns string in lowercase 49 | /// The MD5 hash as string 50 | public static string MD5Hash(string text, bool lowercase) 51 | { 52 | byte[] hash = MD5Hash(text); 53 | string builder = string.Empty; 54 | foreach (byte b in hash) 55 | builder += b.ToString(lowercase ? "x2" : "X2"); 56 | 57 | return builder; 58 | } 59 | 60 | /// 61 | /// Returns dump string of the given packet 62 | /// 63 | /// The packet. 64 | /// Packet dump as string 65 | public static string HexDump(this Packet packet, bool sc_true_or_cs_false) 66 | { 67 | return String.Format("[{0}][Opcode:0x{3:X4}][Encrypted:{1}][Massive:{2}]{4}{5}", sc_true_or_cs_false ? "S->C" : "C->S", packet.Encrypted, packet.Massive, packet.Opcode, Environment.NewLine, HexDump(packet.GetBytes())); 68 | } 69 | 70 | /// 71 | /// Returns dump string of the given buffer 72 | /// 73 | /// The buffer. 74 | /// buffer dump as string 75 | public static string HexDump(this byte[] buffer) 76 | { 77 | return HexDump(buffer, 0, buffer.Length); 78 | } 79 | 80 | /// 81 | /// Returns dump string of the given buffer 82 | /// 83 | /// The buffer. 84 | /// buffer dump as string 85 | public static string HexDump(this byte[] buffer, int offset, int count) 86 | { 87 | const int bytesPerLine = 16; 88 | StringBuilder output = new StringBuilder(); 89 | StringBuilder ascii_output = new StringBuilder(); 90 | int length = count; 91 | if (length % bytesPerLine != 0) 92 | { 93 | length += bytesPerLine - length % bytesPerLine; 94 | } 95 | for (int x = 0; x <= length; ++x) 96 | { 97 | if (x % bytesPerLine == 0) 98 | { 99 | if (x > 0) 100 | { 101 | output.AppendFormat(" {0}{1}", ascii_output.ToString(), Environment.NewLine); 102 | ascii_output.Clear(); 103 | } 104 | if (x != length) 105 | { 106 | output.AppendFormat("{0:d10} ", x); 107 | } 108 | } 109 | if (x < count) 110 | { 111 | output.AppendFormat("{0:X2} ", buffer[offset + x]); 112 | char ch = (char)buffer[offset + x]; 113 | if (!Char.IsControl(ch)) 114 | { 115 | ascii_output.AppendFormat("{0}", ch); 116 | } 117 | else 118 | { 119 | ascii_output.Append("."); 120 | } 121 | } 122 | else 123 | { 124 | output.Append(" "); 125 | ascii_output.Append("."); 126 | } 127 | } 128 | return output.ToString(); 129 | } 130 | 131 | public static string ReadAscii(this BinaryReader reader) 132 | { 133 | return new string(reader.ReadChars(reader.ReadInt32())); 134 | } 135 | 136 | public static Vector2 ReadVector2(this BinaryReader reader) 137 | { 138 | return new Vector2(reader.ReadSingle(), reader.ReadSingle()); 139 | } 140 | 141 | public static Vector3 ReadVector3(this BinaryReader reader) 142 | { 143 | return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); 144 | } 145 | 146 | #endregion 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /SCore.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanisman/SilkroadProject/8f72246035555abdaba4cf079a356ea028db7385/SCore.dll -------------------------------------------------------------------------------- /SCore/SCore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SCore", "SCore\SCore.vcxproj", "{A0E9C09C-CC53-474F-BDD5-A641F57E2215}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Debug|Win32.Build.0 = Debug|Win32 16 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Release|Win32.ActiveCfg = Release|Win32 17 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SCore/SCore/AssemblyInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | using namespace System; 4 | using namespace System::Reflection; 5 | using namespace System::Runtime::CompilerServices; 6 | using namespace System::Runtime::InteropServices; 7 | using namespace System::Security::Permissions; 8 | 9 | // 10 | // General Information about an assembly is controlled through the following 11 | // set of attributes. Change these attribute values to modify the information 12 | // associated with an assembly. 13 | // 14 | [assembly:AssemblyTitleAttribute(L"SCore")]; 15 | [assembly:AssemblyDescriptionAttribute(L"")]; 16 | [assembly:AssemblyConfigurationAttribute(L"")]; 17 | [assembly:AssemblyCompanyAttribute(L"")]; 18 | [assembly:AssemblyProductAttribute(L"SCore")]; 19 | [assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2016")]; 20 | [assembly:AssemblyTrademarkAttribute(L"")]; 21 | [assembly:AssemblyCultureAttribute(L"")]; 22 | 23 | // 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the value or you can default the Revision and Build Numbers 32 | // by using the '*' as shown below: 33 | 34 | [assembly:AssemblyVersionAttribute("1.0.*")]; 35 | 36 | [assembly:ComVisible(false)]; 37 | 38 | [assembly:CLSCompliantAttribute(true)]; -------------------------------------------------------------------------------- /SCore/SCore/AsyncTimer.Native.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "SCore.h" 3 | #include "AsyncTimer.Native.h" 4 | 5 | using namespace SCore::Native; 6 | 7 | AsyncTimer::AsyncTimer(TimerCallback clb) 8 | : m_timer(SCore::ios), m_callback(clb), m_running(FALSE), m_reset (FALSE) 9 | { 10 | 11 | } 12 | 13 | AsyncTimer::AsyncTimer(TimerCallback clb, void *data, DWORD dueTime, DWORD perTime) 14 | : m_timer(SCore::ios, std::chrono::milliseconds(dueTime)), m_data(data), m_callback(clb), m_dueTime(dueTime), m_perTime(perTime), m_running(TRUE), m_reset(FALSE) 15 | { 16 | if (dueTime < 0) 17 | throw new std::exception("due time cannot be smaller than 0"); 18 | 19 | m_timer.async_wait(std::bind(&AsyncTimer::AsyncWaitCompleted, this, std::placeholders::_1, std::ref(m_timer))); 20 | } 21 | 22 | AsyncTimer::~AsyncTimer() 23 | { 24 | AutoLockScope locker(&m_lock); 25 | asio::error_code ec; 26 | m_timer.cancel(ec); 27 | m_running = FALSE; 28 | } 29 | 30 | void AsyncTimer::SetDueTime(DWORD dueTime) 31 | { 32 | AutoLockScope locker(&m_lock); 33 | m_dueTime = dueTime; 34 | } 35 | 36 | void AsyncTimer::SetPerTime(DWORD perTime) 37 | { 38 | AutoLockScope locker(&m_lock); 39 | m_perTime = perTime; 40 | } 41 | 42 | void AsyncTimer::SetData(void * data) 43 | { 44 | AutoLockScope locker(&m_lock); 45 | m_data = data; 46 | } 47 | 48 | void AsyncTimer::Start() 49 | { 50 | AutoLockScope locker(&m_lock); 51 | if (IsRunning()) 52 | { 53 | printf("timer is already running\n"); 54 | throw new std::exception("timer is already running"); 55 | } 56 | 57 | m_timer.expires_from_now(std::chrono::milliseconds(m_dueTime)); 58 | m_timer.async_wait(std::bind(&AsyncTimer::AsyncWaitCompleted, this, std::placeholders::_1, std::ref(m_timer))); 59 | 60 | m_running = TRUE; 61 | } 62 | 63 | void AsyncTimer::Start(DWORD dueTime, DWORD perTime) 64 | { 65 | AutoLockScope locker(&m_lock); 66 | if (IsRunning()) 67 | { 68 | printf("timer is already running\n"); 69 | throw new std::exception("timer is already running"); 70 | } 71 | 72 | if (dueTime < 0) 73 | throw new std::exception("due time cannot be smaller than 0"); 74 | 75 | SetDueTime(dueTime); 76 | SetPerTime(perTime); 77 | 78 | m_timer.expires_from_now(std::chrono::milliseconds(m_dueTime)); 79 | m_timer.async_wait(std::bind(&AsyncTimer::AsyncWaitCompleted, this, std::placeholders::_1, std::ref(m_timer))); 80 | 81 | m_running = TRUE; 82 | } 83 | 84 | void AsyncTimer::Start(DWORD dueTime, DWORD perTime, void *data) 85 | { 86 | AutoLockScope locker(&m_lock); 87 | if (IsRunning()) 88 | { 89 | printf("timer is already running\n"); 90 | throw new std::exception("timer is already running"); 91 | } 92 | 93 | if (dueTime < 0) 94 | throw new std::exception("due time cannot be smaller than 0"); 95 | 96 | SetDueTime(dueTime); 97 | SetPerTime(perTime); 98 | SetData(data); 99 | 100 | m_timer.expires_from_now(std::chrono::milliseconds(m_dueTime)); 101 | m_timer.async_wait(std::bind(&AsyncTimer::AsyncWaitCompleted, this, std::placeholders::_1, std::ref(m_timer))); 102 | 103 | m_running = TRUE; 104 | } 105 | 106 | void AsyncTimer::Stop() 107 | { 108 | AutoLockScope locker(&m_lock); 109 | m_running = FALSE; 110 | asio::error_code ec; 111 | m_timer.cancel(ec); 112 | if (ec) 113 | printf("cannot stop timer (exception code: %d)\n", ec.value()); 114 | } 115 | 116 | void AsyncTimer::Change(DWORD dueTime, DWORD perTime, void *data) 117 | { 118 | AutoLockScope locker(&m_lock); 119 | if (IsRunning()) 120 | Stop(); 121 | 122 | Start(dueTime, perTime, data); 123 | } 124 | 125 | void AsyncTimer::Change(DWORD dueTime, DWORD perTime) 126 | { 127 | AutoLockScope locker(&m_lock); 128 | if (IsRunning()) 129 | Stop(); 130 | 131 | Start(dueTime, perTime); 132 | } 133 | 134 | void AsyncTimer::Reset(DWORD dueTime, DWORD perTime) 135 | { 136 | AutoLockScope locker(&m_lock); 137 | SetDueTime(dueTime); 138 | SetPerTime(perTime); 139 | m_reset = TRUE; 140 | } 141 | 142 | void AsyncTimer::Reset(DWORD dueTime, DWORD perTime, void *data) 143 | { 144 | AutoLockScope locker(&m_lock); 145 | SetDueTime(dueTime); 146 | SetPerTime(perTime); 147 | SetData(data); 148 | m_reset = TRUE; 149 | } 150 | 151 | BOOL AsyncTimer::IsRunning() 152 | { 153 | AutoLockScope locker(&m_lock); 154 | return m_running; 155 | } 156 | 157 | void AsyncTimer::AsyncWaitCompleted(const asio::error_code &ec, asio::steady_timer &t) 158 | { 159 | if (AsyncTimer::IsRunning()) 160 | { 161 | if (ec) 162 | printf("error at Native::AsyncTimer::AsyncWaitCompleted %d\n", ec.value()); 163 | else 164 | { 165 | m_callback(*this, m_data); 166 | 167 | AutoLockScope locker(&m_lock); 168 | if (m_reset) 169 | { 170 | m_reset = FALSE; 171 | if (m_dueTime == -1) 172 | { 173 | m_running = FALSE; 174 | return; 175 | } 176 | 177 | m_timer.expires_from_now(std::chrono::milliseconds(m_dueTime)); 178 | m_timer.async_wait(std::bind(&AsyncTimer::AsyncWaitCompleted, this, std::placeholders::_1, std::ref(m_timer))); 179 | return; 180 | } 181 | 182 | if (m_perTime > 0) 183 | { 184 | m_timer.expires_from_now(std::chrono::milliseconds(m_perTime)); 185 | m_timer.async_wait(std::bind(&AsyncTimer::AsyncWaitCompleted, this, std::placeholders::_1, std::ref(m_timer))); 186 | } 187 | else 188 | m_running = FALSE; 189 | } 190 | } 191 | } -------------------------------------------------------------------------------- /SCore/SCore/AsyncTimer.Native.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "AutoCriticalSection.h" 5 | 6 | namespace SCore 7 | { 8 | namespace Native 9 | { 10 | class AsyncTimer; 11 | typedef void(CALLBACK *TimerCallback)(AsyncTimer &sender, void *data); 12 | 13 | class AsyncTimer 14 | { 15 | private: 16 | asio::steady_timer m_timer; 17 | void *m_data; 18 | TimerCallback m_callback; 19 | DWORD m_dueTime; 20 | DWORD m_perTime; 21 | AutoCriticalSection m_lock; 22 | BOOL m_running; 23 | BOOL m_reset; 24 | public: 25 | AsyncTimer(TimerCallback clb); 26 | AsyncTimer(TimerCallback clb, void *data, DWORD dueTime, DWORD perTime); 27 | void SetDueTime(DWORD dueTime); 28 | void SetPerTime(DWORD perTime); 29 | void SetData(void *data); 30 | void Start(); 31 | void Start(DWORD dueTime, DWORD perTime); 32 | void Start(DWORD dueTime, DWORD perTime, void *data); 33 | void Stop(); 34 | void Change(DWORD dueTime, DWORD perTime); 35 | void Change(DWORD dueTime, DWORD perTime, void *data); 36 | void Reset(DWORD dueTime, DWORD perTime); 37 | void Reset(DWORD dueTime, DWORD perTime, void *data); 38 | BOOL IsRunning(); 39 | ~AsyncTimer(); 40 | private: 41 | void AsyncWaitCompleted(const asio::error_code &ec, asio::steady_timer &t); 42 | }; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /SCore/SCore/AsyncTimer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "AsyncTimer.h" 3 | 4 | using namespace SCore; 5 | 6 | AsyncTimer::AsyncTimer(EventHandler^ callback) 7 | : m_callback( callback ) 8 | { 9 | m_fpCallback = gcnew NativeCallbackDelegate(this, &AsyncTimer::AsyncWaitCompleted); 10 | m_gcHandle = GCHandle::Alloc(m_fpCallback); 11 | IntPtr ip = Marshal::GetFunctionPointerForDelegate(m_fpCallback); 12 | Native::TimerCallback cb = static_cast(ip.ToPointer()); 13 | 14 | m_nativeHandle = new Native::AsyncTimer(cb); 15 | } 16 | 17 | AsyncTimer::AsyncTimer(EventHandler^ callback, Object^ data, UInt32 dueTime, UInt32 perTime) 18 | : m_callback( callback ) , m_data ( data ) 19 | { 20 | m_fpCallback = gcnew NativeCallbackDelegate(this, &AsyncTimer::AsyncWaitCompleted); 21 | m_gcHandle = GCHandle::Alloc(m_fpCallback); 22 | IntPtr ip = Marshal::GetFunctionPointerForDelegate(m_fpCallback); 23 | Native::TimerCallback cb = static_cast(ip.ToPointer()); 24 | 25 | m_nativeHandle = new Native::AsyncTimer(cb, NULL, dueTime, perTime); 26 | } 27 | 28 | void AsyncTimer::Start(Int32 dueTime, Int32 perTime) 29 | { 30 | m_nativeHandle->Start(dueTime, perTime); 31 | } 32 | 33 | void AsyncTimer::Start(Int32 dueTime, Int32 perTime, Object^ data) 34 | { 35 | m_data = data; 36 | m_nativeHandle->Start(dueTime, perTime); 37 | } 38 | 39 | void AsyncTimer::Stop() 40 | { 41 | m_nativeHandle->Stop(); 42 | } 43 | 44 | void AsyncTimer::Change(Int32 dueTime, Int32 perTime) 45 | { 46 | m_nativeHandle->Change(dueTime, perTime); 47 | } 48 | 49 | void AsyncTimer::Change(Int32 dueTime, Int32 perTime, Object^ data) 50 | { 51 | m_data = data; 52 | m_nativeHandle->Change(dueTime, perTime); 53 | } 54 | 55 | void AsyncTimer::Change(Object^ data) 56 | { 57 | m_data = data; 58 | } 59 | 60 | void AsyncTimer::Reset(Int32 dueTime, Int32 perTime) 61 | { 62 | m_nativeHandle->Reset(dueTime, perTime); 63 | } 64 | 65 | void AsyncTimer::Reset(Int32 dueTime, Int32 perTime, Object^ data) 66 | { 67 | m_data = data; 68 | m_nativeHandle->Reset(dueTime, perTime); 69 | } 70 | 71 | bool AsyncTimer::IsRunning::get() 72 | { 73 | return m_nativeHandle->IsRunning() == 1; 74 | } 75 | 76 | AsyncTimer::~AsyncTimer() 77 | { 78 | delete m_nativeHandle; 79 | m_gcHandle.Free(); 80 | m_fpCallback = nullptr; 81 | } 82 | 83 | void AsyncTimer::AsyncWaitCompleted(Native::AsyncTimer &sender, void *data) 84 | { 85 | m_callback(this, m_data); 86 | } 87 | -------------------------------------------------------------------------------- /SCore/SCore/AsyncTimer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "AsyncTimer.Native.h" 3 | 4 | using namespace System; 5 | using namespace System::Runtime::InteropServices; 6 | 7 | 8 | namespace SCore 9 | { 10 | public ref class AsyncTimer : IDisposable 11 | { 12 | private: 13 | delegate void NativeCallbackDelegate(Native::AsyncTimer &, void *); 14 | Native::AsyncTimer *m_nativeHandle; 15 | Object^ m_data; 16 | EventHandler^ m_callback; 17 | 18 | GCHandle m_gcHandle; 19 | NativeCallbackDelegate^ m_fpCallback; 20 | public: 21 | AsyncTimer(EventHandler^ callback); 22 | AsyncTimer(EventHandler^ callback, Object^ data, UInt32 dueTime, UInt32 perTime); 23 | void Start(Int32 dueTime, Int32 perTime); 24 | void Start(Int32 dueTime, Int32 perTime, Object^ data); 25 | void Stop(); 26 | void Change(Int32 dueTime, Int32 perTime); 27 | void Change(Int32 dueTime, Int32 perTime, Object^ data); 28 | void Change(Object^ data); 29 | void Reset(Int32 dueTime, Int32 perTime); 30 | void Reset(Int32 dueTime, Int32 perTime, Object^ data); 31 | ~AsyncTimer(); 32 | private: 33 | void AsyncWaitCompleted(Native::AsyncTimer &sender, void *data); 34 | public: 35 | property bool IsRunning 36 | { 37 | bool get(); 38 | } 39 | }; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /SCore/SCore/AutoCriticalSection.cpp: -------------------------------------------------------------------------------- 1 | #include "Stdafx.h" 2 | #include "AutoCriticalSection.h" 3 | using namespace SCore::Native; 4 | 5 | AutoCriticalSection::AutoCriticalSection() 6 | { 7 | InitializeCriticalSection(&m_cs); 8 | } 9 | 10 | 11 | AutoCriticalSection::~AutoCriticalSection() 12 | { 13 | DeleteCriticalSection(&m_cs); 14 | } 15 | 16 | void AutoCriticalSection::Lock() 17 | { 18 | EnterCriticalSection(&m_cs); 19 | } 20 | 21 | void AutoCriticalSection::Unlock() 22 | { 23 | LeaveCriticalSection(&m_cs); 24 | } -------------------------------------------------------------------------------- /SCore/SCore/AutoCriticalSection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | namespace SCore 6 | { 7 | namespace Native 8 | { 9 | class AutoCriticalSection 10 | { 11 | private: 12 | CRITICAL_SECTION m_cs; 13 | public: 14 | AutoCriticalSection(); 15 | AutoCriticalSection(DWORD dwSpinCount); 16 | ~AutoCriticalSection(); 17 | void Lock(); 18 | bool TryLock(); 19 | void Unlock(); 20 | }; 21 | 22 | class AutoLockScope 23 | { 24 | private: 25 | AutoCriticalSection *m_pAcs; 26 | public: 27 | AutoLockScope(AutoCriticalSection *pAcs) 28 | : m_pAcs(pAcs) 29 | { 30 | m_pAcs->Lock(); 31 | } 32 | ~AutoLockScope() 33 | { 34 | m_pAcs->Unlock(); 35 | } 36 | }; 37 | } 38 | } -------------------------------------------------------------------------------- /SCore/SCore/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | DYNAMIC LINK LIBRARY : SCore Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this SCore DLL for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your SCore application. 9 | 10 | SCore.vcxproj 11 | This is the main project file for VC++ projects generated using an Application Wizard. 12 | It contains information about the version of Visual C++ that generated the file, and 13 | information about the platforms, configurations, and project features selected with the 14 | Application Wizard. 15 | 16 | SCore.vcxproj.filters 17 | This is the filters file for VC++ projects generated using an Application Wizard. 18 | It contains information about the association between the files in your project 19 | and the filters. This association is used in the IDE to show grouping of files with 20 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 21 | "Source Files" filter). 22 | 23 | SCore.cpp 24 | This is the main DLL source file. 25 | 26 | SCore.h 27 | This file contains a class declaration. 28 | 29 | AssemblyInfo.cpp 30 | Contains custom attributes for modifying assembly metadata. 31 | 32 | ///////////////////////////////////////////////////////////////////////////// 33 | Other notes: 34 | 35 | AppWizard uses "TODO:" to indicate parts of the source code you 36 | should add to or customize. 37 | 38 | ///////////////////////////////////////////////////////////////////////////// 39 | -------------------------------------------------------------------------------- /SCore/SCore/SCore.cpp: -------------------------------------------------------------------------------- 1 | // This is the main DLL file. 2 | 3 | #include "stdafx.h" 4 | 5 | -------------------------------------------------------------------------------- /SCore/SCore/SCore.h: -------------------------------------------------------------------------------- 1 | // SCore.h 2 | 3 | #pragma once 4 | #include "stdafx.h" 5 | #include 6 | 7 | using namespace System; 8 | 9 | namespace SCore 10 | { 11 | static asio::io_service ios(2); 12 | static asio::io_service::work w(ios); 13 | static std::list ioworkers; 14 | 15 | void run(int numthreads) 16 | { 17 | unsigned int worker_count = numthreads; 18 | 19 | if (worker_count < 1) 20 | { 21 | SYSTEM_INFO sysinfo; 22 | GetSystemInfo(&sysinfo); 23 | worker_count = sysinfo.dwNumberOfProcessors * 2; 24 | } 25 | 26 | if (worker_count == 0) 27 | worker_count = 16; 28 | 29 | for (int i = 0; i < worker_count; i++) 30 | ioworkers.emplace_back([&] { ios.run(); }); 31 | } 32 | 33 | public ref class TimerService 34 | { 35 | internal: 36 | 37 | public: 38 | static void Initialize(int numthreads) 39 | { 40 | run(numthreads); 41 | } 42 | 43 | static void Initialize() 44 | { 45 | run(0); 46 | } 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /SCore/SCore/SCore.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215} 15 | v4.5.2 16 | ManagedCProj 17 | SCore 18 | 8.1 19 | 20 | 21 | 22 | DynamicLibrary 23 | true 24 | v140 25 | true 26 | Unicode 27 | 28 | 29 | DynamicLibrary 30 | false 31 | v140 32 | true 33 | Unicode 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | true 47 | C:\zaa\sremu_c\iocp;$(IncludePath) 48 | 49 | 50 | false 51 | C:\zaa\sremu_c\iocp;$(IncludePath) 52 | $(SolutionDir)..\ 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | WIN32;_DEBUG;%(PreprocessorDefinitions) 59 | Use 60 | 61 | 62 | true 63 | 64 | 65 | 66 | 67 | 68 | Level3 69 | WIN32;NDEBUG;%(PreprocessorDefinitions) 70 | Use 71 | 72 | 73 | true 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Create 98 | Create 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /SCore/SCore/SCore.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Resource Files 63 | 64 | 65 | 66 | 67 | Resource Files 68 | 69 | 70 | -------------------------------------------------------------------------------- /SCore/SCore/Stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // SCore.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | -------------------------------------------------------------------------------- /SCore/SCore/Stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, 3 | // but are changed infrequently 4 | 5 | #pragma once 6 | 7 | 8 | #define ASIO_STANDALONE 9 | #define ASIO_MSVC _MSC_VER 10 | 11 | #define ASIO_HAS_CONSTEXPR 1 12 | #define ASIO_HAS_VARIADIC_TEMPLATES 1 13 | 14 | #include 15 | -------------------------------------------------------------------------------- /SCore/SCore/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanisman/SilkroadProject/8f72246035555abdaba4cf079a356ea028db7385/SCore/SCore/app.ico -------------------------------------------------------------------------------- /SCore/SCore/app.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanisman/SilkroadProject/8f72246035555abdaba4cf079a356ea028db7385/SCore/SCore/app.rc -------------------------------------------------------------------------------- /SCore/SCore/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by app.rc 4 | -------------------------------------------------------------------------------- /SR_GameServer/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /SR_GameServer/Data/Enumarations.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data 2 | { 3 | using System; 4 | 5 | public enum JobType 6 | { 7 | Trader = 0, 8 | Thief = 1, 9 | Hunter = 2, 10 | } 11 | 12 | public enum ItemType 13 | { 14 | CH_WEAPON_SWORD = 1, 15 | CH_WEAPON_BLADE = 2, 16 | CH_WEAPON_SPEAR = 3, 17 | CH_WEAPON_TBLADE = 4, 18 | CH_WEAPON_BOW = 5, 19 | CH_WEAPON_SHIELD = 6, 20 | CH_ARMOR_HEAVY = 7, 21 | CH_ARMOR_LIGHT = 8, 22 | CH_ARMOR_CLOTHES = 9, 23 | CH_ACCESSORY_NECKLACE = 10, 24 | CH_ACCESSORY_EARRING = 11, 25 | CH_ACCESSORY_RING = 12, 26 | EU_WEAPON_SWORD = 13, 27 | EU_WEAPON_TSWORD = 14, 28 | EU_WEAPON_DUALAXE = 15, 29 | EU_WEAPON_WROD = 16, 30 | EU_WEAPON_CROD = 17, 31 | EU_WEAPON_TSTAFF = 18, 32 | EU_WEAPON_CROSSBOW = 19, 33 | EU_WEAPON_DAGGER = 20, 34 | EU_WEAPON_HARP = 21, 35 | EU_WEAPON_SHIELD = 22, 36 | EU_ARMOR_HEAVY = 23, 37 | EU_ARMOR_LIGHT = 24, 38 | EU_ARMOR_ROBE = 25, 39 | EU_ACCESSORY_NECKLACE = 26, 40 | EU_ACCESSORY_EARRING = 27, 41 | EU_ACCESSORY_RING = 28, 42 | COSTUME_TRIANGLE = 29, 43 | COSTUME_AVATAR = 30, 44 | COSTUME_ETC = 31, 45 | COSTUME_NASRUN = 32, 46 | ALCHEMY_ELIXIR = 33, 47 | SOCKET_STONE = 34, 48 | ALCHEMY_ELEMENT = 35, 49 | ALCHEMY_MAGICSTONE = 36, 50 | ALCHEMY_ATTRSTONE = 37, 51 | ALCHEMY_TABLET = 38, 52 | ALCHEMY_MATERIAL = 39, 53 | COS_COS = 40, 54 | COS_ETC = 41, 55 | ARTICLES_RECOVERY = 42, 56 | ARTICLES_CURE = 43, 57 | ARTICLES_RETURN = 44, 58 | ARTICLES_FORTIFY = 45, 59 | ARTICLES_ARROW = 46, 60 | GUILD_ITEM = 47, 61 | FORTWAR_WEAPON = 48, 62 | FORTWAR_ITEM = 49, 63 | EXCHANGE_COIN = 50, 64 | EVENT_ITEM = 51, 65 | ETC_CHANGE = 52, 66 | ETC_SPECIAL = 53, 67 | ETC_SKILL = 54, 68 | ETC_CHAT = 55, 69 | ETC_REPAIR = 56, 70 | ETC_ETC = 57, 71 | NEW_TRADE_WEAPON = 58, 72 | NEW_TRADE_ARMOR = 59, 73 | NEW_TRADE_ACCESSORY = 60, 74 | NEW_TRADE_ALCHEMY = 61, 75 | NEW_TRADE_ETC = 62, 76 | ALCHEMY_UPGRADE = 63, 77 | GOLD = 64, 78 | ETC_FIREWORK = 65, 79 | ETC_CAMPFIRE = 66, 80 | ETC_TRADE_ITEM = 67, 81 | None, 82 | COSTUME_FRPVP = 999, 83 | } 84 | 85 | [Flags] 86 | public enum AuthType 87 | { 88 | None = 0, 89 | GM = 1, 90 | } 91 | } -------------------------------------------------------------------------------- /SR_GameServer/Data/Globals.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | 7 | using SCommon; 8 | using SCommon.Database; 9 | 10 | using RefData; 11 | 12 | internal static class Globals 13 | { 14 | public static Dictionary Config; 15 | public static MSSQL GlobalDB; 16 | public static MSSQL ShardDB; 17 | public static SRGame SRGameService; 18 | public static string AllowedCharacters = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuopasdfghjklizxcvbnm1234567890_"; 19 | public static _refData Ref; 20 | public static PooledList GObjList; 21 | 22 | public static bool ConnectGlobalDB() 23 | { 24 | try 25 | { 26 | GlobalDB = new MSSQL("SR_Global Connection String"); 27 | return true; 28 | } 29 | #if DEBUG 30 | catch (Exception ex) 31 | #else 32 | catch (Exception) 33 | #endif 34 | { 35 | #if DEBUG 36 | Console.WriteLine(ex); 37 | #endif 38 | return false; 39 | } 40 | } 41 | 42 | public static bool ConnectShardDB() 43 | { 44 | try 45 | { 46 | ShardDB = new MSSQL("SR_OPEN (aka shard) Connection String"); 47 | return true; 48 | } 49 | #if DEBUG 50 | catch (Exception ex) 51 | #else 52 | catch (Exception) 53 | #endif 54 | { 55 | #if DEBUG 56 | Console.WriteLine(ex); 57 | #endif 58 | return false; 59 | } 60 | } 61 | 62 | public static bool LoadConfigTable() 63 | { 64 | try 65 | { 66 | Config = new Dictionary(); 67 | using (var reader = GlobalDB.ExecuteReader("SELECT * FROM _ServerConfig")) 68 | { 69 | while (reader.Read()) 70 | Config.Add(Convert.ToString(reader["Key"]), Convert.ToString(reader["Value"])); 71 | } 72 | return true; 73 | } 74 | #if DEBUG 75 | catch (Exception ex) 76 | #else 77 | catch (Exception) 78 | #endif 79 | { 80 | #if DEBUG 81 | Console.WriteLine(ex); 82 | #endif 83 | return false; 84 | } 85 | } 86 | 87 | public static bool LoadRefData() 88 | { 89 | try 90 | { 91 | GObjList = new PooledList(); 92 | Ref = new _refData(); 93 | 94 | Ref.CharGen = new List(); 95 | Ref.CharGen.Load(); 96 | 97 | Ref.FmnTidGroupMap = new List(); 98 | Ref.FmnTidGroupMap.Load(); 99 | 100 | Ref.ObjItem = new RefObjItem[45000]; 101 | Ref.ObjItemByCodeName = new Dictionary(); 102 | Ref.ObjItem.Load(); 103 | Ref.ObjItem.ToList().ForEach(p => { if (p != null) Ref.ObjItemByCodeName.Add(p.CodeName128, p); }); 104 | 105 | Ref.ObjChar = new RefObjChar[45000]; 106 | Ref.ObjCharByCodeName = new Dictionary(); 107 | Ref.ObjChar.Load(); 108 | Ref.ObjChar.ToList().ForEach(p => { if (p != null) Ref.ObjCharByCodeName.Add(p.CodeName128, p); }); 109 | 110 | Ref.Skill = new RefSkill[45000]; 111 | Ref.Skill.Load(); 112 | 113 | Ref.RegionBindAssocServer = new List(); 114 | Ref.RegionBindAssocServer.Load(); 115 | 116 | Ref.Region = new RefRegion[65535]; 117 | Ref.Region.Load(); 118 | 119 | Ref.DropGold = new RefDropGold[255]; 120 | Ref.DropGold.Load(); 121 | 122 | Ref.Level = new RefLevel[255]; 123 | Ref.Level.Load(); 124 | 125 | Ref.TeleportData = new List(); 126 | Ref.TeleportData.Load(); 127 | 128 | Ref.TeleportBuilding = new RefTeleportBuilding[45000]; 129 | Ref.TeleportBuilding.Load(); 130 | 131 | Ref.TeleportLink = new List(); 132 | Ref.TeleportLink.Load(); 133 | 134 | Ref.ObjCommon = new RefObjCommon[45000]; 135 | Ref.ObjItem.ToList().ForEach(p => { if (p != null) Ref.ObjCommon[p.ID] = p; }); 136 | Ref.ObjChar.ToList().ForEach(p => { if (p != null) Ref.ObjCommon[p.ID] = p; }); 137 | Ref.TeleportBuilding.ToList().ForEach(p => { if (p != null) Ref.ObjCommon[p.ID] = p; }); 138 | 139 | Ref.Shop = new List(); 140 | Ref.Shop.Load(); 141 | 142 | Ref.Hive = new Dictionary(); 143 | Ref.Hive.Load(); 144 | 145 | Ref.Tactics = new Dictionary(); 146 | Ref.Tactics.Load(); 147 | 148 | Ref.Nest = new Dictionary(); 149 | Ref.Nest.Load(); 150 | 151 | return true; 152 | } 153 | #if DEBUG 154 | catch (Exception ex) 155 | #else 156 | catch (Exception) 157 | #endif 158 | { 159 | #if DEBUG 160 | Console.WriteLine(ex); 161 | #endif 162 | return false; 163 | } 164 | } 165 | 166 | public static T GetConfigValue(string key) 167 | { 168 | return (T)Convert.ChangeType(Config[key], typeof(T)); 169 | } 170 | 171 | 172 | internal struct _refData 173 | { 174 | public List CharGen; 175 | public RefObjItem[] ObjItem; 176 | public Dictionary ObjItemByCodeName; 177 | public RefObjChar[] ObjChar; 178 | public Dictionary ObjCharByCodeName; 179 | public RefSkill[] Skill; 180 | public List FmnTidGroupMap; 181 | public RefRegion[] Region; 182 | public List RegionBindAssocServer; 183 | public RefDropGold[] DropGold; 184 | public RefLevel[] Level; 185 | public RefObjCommon[] ObjCommon; 186 | public Dictionary Hive; 187 | public Dictionary Nest; 188 | public Dictionary Tactics; 189 | public List TeleportData; 190 | public RefTeleportBuilding[] TeleportBuilding; 191 | public List TeleportLink; 192 | public List Shop; 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /SR_GameServer/Data/NavMesh/JmxMesh.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.NavMesh 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | using SCommon; 8 | 9 | using SharpDX; 10 | 11 | public static class JmxMesh 12 | { 13 | public static List<_bms_data> s_List; 14 | 15 | static JmxMesh() 16 | { 17 | s_List = new List<_bms_data>(); 18 | } 19 | 20 | public static _bms_data Load(string dir) 21 | { 22 | if (s_List.Exists(p => p.directory == dir)) 23 | return s_List.Find(p => p.directory == dir); 24 | 25 | using (var reader = new BinaryReader(File.Open(Path.Combine(Environment.CurrentDirectory, "data", dir), FileMode.Open))) 26 | { 27 | reader.ReadBytes(12); //skip header 28 | reader.ReadBytes(5 * 4); //skip pointers 29 | int pointer_bbox = reader.ReadInt32(); 30 | reader.ReadBytes(1 * 4); //skip pointers 31 | int pointer_hitbox = reader.ReadInt32(); 32 | reader.ReadBytes(2 * 4); //skip pointers 33 | 34 | uint unk00 = reader.ReadUInt32(); 35 | uint unk01 = reader.ReadUInt32(); //has special collision 36 | uint unk02 = reader.ReadUInt32(); 37 | uint lightmap = reader.ReadUInt32(); //0 = none, 1024 = lightmap 38 | uint unk03 = reader.ReadUInt32(); 39 | 40 | _bms_data bms = new _bms_data(); 41 | bms.directory = dir; 42 | reader.BaseStream.Position = pointer_bbox; 43 | bms.BBox = new BoundingBox(reader.ReadVector3(), reader.ReadVector3()); 44 | 45 | if (pointer_hitbox > 0) 46 | { 47 | reader.BaseStream.Position = pointer_hitbox; 48 | 49 | int point_count = reader.ReadInt32(); 50 | bms.Points = new sPoint[point_count]; 51 | 52 | for (int i = 0; i < point_count; i++) 53 | { 54 | var point = new sPoint(); 55 | point.Position = reader.ReadVector3(); 56 | point.Flag = reader.ReadByte(); 57 | 58 | bms.Points[i] = point; 59 | } 60 | 61 | int objectground_count = reader.ReadInt32(); 62 | bms.ObjectGround = new sTriangle[objectground_count]; 63 | 64 | for (int i = 0; i < objectground_count; i++) 65 | { 66 | var triangle = new sTriangle(); 67 | triangle.ID = i; 68 | triangle.PointA = reader.ReadUInt16(); 69 | triangle.PointB = reader.ReadUInt16(); 70 | triangle.PointC = reader.ReadUInt16(); 71 | triangle.unk00 = reader.ReadUInt16(); 72 | 73 | if (unk01 == 6 || unk01 == 7 || unk01 == 14) 74 | triangle.unk01 = reader.ReadByte(); 75 | 76 | bms.ObjectGround[i] = triangle; 77 | } 78 | 79 | int outlines_count = reader.ReadInt32(); 80 | bms.OutLines = new sLine[outlines_count]; 81 | 82 | for (int i = 0; i < outlines_count; i++) 83 | { 84 | var outline = new sLine(); 85 | outline.PointA = reader.ReadUInt16(); 86 | outline.PointB = reader.ReadUInt16(); 87 | outline.NeighbourA = reader.ReadUInt16(); 88 | outline.NeighbourB = reader.ReadUInt16(); 89 | outline.Flag = reader.ReadByte(); 90 | if (unk01 == 5 || unk01 == 7) 91 | outline.unk00 = reader.ReadByte(); 92 | 93 | bms.OutLines[i] = outline; 94 | } 95 | 96 | int inline_count = reader.ReadInt32(); 97 | bms.InLines = new sLine[inline_count]; 98 | 99 | for (int i = 0; i < inline_count; i++) 100 | { 101 | var inline = new sLine(); 102 | inline.PointA = reader.ReadUInt16(); 103 | inline.PointB = reader.ReadUInt16(); 104 | inline.NeighbourA = reader.ReadUInt16(); 105 | inline.NeighbourB = reader.ReadUInt16(); 106 | inline.Flag = reader.ReadByte(); 107 | if (unk01 == 5 || unk01 == 7) 108 | inline.unk00 = reader.ReadByte(); 109 | 110 | bms.InLines[i] = inline; 111 | } 112 | 113 | if (unk01 == 4 || unk01 == 5 || unk01 == 6 || unk01 == 7 || unk01 == 8) 114 | { 115 | int event_count = reader.ReadInt32(); 116 | bms.Events = new string[event_count]; 117 | 118 | for (int i = 0; i < event_count; i++) 119 | bms.Events[i] = reader.ReadAscii(); 120 | } 121 | } 122 | return bms; 123 | } 124 | } 125 | public static List<_bms_data> Items => s_List; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /SR_GameServer/Data/NavMesh/JmxNavmesh.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.NavMesh 2 | { 3 | using System; 4 | using System.IO; 5 | using System.Globalization; 6 | 7 | using SCommon; 8 | 9 | using SharpDX; 10 | 11 | public static class JmxNavmesh 12 | { 13 | private static _nvm_data[] s_List; 14 | 15 | public static void Load() 16 | { 17 | JmxObj.Load(); 18 | 19 | s_List = new _nvm_data[65535]; 20 | 21 | string[] nvmFiles = Directory.GetFiles(Path.Combine(Environment.CurrentDirectory, "data\\navmesh\\")); 22 | foreach (var nvmfile in nvmFiles) 23 | { 24 | if (nvmfile != null) 25 | { 26 | if (nvmfile.Split('.')[1] == "nvm") 27 | { 28 | using (var reader = new BinaryReader(new FileStream(nvmfile, FileMode.Open, FileAccess.Read))) 29 | { 30 | FileInfo info = new FileInfo(nvmfile); 31 | _nvm_data nvm = new _nvm_data(); 32 | nvm.company = reader.ReadInt32(); 33 | nvm.format = reader.ReadInt32(); 34 | nvm.version = reader.ReadInt32(); 35 | 36 | nvm.region = short.Parse(info.Name.Replace("nv_", "").Replace(".nvm", "").ToString(), NumberStyles.HexNumber); 37 | 38 | nvm.entries = new _nvm_entry[reader.ReadUInt16()]; 39 | for(int i = 0; i < nvm.entries.Length; i++) 40 | { 41 | nvm.entries[i] = new _nvm_entry(); 42 | nvm.entries[i].model = reader.ReadUInt32(); 43 | nvm.entries[i].position = reader.ReadVector3(); 44 | nvm.entries[i].collisionflag = reader.ReadUInt16(); 45 | nvm.entries[i].yaw = reader.ReadSingle(); 46 | nvm.entries[i].uniqueid = reader.ReadUInt16(); 47 | nvm.entries[i].unk00 = reader.ReadUInt16(); 48 | nvm.entries[i].unk01 = reader.ReadUInt16(); 49 | nvm.entries[i].region = reader.ReadInt16(); 50 | 51 | nvm.entries[i].extra = new _nvm_entry_extra[reader.ReadUInt16()]; 52 | for(int j = 0; j < nvm.entries[i].extra.Length; j++) 53 | { 54 | nvm.entries[i].extra[j] = new _nvm_entry_extra(); 55 | nvm.entries[i].extra[j].unk00 = reader.ReadUInt32(); 56 | nvm.entries[i].extra[j].unk01 = reader.ReadUInt16(); 57 | } 58 | 59 | nvm.entries[i].resource = JmxRes.Load(nvm.entries[i].model); 60 | //translate res bbox 61 | nvm.entries[i].resource.BBox = new BoundingBox( 62 | nvm.entries[i].position + nvm.entries[i].resource.BBox.Minimum.ToVector2().Rotated(nvm.entries[i].yaw).ToVector3(nvm.entries[i].resource.BBox.Minimum.Y), 63 | nvm.entries[i].position + nvm.entries[i].resource.BBox.Maximum.ToVector2().Rotated(nvm.entries[i].yaw).ToVector3(nvm.entries[i].resource.BBox.Maximum.Y)); 64 | 65 | //correct bbox min/max & scale by 100 66 | Vector3 v1 = nvm.entries[i].resource.BBox.Minimum, v2 = nvm.entries[i].resource.BBox.Maximum; 67 | nvm.entries[i].resource.BBox.Minimum.X = Math.Min(v1.X, v2.X) - 50; 68 | nvm.entries[i].resource.BBox.Maximum.X = Math.Max(v1.X, v2.X) + 50; 69 | nvm.entries[i].resource.BBox.Minimum.Z = Math.Min(v1.Z, v2.Z) - 50; 70 | nvm.entries[i].resource.BBox.Maximum.Z = Math.Max(v1.Z, v2.Z) + 50; 71 | 72 | //re-create obbox for translated object 73 | nvm.entries[i].resource.OBBox = new OrientedBoundingBox(nvm.entries[i].resource.BBox); 74 | 75 | if (nvm.entries[i].resource.mesh != null && nvm.entries[i].resource.mesh != string.Empty) 76 | { 77 | nvm.entries[i].mesh = JmxMesh.Load(nvm.entries[i].resource.mesh); 78 | nvm.entries[i].hasmesh = true; 79 | //translate mesh bbox 80 | nvm.entries[i].mesh.BBox = new BoundingBox( 81 | nvm.entries[i].position + nvm.entries[i].mesh.BBox.Minimum.ToVector2().Rotated(nvm.entries[i].yaw).ToVector3(nvm.entries[i].mesh.BBox.Minimum.Y), 82 | nvm.entries[i].position + nvm.entries[i].mesh.BBox.Maximum.ToVector2().Rotated(nvm.entries[i].yaw).ToVector3(nvm.entries[i].mesh.BBox.Maximum.Y)); 83 | 84 | //translate mesh points 85 | for (int j = 0; j < nvm.entries[i].mesh.Points.Length; j++) 86 | { 87 | nvm.entries[i].mesh.Points[j].Position = 88 | nvm.entries[i].position + nvm.entries[i].mesh.Points[j].Position.ToVector2().Rotated(nvm.entries[i].yaw).ToVector3(nvm.entries[i].mesh.Points[j].Position.Y); 89 | } 90 | } 91 | } 92 | 93 | nvm.zone1 = new _nvm_zone1[reader.ReadUInt32()]; 94 | nvm.unk00 = reader.ReadUInt32(); 95 | for (int i = 0; i < nvm.zone1.Length; i++) 96 | { 97 | nvm.zone1[i] = new _nvm_zone1(); 98 | nvm.zone1[i].min = reader.ReadVector2(); 99 | nvm.zone1[i].max = reader.ReadVector2(); 100 | 101 | nvm.zone1[i].extra = new _nvm_zone1_extra[reader.ReadByte()]; 102 | for(int j = 0; j < nvm.zone1[i].extra.Length; j++) 103 | { 104 | nvm.zone1[i].extra[j] = new _nvm_zone1_extra(); 105 | nvm.zone1[i].extra[j].entryidx = reader.ReadUInt16(); 106 | } 107 | } 108 | 109 | nvm.zone2 = new _nvm_zone2[reader.ReadUInt32()]; 110 | for (int i = 0; i < nvm.zone2.Length; i++) 111 | { 112 | nvm.zone2[i] = new _nvm_zone2(); 113 | nvm.zone2[i].PointA = reader.ReadVector2(); 114 | nvm.zone2[i].PointB = reader.ReadVector2(); 115 | nvm.zone2[i].flag = reader.ReadByte(); 116 | nvm.zone2[i].source = reader.ReadByte(); 117 | nvm.zone2[i].destination = reader.ReadByte(); 118 | nvm.zone2[i].ZoneSource = reader.ReadUInt16(); 119 | nvm.zone2[i].ZoneDestination = reader.ReadUInt16(); 120 | nvm.zone2[i].RegionSource = reader.ReadInt16(); 121 | nvm.zone2[i].RegionDestination = reader.ReadInt16(); 122 | } 123 | 124 | nvm.zone3 = new _nvm_zone3[reader.ReadUInt32()]; 125 | for (int i = 0; i < nvm.zone3.Length; i++) 126 | { 127 | nvm.zone3[i] = new _nvm_zone3(); 128 | nvm.zone3[i].PointA = reader.ReadVector2(); 129 | nvm.zone3[i].PointB = reader.ReadVector2(); 130 | nvm.zone3[i].flag = reader.ReadByte(); 131 | nvm.zone3[i].source = reader.ReadByte(); 132 | nvm.zone3[i].destination = reader.ReadByte(); 133 | nvm.zone3[i].ZoneSource = reader.ReadUInt16(); 134 | nvm.zone3[i].ZoneDestination = reader.ReadUInt16(); 135 | } 136 | 137 | reader.BaseStream.Position += 0x9000; //skip texture map 138 | 139 | nvm.heightmap = new float[9409]; 140 | for (int i = 0; i < 9409; i++) 141 | nvm.heightmap[i] = reader.ReadSingle(); 142 | 143 | s_List[(ushort)nvm.region] = nvm; 144 | } 145 | } 146 | } 147 | } 148 | Logging.Log()("NavMesh loaded."); 149 | } 150 | 151 | public static float GetHeightAt(short region, float x, float z) 152 | { 153 | if (x > 1920) 154 | { 155 | region += (short)(x / 1920); 156 | x = x % 1920; 157 | } 158 | else if (x < 0) 159 | { 160 | region -= (short)((short)((-x - 1) / 1920) + 1); 161 | x = 1920 + (x % 1920); 162 | } 163 | 164 | if (z > 1920) 165 | { 166 | region += (short)(Formula.REGION_SCALE * z / 1920); 167 | z = z % 1920; 168 | } 169 | else if (z < 0) 170 | { 171 | region -= (short)(Formula.REGION_SCALE * ((short)((-z - 1) / 1920) + 1)); 172 | z = 1920 + (z % 1920); 173 | } 174 | 175 | if (s_List[(ushort)region].heightmap == null) 176 | return 0; 177 | 178 | return s_List[(ushort)region].heightmap[Math.Min(9408, (int)((int)z / 20f) * 97 + (int)((int)x / 20f))]; 179 | } 180 | 181 | public static _nvm_data[] Items => s_List; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /SR_GameServer/Data/NavMesh/JmxObj.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.NavMesh 2 | { 3 | using System; 4 | using System.IO; 5 | using System.Globalization; 6 | 7 | using SCommon; 8 | 9 | public static class JmxObj 10 | { 11 | private static _nvm_link_bsr[] s_List; 12 | 13 | public static void Load() 14 | { 15 | using (var reader = new StreamReader(Path.Combine(Environment.CurrentDirectory, "data\\navmesh\\object.ifo"))) 16 | { 17 | if (reader.ReadLine() == "JMXVOBJI1000") 18 | { 19 | int count = Convert.ToInt32(reader.ReadLine()); 20 | s_List = new _nvm_link_bsr[count]; 21 | 22 | while(!reader.EndOfStream) 23 | { 24 | string[] data = reader.ReadLine().Split(' '); 25 | 26 | _nvm_link_bsr link = new _nvm_link_bsr(); 27 | link.model = Convert.ToUInt32(data[0]); 28 | link.unk = Int32.Parse(data[1].Replace("0x", ""), NumberStyles.HexNumber); 29 | link.directory = data[2].Replace('"', ' ').Replace(" ", ""); 30 | 31 | s_List[link.model] = link; 32 | } 33 | } 34 | else 35 | Logging.Log()("Wrong Ifo File Format", LogLevel.Error); 36 | } 37 | } 38 | 39 | public static _nvm_link_bsr[] Items => s_List; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SR_GameServer/Data/NavMesh/JmxRes.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.NavMesh 2 | { 3 | using System; 4 | using System.IO; 5 | using System.Collections.Generic; 6 | 7 | using SCommon; 8 | 9 | using SharpDX; 10 | 11 | public static class JmxRes 12 | { 13 | private static List<_bsr_data> s_List; 14 | 15 | static JmxRes() 16 | { 17 | s_List = new List<_bsr_data>(); 18 | } 19 | 20 | public static _bsr_data Load(uint model) 21 | { 22 | if (s_List.Exists(p => p.model == model)) 23 | return s_List.Find(p => p.model == model); 24 | 25 | _bsr_data bsr = new _bsr_data(); 26 | bsr.model = model; 27 | bsr.directory = JmxObj.Items[model].directory; 28 | 29 | if (File.Exists(Path.Combine(Environment.CurrentDirectory, "data", bsr.directory))) 30 | { 31 | using (var reader = new BinaryReader(new FileStream(Path.Combine(Environment.CurrentDirectory, "data\\" + bsr.directory), FileMode.Open, FileAccess.Read))) 32 | { 33 | reader.ReadBytes(12); //skip header 34 | reader.ReadBytes(7 * 4); //skip pointers 35 | int pointer_bbox = reader.ReadInt32(); 36 | reader.ReadBytes(5 * 4); //skip unknown dwords 37 | 38 | bsr.type = reader.ReadUInt32(); 39 | bsr.name = reader.ReadAscii(); 40 | 41 | reader.ReadBytes(48); //skip unknown bytes; 42 | 43 | if (bsr.type == 0x20002 || bsr.type == 0x20003 || bsr.type == 0x20004) 44 | { 45 | reader.BaseStream.Position = pointer_bbox; //jump 46 | bsr.mesh = reader.ReadAscii(); 47 | bsr.BBox = new BoundingBox(reader.ReadVector3(), reader.ReadVector3()); 48 | bsr.OBBox = new OrientedBoundingBox(reader.ReadVector3(), reader.ReadVector3()); 49 | } 50 | } 51 | } 52 | 53 | s_List.Add(bsr); 54 | return bsr; 55 | } 56 | 57 | public static List<_bsr_data> Items => s_List; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SR_GameServer/Data/NavMesh/Structures.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.NavMesh 2 | { 3 | using SharpDX; 4 | 5 | public struct _bms_data 6 | { 7 | public string directory; 8 | public sPoint[] Points; 9 | public sTriangle[] ObjectGround; 10 | public sLine[] InLines; 11 | public sLine[] OutLines; 12 | public BoundingBox BBox; 13 | public string[] Events; 14 | } 15 | 16 | public struct _bsr_data 17 | { 18 | public uint model; 19 | public string directory; 20 | public uint type; 21 | public string name; 22 | public string mesh; 23 | public BoundingBox BBox; 24 | public OrientedBoundingBox OBBox; 25 | } 26 | 27 | public struct _nvm_link_bsr 28 | { 29 | public uint model; 30 | public int unk; 31 | public string directory; 32 | } 33 | 34 | public struct _nvm_data 35 | { 36 | public int company; 37 | public int format; 38 | public int version; 39 | public short region; 40 | public _nvm_entry[] entries; 41 | public _nvm_zone1[] zone1; 42 | public _nvm_zone2[] zone2; 43 | public uint unk00; 44 | public _nvm_zone3[] zone3; 45 | public float[] heightmap; 46 | } 47 | 48 | public struct _nvm_entry 49 | { 50 | public uint model; 51 | public Vector3 position; 52 | public ushort collisionflag; 53 | public float yaw; 54 | public ushort uniqueid; 55 | public ushort unk00; 56 | public ushort unk01; 57 | public short region; 58 | public _nvm_entry_extra[] extra; 59 | public _bsr_data resource; 60 | public bool hasmesh; 61 | public _bms_data mesh; 62 | } 63 | 64 | public struct _nvm_entry_extra 65 | { 66 | public uint unk00; 67 | public ushort unk01; 68 | } 69 | 70 | public struct _nvm_zone1 71 | { 72 | public Vector2 min; 73 | public Vector2 max; 74 | public _nvm_zone1_extra[] extra; 75 | } 76 | 77 | public struct _nvm_zone1_extra 78 | { 79 | public ushort entryidx; 80 | } 81 | 82 | public struct _nvm_zone2 83 | { 84 | public Vector2 PointA; 85 | public Vector2 PointB; 86 | public byte flag; 87 | public byte source; 88 | public byte destination; 89 | public ushort ZoneSource; 90 | public ushort ZoneDestination; 91 | public short RegionSource; 92 | public short RegionDestination; 93 | } 94 | 95 | public struct _nvm_zone3 96 | { 97 | public Vector2 PointA; 98 | public Vector2 PointB; 99 | public byte flag; 100 | public byte source; 101 | public byte destination; 102 | public ushort ZoneSource; 103 | public ushort ZoneDestination; 104 | } 105 | 106 | public struct sPoint 107 | { 108 | public Vector3 Position; 109 | public byte Flag; 110 | } 111 | 112 | public struct sLine 113 | { 114 | public ushort PointA; 115 | public ushort PointB; 116 | public ushort NeighbourA; 117 | public ushort NeighbourB; 118 | public byte Flag; 119 | public byte unk00; 120 | } 121 | 122 | public struct sTriangle 123 | { 124 | public int ID; 125 | public ushort PointA; 126 | public ushort PointB; 127 | public ushort PointC; 128 | public ushort unk00; 129 | public byte unk01; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /SR_GameServer/Data/RefData/RefCharGen.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.RefData 2 | { 3 | using System.Collections.Generic; 4 | 5 | public class RefCharGen 6 | { 7 | #region Public Properties and Fields 8 | 9 | public int RefObjID { get; private set; } 10 | 11 | #endregion 12 | 13 | #region Constructors & Destructors 14 | 15 | public RefCharGen(int id) 16 | { 17 | RefObjID = id; 18 | } 19 | 20 | #endregion 21 | } 22 | 23 | public static class RefCharGenExtensions 24 | { 25 | public static void Load(this List list) 26 | { 27 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefCharGen WHERE Service = 1")) 28 | { 29 | while (reader.Read()) 30 | list.Add(new RefCharGen((int)reader["RefObjID"])); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SR_GameServer/Data/RefData/RefDropGold.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.RefData 2 | { 3 | public class RefDropGold 4 | { 5 | #region Public Properties and Fields 6 | 7 | public byte MonLevel; 8 | public double DropProb; 9 | public int GoldMin, GoldMax; 10 | 11 | #endregion 12 | } 13 | 14 | public static class RefDropGoldExtensions 15 | { 16 | public static void Load(this RefDropGold[] list) 17 | { 18 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefDropGold")) 19 | { 20 | while (reader.Read()) 21 | { 22 | byte tmp_monlvl = (byte)reader["MonLevel"]; 23 | list[tmp_monlvl] = new RefDropGold(); 24 | list[tmp_monlvl].MonLevel = tmp_monlvl; 25 | list[tmp_monlvl].DropProb = (float)reader["DropProb"]; 26 | list[tmp_monlvl].GoldMin = (int)reader["GoldMin"]; 27 | list[tmp_monlvl].GoldMax = (int)reader["GoldMax"]; 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SR_GameServer/Data/RefData/RefFmnTidGroupMap.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.RefData 2 | { 3 | using System.Collections.Generic; 4 | 5 | public class RefFmnTidGroupMap 6 | { 7 | #region Public Properties and Fields 8 | 9 | public int TidGroup; 10 | public byte TID1, TID2, TID3, TID4; 11 | 12 | #endregion 13 | } 14 | 15 | public static class RefFmnTidGroupExtensions 16 | { 17 | public static void Load(this List list) 18 | { 19 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefFmnTidGroupMap WHERE Service = 1")) 20 | { 21 | while (reader.Read()) 22 | { 23 | int dmp_id = (int)reader["TidGroupID"]; 24 | RefFmnTidGroupMap tid = new RefFmnTidGroupMap(); 25 | tid.TidGroup = dmp_id; 26 | tid.TID1 = (byte)reader["TypeID1"]; 27 | tid.TID2 = (byte)reader["TypeID2"]; 28 | tid.TID3 = (byte)reader["TypeID3"]; 29 | tid.TID4 = (byte)reader["TypeID4"]; 30 | list.Add(tid); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SR_GameServer/Data/RefData/RefLevel.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.RefData 2 | { 3 | public class RefLevel 4 | { 5 | #region Public Properties and Fields 6 | 7 | public byte Lvl; 8 | public long Exp_C; 9 | public int Exp_M, Cost_M, Cost_ST, GUST_Mob_Exp, JobExp_Trader, JobExp_Robber, JobExp_Hunter; 10 | 11 | #endregion 12 | } 13 | 14 | public static class RefLevelExtensions 15 | { 16 | public static void Load(this RefLevel[] list) 17 | { 18 | list[0] = new RefLevel(); //dummy 19 | 20 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefLevel")) 21 | { 22 | while (reader.Read()) 23 | { 24 | byte dmp_lvl = (byte)reader["Lvl"]; 25 | list[dmp_lvl] = new RefLevel(); 26 | list[dmp_lvl].Lvl = dmp_lvl; 27 | list[dmp_lvl].Exp_C = (long)reader["Exp_C"]; 28 | list[dmp_lvl].Exp_M = (int)reader["Exp_M"]; 29 | list[dmp_lvl].Cost_M = (int)reader["Cost_M"]; 30 | list[dmp_lvl].Cost_ST = (int)reader["Cost_ST"]; 31 | list[dmp_lvl].GUST_Mob_Exp = (int)reader["GUST_Mob_Exp"]; 32 | list[dmp_lvl].JobExp_Trader = (int)reader["JobExp_Trader"]; 33 | list[dmp_lvl].JobExp_Robber = (int)reader["JobExp_Robber"]; 34 | list[dmp_lvl].JobExp_Hunter = (int)reader["JobExp_Hunter"]; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SR_GameServer/Data/RefData/RefRegion.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.RefData 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public class RefRegion 7 | { 8 | #region Public Properties and Fields 9 | 10 | public ushort Region; 11 | public byte X, Z; 12 | public string ContinentName, AreaName; 13 | public bool IsBattleField; 14 | public int Climate, MaxCapacity, AssocObjID, AssocServer; 15 | public string AssocFile256; 16 | 17 | #endregion 18 | } 19 | 20 | public class RefRegionBindAssocServer 21 | { 22 | #region Public Properties and Fields 23 | 24 | public string AreaName; 25 | public byte AssocServer; 26 | 27 | #endregion 28 | } 29 | 30 | public static class RefRegionExtensions 31 | { 32 | public static void Load(this RefRegion[] list) 33 | { 34 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefRegion")) 35 | { 36 | while (reader.Read()) 37 | { 38 | if (Globals.Ref.RegionBindAssocServer.Exists(p => p.AreaName == (string)reader["ContinentName"] && p.AssocServer != 0)) 39 | { 40 | ushort region = Convert.ToUInt16((short)reader["wRegionID"]); 41 | list[region] = new RefRegion(); 42 | list[region].Region = region; 43 | list[region].X = (byte)reader["X"]; 44 | list[region].Z = (byte)reader["Z"]; 45 | list[region].ContinentName = (string)reader["ContinentName"]; 46 | list[region].AreaName = (string)reader["AreaName"]; 47 | list[region].IsBattleField = Convert.ToBoolean((byte)reader["IsBattleField"]); 48 | list[region].Climate = (int)reader["Climate"]; 49 | list[region].MaxCapacity = (int)reader["MaxCapacity"]; 50 | list[region].AssocObjID = (int)reader["AssocObjID"]; 51 | list[region].AssocServer = Globals.Ref.RegionBindAssocServer.Find(p => p.AreaName == (string)reader["ContinentName"] && p.AssocServer != 0).AssocServer; 52 | list[region].AssocFile256 = (string)reader["AssocFile256"]; 53 | } 54 | } 55 | } 56 | } 57 | 58 | public static void Load(this List list) 59 | { 60 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefRegionBindAssocServer")) 61 | { 62 | while (reader.Read()) 63 | { 64 | list.Add(new RefRegionBindAssocServer 65 | { 66 | AreaName = (string)reader["AreaName"], 67 | AssocServer = (byte)reader["AssocServer"] 68 | }); 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SR_GameServer/Data/RefData/RefShop.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.RefData 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | using SCommon; 7 | 8 | public class RefShop 9 | { 10 | public int ID, ShopType, NpcID; 11 | public string CodeName128; 12 | public _shop_tab[] Tabs; 13 | 14 | public struct _shop_tab 15 | { 16 | public int ID; 17 | public List<_shop_item> Items; 18 | } 19 | 20 | public struct _shop_item 21 | { 22 | public int RefItemID; 23 | public int GoldPrice; 24 | public int SilkPrice; 25 | public byte OptLevel; 26 | 27 | public _shop_item(int rid, int gp, int sp, byte opt) 28 | { 29 | RefItemID = rid; 30 | if (gp <= 0) GoldPrice = Globals.Ref.ObjItem[rid].Price; 31 | else GoldPrice = gp; 32 | SilkPrice = sp; 33 | OptLevel = opt; 34 | } 35 | } 36 | } 37 | 38 | public static class RefShopExtensions 39 | { 40 | public static void Load(this List list) 41 | { 42 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefShop WHERE Service = 1 ORDER BY ID")) 43 | { 44 | while (reader.Read()) 45 | { 46 | var shop = new RefShop(); 47 | shop.NpcID = (int)reader["NPCID"]; 48 | shop.ID = (int)reader["ID"]; 49 | shop.ShopType = (int)reader["ShopType"]; 50 | shop.Tabs = new RefShop._shop_tab[10]; 51 | for (byte b = 0; b < 10; b++) 52 | { 53 | int tabid = (int)reader[String.Format("TabID_{0}", b + 1)]; 54 | if (tabid > 0) 55 | { 56 | shop.Tabs[b] = new RefShop._shop_tab(); 57 | shop.Tabs[b].ID = tabid; 58 | shop.Tabs[b].Items = new List(); 59 | using (var reader2 = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefShopGoods WHERE AssocTabID = {0} AND Service = 1", tabid)) 60 | { 61 | while (reader2.Read()) 62 | shop.Tabs[b].Items.Add(new RefShop._shop_item((int)reader2["ItemToSell"], (int)reader2["PriceGold"], (int)reader2["PriceSilk"], (byte)reader2["OptLevel"])); 63 | } 64 | } 65 | } 66 | list.Add(shop); 67 | } 68 | } 69 | Logging.Log()("Shops are loaded"); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SR_GameServer/Data/RefData/RefTeleport.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data.RefData 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | 7 | public class RefTeleport 8 | { 9 | public int ID, AssocRefObjID; 10 | public string CodeName128, ZoneName128; 11 | public short GenRegionID, GenPos_X, GenPos_Y, GenPos_Z, GenAreaRadius; 12 | public byte CanBeResurrectPos, CanGotoResurrectPos; 13 | } 14 | 15 | public class RefTeleportBuilding : RefObjCommon 16 | { 17 | public RefTeleport TeleportData; 18 | } 19 | 20 | public class RefTeleportLink 21 | { 22 | public int OwnerTeleport, TargetTeleport, Fee; 23 | public byte RestrictBindMethod, CheckResult; 24 | public _teleport_restrict[] Restrict; 25 | 26 | public RefTeleportLink() 27 | { 28 | Restrict = new _teleport_restrict[5]; 29 | } 30 | } 31 | 32 | public static class RefTeleportExtensions 33 | { 34 | public static void Load(this List list) 35 | { 36 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefTeleport ORDER BY ID")) 37 | { 38 | while (reader.Read()) 39 | { 40 | var t = new RefTeleport(); 41 | t.ID = (int)reader["ID"]; 42 | t.AssocRefObjID = (int)reader["AssocRefObjID"]; 43 | t.CodeName128 = (string)reader["CodeName128"]; 44 | t.ZoneName128 = (string)reader["ZoneName128"]; 45 | t.GenRegionID = (short)reader["GenRegionID"]; 46 | t.GenPos_X = (short)reader["GenPos_X"]; 47 | t.GenPos_Y = (short)reader["GenPos_Y"]; 48 | t.GenPos_Z = (short)reader["GenPos_Z"]; 49 | t.GenAreaRadius = (short)reader["GenAreaRadius"]; 50 | t.CanBeResurrectPos = (byte)reader["CanBeResurrectPos"]; 51 | t.CanGotoResurrectPos = (byte)reader["CanGotoResurrectPos"]; 52 | list.Add(t); 53 | } 54 | } 55 | } 56 | 57 | public static void Load(this RefTeleportBuilding[] list) 58 | { 59 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefTeleportBuilding ORDER BY ID")) 60 | { 61 | while (reader.Read()) 62 | { 63 | int dmp_id = (int)reader["ID"]; 64 | list[dmp_id] = new RefTeleportBuilding(); 65 | list[dmp_id].ID = dmp_id; 66 | list[dmp_id].CodeName128 = (string)reader["CodeName128"]; 67 | list[dmp_id].ObjName128 = (string)reader["ObjName128"]; 68 | list[dmp_id].OrgObjCodeName128 = (string)reader["OrgObjCodeName128"]; 69 | list[dmp_id].NameStrID128 = (string)reader["NameStrID128"]; 70 | list[dmp_id].DescStrID128 = (string)reader["DescStrID128"]; 71 | list[dmp_id].Bionic = (byte)reader["Bionic"]; 72 | list[dmp_id].TypeID1 = (byte)reader["TypeID1"]; 73 | list[dmp_id].TypeID2 = (byte)reader["TypeID2"]; 74 | list[dmp_id].TypeID3 = (byte)reader["TypeID3"]; 75 | list[dmp_id].TypeID4 = (byte)reader["TypeID4"]; 76 | list[dmp_id].Country = (byte)reader["Country"]; 77 | list[dmp_id].Rarity = (byte)reader["Rarity"]; 78 | list[dmp_id].CanTrade = (byte)reader["CanTrade"]; 79 | list[dmp_id].CanSell = (byte)reader["CanSell"]; 80 | list[dmp_id].CanBuy = (byte)reader["CanBuy"]; 81 | list[dmp_id].CanBorrow = (byte)reader["CanBorrow"]; 82 | list[dmp_id].CanDrop = (byte)reader["CanDrop"]; 83 | list[dmp_id].CanPick = (byte)reader["CanPick"]; 84 | list[dmp_id].CanRepair = (byte)reader["CanRepair"]; 85 | list[dmp_id].CanRevive = (byte)reader["CanRevive"]; 86 | list[dmp_id].CanUse = (byte)reader["CanUse"]; 87 | list[dmp_id].CanThrow = (byte)reader["CanThrow"]; 88 | list[dmp_id].DecayTime = (int)reader["DecayTime"]; 89 | list[dmp_id].Price = (int)reader["Price"]; 90 | list[dmp_id].CostRepair = (int)reader["CostRepair"]; 91 | list[dmp_id].CostRevive = (int)reader["CostRevive"]; 92 | list[dmp_id].CostBorrow = (int)reader["CostBorrow"]; 93 | list[dmp_id].KeepingFee = (int)reader["KeepingFee"]; 94 | list[dmp_id].SellPrice = (int)reader["SellPrice"]; 95 | list[dmp_id].ReqLevelType1 = (int)reader["ReqLevelType1"]; 96 | list[dmp_id].ReqLevelType2 = (int)reader["ReqLevelType2"]; 97 | list[dmp_id].ReqLevel1 = (byte)reader["ReqLevel1"]; 98 | list[dmp_id].ReqLevel2 = (byte)reader["ReqLevel2"]; 99 | list[dmp_id].MaxContain = (int)reader["MaxContain"]; 100 | list[dmp_id].RegionID = (short)reader["RegionID"]; 101 | list[dmp_id].Dir = (short)reader["Dir"]; 102 | list[dmp_id].OffsetX = (short)reader["OffsetX"]; 103 | list[dmp_id].OffsetY = (short)reader["OffsetY"]; 104 | list[dmp_id].OffsetZ = (short)reader["OffsetZ"]; 105 | list[dmp_id].Speed1 = (short)reader["Speed1"]; 106 | list[dmp_id].Speed2 = (short)reader["Speed2"]; 107 | list[dmp_id].Scale = (int)reader["Scale"]; 108 | list[dmp_id].BCHeight = (short)reader["BCHeight"]; 109 | list[dmp_id].BCRadius = (short)reader["BCRadius"]; 110 | list[dmp_id].EventID = (int)reader["EventID"]; 111 | list[dmp_id].AssocFileObj128 = (string)reader["AssocFileObj128"]; 112 | list[dmp_id].AssocFileDrop128 = (string)reader["AssocFileDrop128"]; 113 | list[dmp_id].AssocFileIcon128 = (string)reader["AssocFileIcon128"]; 114 | list[dmp_id].AssocFile1_128 = (string)reader["AssocFile1_128"]; 115 | list[dmp_id].AssocFile2_128 = (string)reader["AssocFile2_128"]; 116 | list[dmp_id].TeleportData = Globals.Ref.TeleportData.FirstOrDefault(p => p != null && p.AssocRefObjID == dmp_id); 117 | } 118 | } 119 | } 120 | 121 | public static void Load(this List list) 122 | { 123 | using (var reader = Globals.ShardDB.ExecuteReader("SELECT * FROM _RefTeleportLink")) 124 | { 125 | while (reader.Read()) 126 | { 127 | RefTeleportLink l = new RefTeleportLink(); 128 | l.OwnerTeleport = (int)reader["OwnerTeleport"]; 129 | l.TargetTeleport = (int)reader["TargetTeleport"]; 130 | l.Fee = (int)reader["Fee"]; 131 | l.RestrictBindMethod = (byte)reader["RestrictBindMethod"]; 132 | l.CheckResult = (byte)reader["CheckResult"]; 133 | for (byte b = 0; b < 5; b++) 134 | { 135 | l.Restrict[b] = new _teleport_restrict(); 136 | l.Restrict[b].Restrict = (int)reader[String.Format("Restrict{0}", b + 1)]; 137 | l.Restrict[b].Data1 = (int)reader[String.Format("Data{0}_1", b + 1)]; 138 | l.Restrict[b].Data2 = (int)reader[String.Format("Data{0}_2", b + 1)]; 139 | } 140 | list.Add(l); 141 | } 142 | } 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /SR_GameServer/Data/Structures.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Data 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | public struct AccountInfo 7 | { 8 | public int SID; 9 | public string StrUserID; 10 | public string Password; 11 | public AuthType Auth; 12 | public List> Characters; //charid, index, deleting 13 | } 14 | 15 | public struct _teleport_restrict 16 | { 17 | public int Restrict; 18 | public int Data1, Data2; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SR_GameServer/Enumarations.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | using System; 4 | 5 | public enum GObjType 6 | { 7 | GObjMob, 8 | GObjItem, 9 | GObjNPC, 10 | GObjChar, 11 | GObjCOS, 12 | GObjStructure, 13 | } 14 | 15 | public enum WalkState 16 | { 17 | Walking, 18 | Running, 19 | Momentum = 7, 20 | } 21 | 22 | public enum MovementType 23 | { 24 | NotMoveable, 25 | NotMoving, 26 | Moving, 27 | Seat, 28 | //0 = None, 2 = Walking, 3 = Running, 4 = Sitting << to do: try 29 | } 30 | 31 | public enum LifeState 32 | { 33 | None, 34 | Alive, 35 | Dead, 36 | } 37 | 38 | public enum StatusType 39 | { 40 | None, 41 | Hwan, 42 | Untouchable, 43 | GameMasterInvincible, 44 | GameMasterInvisible, 45 | Stealth, 46 | Invisible, 47 | } 48 | 49 | public enum AttackType 50 | { 51 | None, 52 | Normal, 53 | Skill, 54 | } 55 | 56 | public enum GObjMobRarity 57 | { 58 | General, 59 | Champion, 60 | Unknown, 61 | Unique, 62 | Giant, 63 | Titan, 64 | Elite, 65 | } 66 | 67 | [Flags] 68 | public enum GObjTalkFlags 69 | { 70 | None = 0, 71 | Unknown1 = 1, 72 | Talkable = 2, 73 | } 74 | 75 | public enum PKType 76 | { 77 | None, 78 | Attacked, 79 | Killed, 80 | } 81 | 82 | [Flags] 83 | public enum GObjUpdateType 84 | { 85 | HP = 1, 86 | MP = 2, 87 | BadEffect = 4 88 | } 89 | 90 | [Flags] 91 | public enum GObjUpdateSource 92 | { 93 | None = 0, 94 | Damage = 1, 95 | DotDamage = 2, 96 | Consume = 4, 97 | Reverse = 8, 98 | Regeneration = 16, 99 | Potion = 32, 100 | Heal = 64, 101 | Unknown128 = 128, //TODO: RESEARCH 102 | BadEffect = 256, 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /SR_GameServer/Formula.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | using System; 4 | using System.Runtime.CompilerServices; 5 | 6 | using SharpDX; 7 | 8 | public static class Formula 9 | { 10 | public const byte REGION_SCALE = 128; 11 | public const byte WORLD_SCALE = 10; 12 | public const byte REGION_HEIGHT = 192; 13 | public const byte REGION_WIDTH = 192; 14 | public const byte X_START_SECTOR = 46; 15 | public const byte Z_START_SECTOR = 46; 16 | 17 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 18 | public static int BaseMaxHealthManaByStats(byte level, int stats) 19 | { 20 | return (int)(Math.Pow(1.02f, (level - 1)) * stats * 10); 21 | } 22 | 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static int BaseDefByStats(int stats) 25 | { 26 | return (int)(0.4f * stats); 27 | } 28 | 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public static int BaseMinAtkByStats(int stats) 31 | { 32 | return (int)(0.45f * stats); 33 | } 34 | 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | public static int BaseMaxAtkByStats(int stats) 37 | { 38 | return (int)(0.65f * stats); 39 | } 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static int PhyBalance(byte level, int stats) 43 | { 44 | return (int)(100f - (100f * 2f / 3f * ((28f + level * 4f) - stats) / (28f + level * 4f))); 45 | } 46 | 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public static int MagBalance(byte level, int stats) 49 | { 50 | return (int)(100f * stats / (28f + level * 4f)); 51 | } 52 | 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | public static byte GetSectorX(short region) 55 | { 56 | return (byte)(region % REGION_SCALE); 57 | } 58 | 59 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 60 | public static byte GetSectorZ(short region) 61 | { 62 | return (byte)((region - GetSectorX(region)) / REGION_SCALE); 63 | } 64 | 65 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 66 | public static short MakeRegion(byte x, byte z) 67 | { 68 | return (short)(z * REGION_SCALE + x); 69 | } 70 | 71 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 72 | public static float GetRegionalX(short region, float x) 73 | { 74 | return (x - (GetSectorX(region) - X_START_SECTOR) * REGION_HEIGHT) * WORLD_SCALE; 75 | } 76 | 77 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 78 | public static float GetRegionalZ(short region, float z) 79 | { 80 | return (z - (GetSectorZ(region) - Z_START_SECTOR) * REGION_WIDTH) * WORLD_SCALE; 81 | } 82 | 83 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 84 | public static float GetWorldX(short region, float x) 85 | { 86 | return (GetSectorX(region) - X_START_SECTOR) * REGION_HEIGHT + (x / WORLD_SCALE); 87 | } 88 | 89 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 90 | public static float GetWorldZ(short region, float z) 91 | { 92 | return (GetSectorZ(region) - Z_START_SECTOR) * REGION_WIDTH + (z / WORLD_SCALE); 93 | } 94 | 95 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 96 | public static short GetRegion(float x, float z) 97 | { 98 | return MakeRegion((byte)(Math.Floor(x / REGION_HEIGHT) + X_START_SECTOR), (byte)(Math.Floor(z / REGION_WIDTH) + Z_START_SECTOR)); 99 | } 100 | 101 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 102 | public static bool IsInSightRegion(short r1, short r2) 103 | { 104 | 105 | /* 106 | ************************* 107 | * * * * 108 | * +127 * +128 * +129 * 109 | * * * * 110 | ************************* 111 | * * * * 112 | * -1 * 0 * +1 * 113 | * * * * 114 | ************************* 115 | * * * * 116 | * -129 * -128 * -127 * 117 | * * * * 118 | ************************* 119 | */ 120 | int region_gap = Math.Abs(r1 - r2); 121 | return (region_gap >= REGION_SCALE - 1 && region_gap <= REGION_SCALE + 1) || region_gap == 1 || region_gap == 0; 122 | } 123 | 124 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 125 | public static float Angle(Vector3 p1, Vector3 p2) 126 | { 127 | return (float)(Math.Atan2(p2.Z - p1.Z, p2.X - p1.X) * 180 / Math.PI * 182); 128 | } 129 | 130 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 131 | public static Vector2 ToGameWorld(this Vector3 v, short r) 132 | { 133 | return new Vector2(GetWorldX(r, v.X), GetWorldZ(r, v.Z)); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /SR_GameServer/GObjItem.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | using System; 4 | 5 | using SCommon; 6 | 7 | public class GObjItem : GObj 8 | { 9 | #region Public Properties and Fields 10 | 11 | public int m_data; 12 | public byte m_optLevel; 13 | public GObjChar m_owner; 14 | 15 | public bool IsGold => Data.Globals.Ref.ObjItem[m_model].Type == Data.ItemType.GOLD; 16 | public bool IsQuest => Data.Globals.Ref.ObjItem[m_model].Type == Data.ItemType.EVENT_ITEM; 17 | public bool IsGoods => Data.Globals.Ref.ObjItem[m_model].Type == Data.ItemType.ETC_TRADE_ITEM; 18 | 19 | #endregion 20 | 21 | #region Constructors & Destructors 22 | 23 | public GObjItem() 24 | : base (GObjType.GObjItem) 25 | { 26 | StartDisappear(60000); 27 | } 28 | 29 | #endregion 30 | 31 | #region Private Methods 32 | 33 | protected override void DisappearTimer_Callback(object sender, object state) 34 | { 35 | base.DisappearTimer_Callback(sender, state); 36 | m_owner = null; 37 | } 38 | 39 | #endregion 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SR_GameServer/GObjMob.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | using System; 4 | 5 | using SCommon; 6 | 7 | using SharpDX; 8 | 9 | public class GObjMob : GObj 10 | { 11 | #region Public Properties and Fields 12 | 13 | public GObjMobRarity m_rarity; 14 | public int m_nestId; 15 | public short m_generatedRegion; 16 | public Vector3 m_generatedPosition; 17 | 18 | #region Stats 19 | 20 | public volatile int m_bonusPhyDefPercent; 21 | public volatile int m_bonusMagDefPercent; 22 | public volatile int m_bonusPhyAtkPercent; 23 | public volatile int m_bonusMagAtkPercent; 24 | public volatile int m_bonusParryPercent; 25 | public volatile int m_bonusHitPercent; 26 | public volatile int m_bonusMaxHealthPercent; 27 | public volatile int m_bonusBlockRatioPercent; 28 | public volatile int m_bonusPhyDef; 29 | public volatile int m_bonusMagDef; 30 | public volatile int m_bonusPhyAtk; 31 | public volatile int m_bonusMagAtk; 32 | public volatile int m_bonusParryRate; 33 | public volatile int m_bonusHitRate; 34 | public volatile int m_bonusMaxHealth; 35 | public volatile int m_bonusBlockRatio; 36 | public volatile int m_currentHealthPoints; 37 | //absorb values doesnt effect def values but absorbs incoming raw dmg by % 38 | public volatile int m_phyAbsorbPercent; 39 | public volatile int m_magAbsorbPercent; 40 | //balance values doesnt effect atk values but modifies outgoing raw dmg by % 41 | public volatile int m_phyBalancePercent; 42 | public volatile int m_magBalancePercent; 43 | 44 | public float TotalPhyDef => (Data.Globals.Ref.ObjChar[this.m_model].PD * StatsMultipler + this.m_bonusPhyDef) * (1.0f + this.m_bonusPhyDefPercent / 100f); 45 | public float TotalMagDef => (Data.Globals.Ref.ObjChar[this.m_model].MD * StatsMultipler + this.m_bonusMagDef) * (1.0f + this.m_bonusMagDefPercent / 100f); 46 | public float TotalPhyAtk => (Data.Globals.Ref.ObjChar[this.m_model].PAR * StatsMultipler + this.m_bonusPhyAtk) * (1.0f + this.m_bonusPhyAtkPercent / 100f); 47 | public float TotalMagAtk => (Data.Globals.Ref.ObjChar[this.m_model].MAR * StatsMultipler + this.m_bonusMagAtk) * (1.0f + this.m_bonusMagAtkPercent / 100f); 48 | public float TotalParryRate => (Data.Globals.Ref.ObjChar[this.m_model].ER * StatsMultipler + this.m_bonusParryRate) * (1.0f + this.m_bonusParryPercent / 100f); 49 | public float TotalHitRate => (Data.Globals.Ref.ObjChar[this.m_model].HR * StatsMultipler + this.m_bonusHitRate) * (1.0f + this.m_bonusHitPercent / 100f); 50 | public float MaxHP => (Data.Globals.Ref.ObjChar[this.m_model].MaxHP * HealthMultipler + this.m_bonusMaxHealth) * (1.0f + this.m_bonusMaxHealthPercent / 100f); 51 | public float BlockRatio => (Data.Globals.Ref.ObjChar[this.m_model].BR * StatsMultipler + this.m_bonusBlockRatio) * (1.0f + this.m_bonusBlockRatioPercent / 100f); 52 | 53 | #endregion 54 | public AttackType m_attackType; 55 | 56 | #endregion 57 | 58 | #region Constructors & Destructors 59 | 60 | public GObjMob() 61 | : base (GObjType.GObjMob) 62 | { 63 | 64 | } 65 | 66 | #endregion 67 | 68 | #region Private Properties and Fields 69 | 70 | private int HealthMultipler 71 | { 72 | get 73 | { 74 | switch (m_rarity) 75 | { 76 | case GObjMobRarity.Champion: 77 | return 10; 78 | 79 | case GObjMobRarity.Unique: 80 | return 20; 81 | 82 | case GObjMobRarity.Giant: 83 | return 20; 84 | default: 85 | return 1; 86 | } 87 | } 88 | } 89 | 90 | private int StatsMultipler 91 | { 92 | get 93 | { 94 | switch (m_rarity) 95 | { 96 | case GObjMobRarity.Champion: 97 | return 2; 98 | 99 | case GObjMobRarity.Unique: 100 | return 5; 101 | 102 | case GObjMobRarity.Giant: 103 | return 4; 104 | default: 105 | return 1; 106 | } 107 | } 108 | } 109 | 110 | #endregion 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /SR_GameServer/GObjNPC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SR_GameServer 8 | { 9 | public class GObjNPC : GObj 10 | { 11 | #region Public Properties and Fields 12 | 13 | public GObjTalkFlags m_talkFlag; 14 | public List m_talkOptions; 15 | 16 | #endregion 17 | 18 | #region Constructors and Destructors 19 | 20 | public GObjNPC() 21 | : base (GObjType.GObjNPC) 22 | { 23 | m_talkOptions = new List(); 24 | } 25 | 26 | #endregion 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SR_GameServer/Program.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | using System; 4 | using System.Threading; 5 | using System.Collections.Generic; 6 | 7 | using SCore; 8 | 9 | using SCommon; 10 | 11 | internal class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | #region Assert Debug Mode 16 | #if DEBUG 17 | Logging.Log()("Debug mode is active", LogLevel.Info); 18 | #endif 19 | #endregion 20 | 21 | #region Initialize Services 22 | 23 | TimerService.Initialize(); 24 | Logging.Log()("Timer service has initialized", LogLevel.Success); 25 | 26 | PacketProcessor.FillTable(); 27 | Logging.Log()("Packet Processor has initialized", LogLevel.Success); 28 | 29 | #endregion 30 | 31 | #region Connect to Database Services 32 | 33 | if (Data.Globals.ConnectGlobalDB()) 34 | Logging.Log()("Connected to global db", LogLevel.Notify); 35 | else 36 | Logging.Log()("Cannot connect to global db", LogLevel.Error); 37 | 38 | if (Data.Globals.ConnectShardDB()) 39 | Logging.Log()("Connected to shard db", LogLevel.Notify); 40 | else 41 | Logging.Log()("Cannot connect to shard db", LogLevel.Error); 42 | 43 | //truncate the sessions 44 | Data.Globals.GlobalDB.ExecuteCommand("TRUNCATE TABLE _ActiveSessions"); 45 | 46 | #endregion 47 | 48 | #region Load Configs 49 | 50 | if (Data.Globals.LoadConfigTable()) 51 | Logging.Log()("Server config has loaded", LogLevel.Notify); 52 | else 53 | Logging.Log()("Cannot load server config", LogLevel.Error); 54 | 55 | #endregion 56 | 57 | #region Load RefData 58 | 59 | Data.Globals.LoadRefData(); 60 | 61 | #endregion 62 | 63 | #region Start Services 64 | 65 | Data.Globals.SRGameService = new SRGame(Data.Globals.GetConfigValue("GameServerIPAddress"), Data.Globals.GetConfigValue("GameServerPort")); 66 | Data.Globals.SRGameService.UpdateServiceState(true); 67 | Logging.Log()("SRGame Service has started", LogLevel.Info); 68 | 69 | #endregion 70 | 71 | #region Start GC Collector Thread 72 | 73 | new Thread(new ThreadStart(() => 74 | { 75 | while (true) 76 | { 77 | GC.Collect(); 78 | Thread.Sleep(10000); 79 | } 80 | })).Start(); 81 | 82 | #endregion 83 | 84 | #region GameWorld Status Thread 85 | 86 | new Thread(new ThreadStart(() => 87 | { 88 | while (true) 89 | { 90 | long c = Data.Globals.GObjList == null ? 0 : Data.Globals.GObjList.Count; 91 | Console.Title = String.Format("GObj Count: {0}", c); 92 | Thread.Sleep(1000); 93 | } 94 | })).Start(); 95 | 96 | #endregion 97 | 98 | #region Console command helper 99 | 100 | while (true) 101 | { 102 | Console.Write("srgame@{0}:~# ", Data.Globals.GetConfigValue("GameServerIPAddress")); 103 | var commands = Console.ReadLine().ToLower().Split(' '); 104 | switch (commands[0]) 105 | { 106 | case "exit": 107 | Environment.Exit(0); 108 | break; 109 | case "clear": 110 | Console.Clear(); 111 | break; 112 | case "enablepacketlogging": 113 | Logging.EnablePacketLogging = Convert.ToBoolean(commands[1]); 114 | Logging.Log()(String.Format("Set EnablePacketLogging = {0}", Logging.EnablePacketLogging ? "TRUE" : "FALSE"), LogLevel.Success); 115 | break; 116 | case "connectioncount": 117 | Logging.Log()(String.Format("Current Active Connections Count is {0}", Data.Globals.SRGameService.ActiveConnectionCount), LogLevel.Info); 118 | break; 119 | } 120 | Thread.Sleep(1); 121 | } 122 | 123 | #endregion 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /SR_GameServer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SR_GameServer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SR_GameServer")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c5000548-d941-4ebf-b580-b0b57e8a9250")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SR_GameServer/SQLTableMapping.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | public enum _Char 4 | { 5 | CharID, 6 | CharName16, 7 | RefObjID, 8 | Scale, 9 | CurLevel, 10 | MaxLevel, 11 | CurHP, 12 | CurMP, 13 | ExpOffset, 14 | SExpOffset, 15 | Strength, 16 | Intellect, 17 | LatestRegion, 18 | PosX, 19 | PosY, 20 | PosZ, 21 | Angle, 22 | RemainGold, 23 | RemainSkillPoint, 24 | RemainStatPoint, 25 | RemainHwanCount, 26 | Deleting, 27 | DeleteEndTime, 28 | TraderLvl, 29 | TraderExp, 30 | HunterLvl, 31 | HunterExp, 32 | ThiefLvl, 33 | ThiefExp, 34 | GGData, 35 | AppointedTeleport, 36 | Deleted, 37 | FieldCount, 38 | } 39 | 40 | public enum _CharSkillMastery 41 | { 42 | CharID, 43 | MasteryID, 44 | Level, 45 | FieldCount, 46 | } 47 | 48 | public enum _CharSkill 49 | { 50 | CharID, 51 | SkillID, 52 | Enabled, 53 | FieldCount, 54 | } 55 | 56 | public enum _Inventory 57 | { 58 | CharID, 59 | Slot, 60 | ItemID, 61 | FieldCount, 62 | } 63 | 64 | public enum _Items 65 | { 66 | ID64, 67 | RefItemID, 68 | OptLevel, 69 | Variance, 70 | Data, 71 | CreaterName, 72 | MagParamCount, 73 | MagParam1, 74 | MagParam2, 75 | MagParam3, 76 | MagParam4, 77 | MagParam5, 78 | MagParam6, 79 | MagParam7, 80 | MagParam8, 81 | MagParam9, 82 | MagParam10, 83 | MagParam11, 84 | MagParam12, 85 | ItemSerial, 86 | FieldCount, 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /SR_GameServer/SRGame.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | using System; 4 | using System.Threading; 5 | 6 | using SCommon; 7 | using SCommon.Networking; 8 | using SCommon.Security; 9 | 10 | internal class SRGame 11 | { 12 | #region Private Properties and Fields 13 | 14 | /// 15 | /// The server's ip address 16 | /// 17 | private string m_IPAddress; 18 | 19 | /// 20 | /// The server's port 21 | /// 22 | private int m_Port; 23 | 24 | /// 25 | /// The tcp server 26 | /// 27 | private TCPServer m_Server; 28 | 29 | /// 30 | /// The pool for class 31 | /// 32 | private ObjectPool m_ClientContextPool; 33 | 34 | #endregion 35 | 36 | #region Constructors and Destructors 37 | 38 | public SRGame(string ip, int port) 39 | { 40 | m_IPAddress = ip; 41 | m_Port = port; 42 | m_ClientContextPool = new ObjectPool(() => new ClientContext(), () => m_ClientContextPool.Count > 200); 43 | 44 | Data.NavMesh.JmxNavmesh.Load(); 45 | Services.UniqueID.Initialize(); 46 | GameWorld.AIManager.Initialize(); 47 | } 48 | 49 | #endregion 50 | 51 | #region Public Properties and Fileds 52 | 53 | public int ActiveConnectionCount => Interlocked.Exchange(ref m_Server.m_ConnectionCount, m_Server.m_ConnectionCount); 54 | 55 | #endregion 56 | 57 | #region Public Methods 58 | 59 | /// 60 | /// Updates the gateway service's state 61 | /// 62 | /// 63 | public void UpdateServiceState(bool state) 64 | { 65 | if (state) 66 | { 67 | //initialize the server and start the tcp service 68 | if (m_Server == null) 69 | { 70 | m_Server = new TCPServer(m_IPAddress, m_Port, SecurityFlags.Blowfish | SecurityFlags.SecurityBytes); 71 | TCPServer.OnNewConnection += Gateway_NewConnection; 72 | SocketContext.OnPacketReceived += SocketContext_PacketReceived; 73 | SocketContext.OnLostConnection += SocketContext_ConnectionLost; 74 | SocketContext.OnPacketSent += SocketContext_PacketSent; 75 | m_Server.StartService(); 76 | } 77 | } 78 | else 79 | { 80 | // 81 | } 82 | } 83 | 84 | #endregion 85 | 86 | #region Private Methods 87 | 88 | /// 89 | /// The OnNewConnection event. 90 | /// 91 | /// The client context. 92 | /// The socket context. 93 | private void Gateway_NewConnection(object sender, SocketContext context) 94 | { 95 | #if DEBUG 96 | Logging.Log()(String.Format("A new connection has arrived. (SocketContext Hash Code:{0:X8})", context.GetHashCode()), LogLevel.Info); 97 | #endif 98 | ClientContext client = m_ClientContextPool.GetObject(); 99 | client.SetContext(context); 100 | 101 | context.SetContext(client); 102 | } 103 | 104 | /// 105 | /// The OnPacketReceived event. 106 | /// 107 | /// The client context. 108 | /// The received packet. 109 | private void SocketContext_PacketReceived(object sender, Packet packet) 110 | { 111 | Func fn; 112 | ClientContext client = (ClientContext)((SocketContext)sender).Context; 113 | 114 | client.LastPingTick = Environment.TickCount; 115 | 116 | if (PacketProcessor.OpcodeMap[packet.Opcode] != null) 117 | fn = PacketProcessor.OpcodeMap[packet.Opcode]; 118 | else 119 | fn = PacketProcessor.OpcodeMap[0]; 120 | 121 | if (!fn(client, packet)) 122 | client.Disconnect(); 123 | } 124 | 125 | /// 126 | /// The OnLostConnection event. 127 | /// 128 | /// The client context. 129 | /// The event args. 130 | private void SocketContext_ConnectionLost(object sender, EventArgs args) 131 | { 132 | #if DEBUG 133 | Logging.Log()(String.Format("A connection has dropped. (SocketContext Hash Code:{0:X8})", sender.GetHashCode()), LogLevel.Info); 134 | #endif 135 | ClientContext client = (ClientContext)((SocketContext)sender).Context; 136 | client.Disconnect(true); 137 | m_ClientContextPool.PutObject(client); 138 | } 139 | 140 | #pragma warning disable 4014 141 | /// 142 | /// The OnPacketSent event. 143 | /// 144 | /// The client context. 145 | /// The sent packet 146 | private void SocketContext_PacketSent(object sender, Packet packet) 147 | { 148 | ClientContext client = (ClientContext)((SocketContext)sender).Context; 149 | client.PacketTransferredNotify(packet); 150 | } 151 | 152 | #endregion 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /SR_GameServer/SR_GameServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C5000548-D941-4EBF-B580-B0B57E8A9250} 8 | Exe 9 | Properties 10 | SR_GameServer 11 | SR_GameServer 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | ..\Output\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | ..\Output\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | true 37 | bin\x86\Debug\ 38 | DEBUG;TRACE 39 | full 40 | x86 41 | prompt 42 | MinimumRecommendedRules.ruleset 43 | true 44 | 45 | 46 | bin\x86\Release\ 47 | TRACE 48 | true 49 | pdbonly 50 | x86 51 | prompt 52 | MinimumRecommendedRules.ruleset 53 | true 54 | 55 | 56 | true 57 | bin\x64\Debug\ 58 | DEBUG;TRACE 59 | full 60 | x64 61 | prompt 62 | MinimumRecommendedRules.ruleset 63 | true 64 | 65 | 66 | bin\x64\Release\ 67 | TRACE 68 | true 69 | pdbonly 70 | x64 71 | prompt 72 | MinimumRecommendedRules.ruleset 73 | true 74 | 75 | 76 | 77 | ..\clipper_library.dll 78 | 79 | 80 | ..\SharpDX.dll 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | {a0e9c09c-cc53-474f-bdd5-a641f57e2215} 135 | SCore 136 | 137 | 138 | 139 | 140 | 147 | -------------------------------------------------------------------------------- /SR_GameServer/Services/UniqueID.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer.Services 2 | { 3 | using System.Threading; 4 | 5 | public static class UniqueID 6 | { 7 | #region Private Properties and Fields 8 | 9 | /// 10 | /// Stores the last generated GObj UniqueID 11 | /// 12 | private static volatile int s_LastGObjID; 13 | 14 | /// 15 | /// Stores the last generated Casting UniqueID 16 | /// 17 | private static volatile int s_LastCastingID; 18 | 19 | #endregion 20 | 21 | #region Initializer Methods 22 | 23 | public static void Initialize() 24 | { 25 | s_LastGObjID = 100; 26 | s_LastCastingID = 150000000; 27 | } 28 | 29 | #endregion 30 | 31 | #region Public Methods 32 | 33 | /// 34 | /// Generates the new GObj UniqueID 35 | /// 36 | /// 37 | public static int GenerateGObjID() 38 | { 39 | if (PreventGObjIDOverflows()) 40 | return 100; 41 | 42 | return Interlocked.Increment(ref s_LastGObjID); 43 | } 44 | 45 | /// 46 | /// Generates the new Casting UniqueID 47 | /// 48 | /// 49 | public static int GenerateCastingID() 50 | { 51 | if (PreventCastingIDOverflows()) 52 | return 150000000; 53 | 54 | return Interlocked.Increment(ref s_LastCastingID); 55 | } 56 | 57 | #endregion 58 | 59 | #region Private Methods 60 | 61 | /// 62 | /// Checks for the GObj UniqueID overflows 63 | /// 64 | /// 65 | private static bool PreventGObjIDOverflows() 66 | { 67 | return Interlocked.CompareExchange(ref s_LastGObjID, 100, 147483646) == 147483646; 68 | } 69 | 70 | /// 71 | /// Checks for the Casting UniqueID overflows 72 | /// 73 | /// 74 | private static bool PreventCastingIDOverflows() 75 | { 76 | return Interlocked.CompareExchange(ref s_LastCastingID, 150000000, 2000000100) == 2000000100; 77 | } 78 | 79 | #endregion 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /SR_GameServer/Structures.cs: -------------------------------------------------------------------------------- 1 | namespace SR_GameServer 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data.SqlClient; 6 | using System.Threading.Tasks; 7 | 8 | using SCommon.Security; 9 | 10 | public struct _buff_item 11 | { 12 | public int SkillID; 13 | public int CastingID; 14 | public byte Slot; 15 | public object Data; 16 | public bool IsFree; 17 | 18 | public _buff_item(int sid, int cid, byte slt) 19 | { 20 | SkillID = sid; 21 | CastingID = cid; 22 | Slot = slt; 23 | Data = null; 24 | IsFree = false; 25 | } 26 | } 27 | 28 | public struct _trijob 29 | { 30 | public int TraderExp; 31 | public int HunterExp; 32 | public int ThiefExp; 33 | public byte TraderLvl; 34 | public byte HunterLvl; 35 | public byte ThiefLvl; 36 | public short ArrangeLevel; 37 | public int ArrangePoint1; 38 | public int ArrangePoint2; 39 | } 40 | 41 | public struct _skill_mastery 42 | { 43 | public int ID; 44 | public byte Level; 45 | } 46 | 47 | public class _item 48 | { 49 | public int CharID; 50 | public int RefItemID; 51 | public byte Slot; 52 | public byte OptLvl; 53 | public long ID64; 54 | public long Variance; 55 | public int Data; 56 | public string CreaterName; 57 | public byte MagParamCount; 58 | public int[] MagParams; 59 | public long ItemSerial; 60 | 61 | public void Read(SqlDataReader reader) 62 | { 63 | this.ID64 = reader.GetFieldValue((int)_Items.ID64); 64 | this.RefItemID = reader.GetFieldValue((int)_Items.RefItemID); 65 | this.OptLvl = reader.GetFieldValue((int)_Items.OptLevel); 66 | this.Variance = reader.GetFieldValue((int)_Items.Variance); 67 | this.Data = reader.GetFieldValue((int)_Items.Data); 68 | this.CreaterName = reader.GetFieldValue((int)_Items.CreaterName); 69 | this.MagParamCount = reader.GetFieldValue((int)_Items.MagParamCount); 70 | if (this.MagParamCount > 0) 71 | { 72 | this.MagParams = new int[this.MagParamCount]; 73 | for (int i = 0; i < this.MagParamCount; i++) 74 | this.MagParams[i] = reader.GetFieldValue((int)_Items.MagParam1 + i); 75 | } 76 | this.ItemSerial = reader.GetFieldValue((int)_Items.ItemSerial); 77 | this.CharID = reader.GetFieldValue((int)_Items.FieldCount + (int)_Inventory.CharID); 78 | this.Slot = reader.GetFieldValue((int)_Items.FieldCount + (int)_Inventory.Slot); 79 | } 80 | 81 | #pragma warning disable 1998 82 | public async Task ReadAsync(SqlDataReader reader) 83 | { 84 | this.ID64 = await reader.GetFieldValueAsync((int)_Items.ID64); 85 | this.RefItemID = await reader.GetFieldValueAsync((int)_Items.RefItemID); 86 | this.OptLvl = await reader.GetFieldValueAsync((int)_Items.OptLevel); 87 | this.Variance = await reader.GetFieldValueAsync((int)_Items.Variance); 88 | this.Data = await reader.GetFieldValueAsync((int)_Items.Data); 89 | this.CreaterName = await reader.GetFieldValueAsync((int)_Items.CreaterName); 90 | this.MagParamCount = await reader.GetFieldValueAsync((int)_Items.MagParamCount); 91 | if (this.MagParamCount > 0) 92 | { 93 | this.MagParams = new int[this.MagParamCount]; 94 | for (int i = 0; i < this.MagParamCount; i++) 95 | this.MagParams[i] = await reader.GetFieldValueAsync((int)_Items.MagParam1 + i); 96 | } 97 | this.ItemSerial = await reader.GetFieldValueAsync((int)_Items.ItemSerial); 98 | this.CharID = await reader.GetFieldValueAsync((int)_Items.FieldCount + (int)_Inventory.CharID); 99 | this.Slot = await reader.GetFieldValueAsync((int)_Items.FieldCount + (int)_Inventory.Slot); 100 | } 101 | 102 | public int Write(Packet p) 103 | { 104 | p.WriteByte(Slot); 105 | p.WriteInt32(RefItemID); 106 | if (SR_GameServer.Data.Globals.Ref.ObjItem[RefItemID].TypeID1 == 3 && SR_GameServer.Data.Globals.Ref.ObjItem[RefItemID].TypeID2 == 1) 107 | { 108 | p.WriteByte(OptLvl); 109 | p.WriteInt32(0); 110 | p.WriteInt32(0); 111 | p.WriteInt16(Data); 112 | return 16; 113 | } 114 | else if (SR_GameServer.Data.Globals.Ref.ObjItem[RefItemID].TypeID1 == 3 && SR_GameServer.Data.Globals.Ref.ObjItem[RefItemID].TypeID2 == 3) 115 | { 116 | p.WriteByte((byte)Data); 117 | return 6; 118 | } 119 | return 5; 120 | } 121 | } 122 | 123 | public struct _pk_info 124 | { 125 | public byte Dailiy; 126 | public short Total; 127 | public int MurdererLevel; 128 | public DateTime Last; 129 | public PKType Type; 130 | } 131 | 132 | public struct _action_info 133 | { 134 | public GObj Target; 135 | public int SkillID; 136 | public int CastingID; 137 | } 138 | 139 | public struct _sightGObj 140 | { 141 | public GObj Object; 142 | public bool Seen; 143 | public Queue PacketQueue; 144 | 145 | public override bool Equals(object obj) 146 | { 147 | try 148 | { 149 | _sightGObj sight = (_sightGObj)obj; 150 | return this.Object.m_uniqueId == sight.Object.m_uniqueId && this.Seen == sight.Seen; 151 | } 152 | catch 153 | { 154 | return false; 155 | } 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /SharpDX.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanisman/SilkroadProject/8f72246035555abdaba4cf079a356ea028db7385/SharpDX.dll -------------------------------------------------------------------------------- /SilkroadProject.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SCommon", "SCommon\SCommon.shproj", "{1CED3D69-AF5C-44F5-985C-33F28C7F521A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GatewayServer", "GatewayServer\GatewayServer.csproj", "{422E556D-B2C7-4607-A485-3B1C6EED41EB}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SR_GameServer", "SR_GameServer\SR_GameServer.csproj", "{C5000548-D941-4EBF-B580-B0B57E8A9250}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SCore", "SCore\SCore\SCore.vcxproj", "{A0E9C09C-CC53-474F-BDD5-A641F57E2215}" 13 | EndProject 14 | Global 15 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 16 | SCommon\SCommon.projitems*{1ced3d69-af5c-44f5-985c-33f28c7f521a}*SharedItemsImports = 13 17 | SCommon\SCommon.projitems*{c5000548-d941-4ebf-b580-b0b57e8a9250}*SharedItemsImports = 4 18 | SCommon\SCommon.projitems*{422e556d-b2c7-4607-a485-3b1c6eed41eb}*SharedItemsImports = 4 19 | EndGlobalSection 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Debug|x64 = Debug|x64 23 | Debug|x86 = Debug|x86 24 | Release|Any CPU = Release|Any CPU 25 | Release|x64 = Release|x64 26 | Release|x86 = Release|x86 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Debug|x64.ActiveCfg = Debug|x64 32 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Debug|x64.Build.0 = Debug|x64 33 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Debug|x86.ActiveCfg = Debug|x86 34 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Debug|x86.Build.0 = Debug|x86 35 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Release|x64.ActiveCfg = Release|x64 38 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Release|x64.Build.0 = Release|x64 39 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Release|x86.ActiveCfg = Release|x86 40 | {422E556D-B2C7-4607-A485-3B1C6EED41EB}.Release|x86.Build.0 = Release|x86 41 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Debug|x64.ActiveCfg = Debug|x64 44 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Debug|x64.Build.0 = Debug|x64 45 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Debug|x86.ActiveCfg = Debug|x86 46 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Debug|x86.Build.0 = Debug|x86 47 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Release|x64.ActiveCfg = Release|x64 50 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Release|x64.Build.0 = Release|x64 51 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Release|x86.ActiveCfg = Release|Any CPU 52 | {C5000548-D941-4EBF-B580-B0B57E8A9250}.Release|x86.Build.0 = Release|Any CPU 53 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Debug|Any CPU.ActiveCfg = Debug|Win32 54 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Debug|Any CPU.Build.0 = Debug|Win32 55 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Debug|x64.ActiveCfg = Debug|Win32 56 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Debug|x86.ActiveCfg = Debug|Win32 57 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Debug|x86.Build.0 = Debug|Win32 58 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Release|Any CPU.ActiveCfg = Release|Win32 59 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Release|x64.ActiveCfg = Release|Win32 60 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Release|x86.ActiveCfg = Release|Win32 61 | {A0E9C09C-CC53-474F-BDD5-A641F57E2215}.Release|x86.Build.0 = Release|Win32 62 | EndGlobalSection 63 | GlobalSection(SolutionProperties) = preSolution 64 | HideSolutionNode = FALSE 65 | EndGlobalSection 66 | EndGlobal 67 | -------------------------------------------------------------------------------- /clipper_library.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tanisman/SilkroadProject/8f72246035555abdaba4cf079a356ea028db7385/clipper_library.dll --------------------------------------------------------------------------------