public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JArray jArray = JArray.Load(reader); var inv = new Inventory(jArray.Count); for (byte i = 0; i < jArray.Count; i++) { dynamic item; if (TryGetValue(jArray[i], out item)) { //itmType = Game.World.WorldData.Values<Item>().Where(x => x.Name == (string)item.FirstOrDefault().Value).FirstOrDefault().Name; if (Game.World.WorldData.TryGetValue <Xml.Item>(item.Id, out Xml.Item itemTemplate)) { inv[i] = new ItemObject(itemTemplate.Id, Game.World) { Count = item.Count ?? 1, Durability = item.Durability ?? itemTemplate.Properties.Physical.Durability }; //this will need to be expanded later based on ItemObject properties being saved back to the database. } else { GameLog.Error($"Inventory deserializer error: item {item.Id} not found in index, skipping"); } } } return(inv); }
public static bool ValidateEncryptionKey(string endpoint, ServerToken token) { bool valid; try { var webReq = WebRequest.Create(new Uri(endpoint)); webReq.ContentType = "application/json"; webReq.Method = "POST"; var json = JsonSerializer.Serialize(token); using (var sw = new StreamWriter(webReq.GetRequestStream())) { sw.Write(json); } var response = webReq.GetResponse(); using (var sr = new StreamReader(response.GetResponseStream())) { valid = (bool)JsonSerializer.Deserialize(sr.ReadToEnd(), typeof(bool)); } } catch (Exception e) { Game.ReportException(e); GameLog.Error("ValidateEncryptionKey failure: {e}", e); return(false); } return(valid); }
public static void DeregisterClient(Client client) { ConnectedClients.TryRemove(client.ConnectionId, out Client _); GameLog.InfoFormat("Deregistering {0}", client.ConnectionId); // Send a control message to clean up after World users; Lobby and Login handle themselves if (client.ServerType == ServerTypes.World) { if (!WorldClients.TryRemove(client.ConnectionId, out Client _)) { GameLog.Error("Couldn't deregister cid {id}", client.ConnectionId); } try { if (!World.ControlMessageQueue.IsCompleted) { World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser, CleanupType.ByConnectionId, client.ConnectionId)); } } catch (InvalidOperationException e) { Game.ReportException(e); if (!World.ControlMessageQueue.IsCompleted) { GameLog.ErrorFormat("Connection {id}: DeregisterClient failed", client.ConnectionId); } } } }
public void ReadCallback(IAsyncResult ar) { ClientState state = (ClientState)ar.AsyncState; Client client; SocketError errorCode = SocketError.SocketError; int bytesRead = 0; ClientPacket receivedPacket; GameLog.Debug($"SocketConnected: {state.WorkSocket.Connected}, IAsyncResult: Completed: {ar.IsCompleted}, CompletedSynchronously: {ar.CompletedSynchronously}, queue size: {state.Buffer.Length}"); GameLog.Debug("Running read callback"); if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client)) { // Is this a redirect? Redirect redirect; if (!GlobalConnectionManifest.TryGetRedirect(state.Id, out redirect)) { GameLog.ErrorFormat("Receive: data from unknown client (id {0}, closing connection", state.Id); state.WorkSocket.Close(); state.WorkSocket.Dispose(); return; } client = redirect.Client; client.ClientState = state; if (client.EncryptionKey == null) { client.EncryptionKey = redirect.EncryptionKey; } GlobalConnectionManifest.RegisterClient(client); } try { bytesRead = state.WorkSocket.EndReceive(ar, out errorCode); if (bytesRead == 0 || errorCode != SocketError.Success) { GameLog.Error($"bytesRead: {bytesRead}, errorCode: {errorCode}"); client.Disconnect(); } } catch (Exception e) { GameLog.Fatal($"EndReceive Error: {e.Message}"); client.Disconnect(); } try { // TODO: improve / refactor while (client.ClientState.TryGetPacket(out receivedPacket)) { client.Enqueue(receivedPacket); } } catch (Exception e) { GameLog.Error($"ReadCallback error: {e.Message}"); } ContinueReceiving(state, client); }
public static byte[] RequestEncryptionKey(string endpoint, IPAddress remoteAddress) { byte[] key; try { var seed = new Seed() { Ip = remoteAddress.ToString() }; var webReq = WebRequest.Create(new Uri(endpoint)); webReq.ContentType = "application/json"; webReq.Method = "POST"; var json = JsonSerializer.Serialize(seed); using (var sw = new StreamWriter(webReq.GetRequestStream())) { sw.Write(json); } var response = webReq.GetResponse(); using (var sr = new StreamReader(response.GetResponseStream())) { key = (byte[])JsonSerializer.Deserialize(sr.ReadToEnd(), typeof(byte[])); } } catch (Exception e) { GameLog.Error("RequestEncryptionKey failure: {e}", e); key = Encoding.ASCII.GetBytes("NOTVALID!"); } return(key); }
public virtual void AcceptConnection(IAsyncResult ar) { // TODO: @norrismiv async callbacks+inheritance? and/or can these callbacks suck less? AllDone.Set(); if (!Active) { return; } Socket handler; Socket clientSocket; try { clientSocket = (Socket)ar.AsyncState; handler = clientSocket.EndAccept(ar); } catch (ObjectDisposedException e) { GameLog.Error($"Disposed socket {e.Message}"); return; } Client client = new Client(handler, this); Clients.TryAdd(handler.Handle, client); GlobalConnectionManifest.RegisterClient(client); if (this is Lobby) { var x7E = new ServerPacket(0x7E); x7E.WriteByte(0x1B); x7E.WriteString("CONNECTED SERVER\n"); client.Enqueue(x7E); GameLog.DebugFormat("Lobby: AcceptConnection occuring"); GameLog.DebugFormat("Lobby: cid is {0}", client.ConnectionId); } else if (this is Login) { GameLog.DebugFormat("Login: AcceptConnection occuring"); GameLog.DebugFormat("Login: cid is {0}", client.ConnectionId); } else if (this is World) { GameLog.DebugFormat("World: AcceptConnection occuring"); GameLog.DebugFormat("World: cid is {0}", client.ConnectionId); } try { handler.BeginReceive(client.ClientState.Buffer, 0, client.ClientState.Buffer.Length, 0, new AsyncCallback(ReadCallback), client.ClientState); GameLog.DebugFormat("AcceptConnection returning"); clientSocket.BeginAccept(new AsyncCallback(AcceptConnection), clientSocket); } catch (SocketException e) { Game.ReportException(e); handler.Close(); } }
private static double _evalFormula(string formula, Xml.Castable castable, Creature target, Creature source) { try { return(new FormulaParser(source, castable, target).Eval(formula)); } catch (Exception e) { GameLog.Error($"NumberCruncher formula error: castable {castable.Name}, target {target.Name}, source {source?.Name ?? "no source"}: {formula}, error: {e}"); return(0); } }
public void InsertNpc(Merchant toInsert) { World.Insert(toInsert); Insert(toInsert, toInsert.X, toInsert.Y); try { toInsert.OnSpawn(); } catch (Exception e) { GameLog.Error("NPC {name}: exception occurred, aborting: {e}", toInsert.Name, e); } }
public void FlushSendBuffer() { //lock (ClientState.SendLock) //{ try { while (ClientState.SendBufferTake(out ServerPacket packet)) { Task.Run(async() => { if (packet == null) { return; } if (packet.ShouldEncrypt) { ++ServerOrdinal; packet.Ordinal = ServerOrdinal; packet.GenerateFooter(); packet.Encrypt(this); } if (packet.TransmitDelay != 0) { await Task.Delay(packet.TransmitDelay); } var buffer = packet.ToArray(); try { Socket.BeginSend(buffer, 0, buffer.Length, 0, SendCallback, ClientState); } catch (ObjectDisposedException e) { GameLog.Warning($"FlushSendBuffer: {e.Message}"); } }); } } catch (ObjectDisposedException) { // Socket is gone, peace out ClientState.Dispose(); } catch (Exception e) { GameLog.Error($"HALP: {e}"); } //} }
private void ProcessHandler(Xml.Handler handler) { if ((handler?.Function ?? String.Empty) == String.Empty) { return; } // If a handler is specified, check the script for it first. Note that we don't run both; // if you override something like OnDeath, that's your problem. VisibleObject invoker; VisibleObject invokee; if (handler.ScriptSource == Xml.ScriptSource.Target) { invokee = Target; invoker = Source; } else // Caster { invokee = Source; invoker = Target; } if (invokee.Script != null) { invokee.Script.ExecuteFunction(handler.Function, invoker); return; } Type type = invokee.GetType(); try { MethodInfo methodInfo = type.GetMethod(handler.Function); methodInfo.Invoke(invokee, null); } catch (Exception e) { Game.ReportException(e); GameLog.Error("Exception processing status handler: {exception}", e); } }
public void SendCallback(IAsyncResult ar) { ClientState state = (ClientState)ar.AsyncState; Client client; GameLog.DebugFormat($"EndSend: SocketConnected: {state.WorkSocket.Connected}, IAsyncResult: Completed: {ar.IsCompleted}, CompletedSynchronously: {ar.CompletedSynchronously}"); try { SocketError errorCode; var bytesSent = state.WorkSocket.EndSend(ar, out errorCode); if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client)) { GameLog.ErrorFormat("Send: socket should not exist: cid {0}", state.Id); state.WorkSocket.Close(); state.WorkSocket.Dispose(); return; } if (bytesSent == 0 || errorCode != SocketError.Success) { GameLog.ErrorFormat("cid {0}: disconnected"); client.Disconnect(); throw new SocketException((int)errorCode); } } catch (SocketException e) { Game.ReportException(e); GameLog.Error($"Error Code: {e.ErrorCode}, {e.Message}"); state.WorkSocket.Close(); } catch (ObjectDisposedException) { //client.Disconnect(); GameLog.Error($"ObjectDisposedException"); state.WorkSocket.Close(); } state.SendComplete.Set(); }
//public Dictionary<string, Xml.Spawn> Spawns { get; set; } /// <summary> /// Create a new Hybrasyl map from an XMLMap object. /// </summary> /// <param name="newMap">An XSD.Map object representing the XML map file.</param> /// <param name="theWorld">A world object where the map will be placed</param> public Map(Xml.Map newMap, World theWorld) { Init(); World = theWorld; SpawnDebug = false; // Spawns = new List<Xml.Spawn>(); // TODO: refactor Map class to not do this, but be a partial which overlays // TODO: XSD.Map Id = newMap.Id; X = newMap.X; Y = newMap.Y; Name = newMap.Name; AllowCasting = newMap.AllowCasting; EntityTree = new QuadTree <VisibleObject>(0, 0, X, Y); Music = newMap.Music; foreach (var warpElement in newMap.Warps) { var warp = new Warp(this) { X = warpElement.X, Y = warpElement.Y }; if (warpElement.MapTarget != null) { // map warp warp.DestinationMapName = warpElement.MapTarget.Value; warp.WarpType = WarpType.Map; warp.DestinationX = warpElement.MapTarget.X; warp.DestinationY = warpElement.MapTarget.Y; } else if (warpElement.WorldMapTarget != string.Empty) { // worldmap warp warp.DestinationMapName = warpElement.WorldMapTarget; warp.WarpType = WarpType.WorldMap; } if (warpElement.Restrictions?.Level != null) { warp.MinimumLevel = warpElement.Restrictions.Level.Min; warp.MaximumLevel = warpElement.Restrictions.Level.Max; } if (warpElement.Restrictions?.Ab != null) { warp.MinimumAbility = warpElement.Restrictions.Ab.Min; warp.MaximumAbility = warpElement.Restrictions.Ab.Max; } warp.MobUse = warpElement.Restrictions?.NoMobUse ?? true; Warps[new Tuple <byte, byte>(warp.X, warp.Y)] = warp; } foreach (var npcElement in newMap.Npcs) { var npcTemplate = World.WorldData.Get <Xml.Npc>(npcElement.Name); if (npcTemplate == null) { GameLog.Error("map ${Name}: NPC ${npcElement.Name} is missing, will not be loaded"); continue; } var merchant = new Merchant { X = npcElement.X, Y = npcElement.Y, Name = npcElement.Name, Sprite = npcTemplate.Appearance.Sprite, Direction = npcElement.Direction, Portrait = npcTemplate.Appearance.Portrait, AllowDead = npcTemplate.AllowDead }; if (npcTemplate.Roles != null) { if (npcTemplate.Roles.Post != null) { merchant.Jobs ^= MerchantJob.Post; } if (npcTemplate.Roles.Bank != null) { merchant.Jobs ^= MerchantJob.Bank; } if (npcTemplate.Roles.Repair != null) { merchant.Jobs ^= MerchantJob.Repair; } if (npcTemplate.Roles.Train != null) { if (npcTemplate.Roles.Train.Any(x => x.Type == "Skill")) { merchant.Jobs ^= MerchantJob.Skills; } if (npcTemplate.Roles.Train.Any(x => x.Type == "Spell")) { merchant.Jobs ^= MerchantJob.Spells; } } if (npcTemplate.Roles.Vend != null) { merchant.Jobs ^= MerchantJob.Vend; } merchant.Roles = npcTemplate.Roles; } InsertNpc(merchant); // Keep the actual spawned object around in the index for later use World.WorldData.Set(merchant.Name, merchant); } foreach (var reactorElement in newMap.Reactors) { var reactor = new Reactor(reactorElement.X, reactorElement.Y, this, reactorElement.Script, reactorElement.Description, reactorElement.Blocking); reactor.AllowDead = reactorElement.AllowDead; InsertReactor(reactor); GameLog.Debug($"{reactor.Id} placed in {reactor.Map.Name}, description was {reactor.Description}"); } foreach (var sign in newMap.Signs) { Signpost post; if (sign.Type == Xml.BoardType.Sign) { post = new Signpost(sign.X, sign.Y, sign.Message); } else { post = new Signpost(sign.X, sign.Y, sign.Message, true, sign.BoardKey); } InsertSignpost(post); } Load(); }
public void FlushSendBuffer() { MemoryStream buffer = new MemoryStream(); int transmitDelay = 0; try { while (!ClientState.SendBufferEmpty) { if (ClientState.SendBufferPeek(out ServerPacket precheck)) { if (buffer.Length > 0 && (precheck.TransmitDelay > 0 && transmitDelay == 0)) { // If we're dealing with a bunch of packets with delays, batch them together. // Otherwise, send them individually. //GameLog.Warning("TransmitDelay occurring"); break; } // Limit outbound transmissions to 65k bytes at a time if (buffer.Length >= 65535) { //GameLog.Warning("Breaking up into chunks"); break; } } if (ClientState.SendBufferTake(out ServerPacket packet)) { // If no packets, just call the whole thing off if (packet == null) { return; } if (packet.ShouldEncrypt) { ++ServerOrdinal; packet.Ordinal = ServerOrdinal; packet.GenerateFooter(); packet.Encrypt(this); } if (packet.TransmitDelay > 0) { transmitDelay = packet.TransmitDelay; } // Write packet to our memory stream buffer.Write(packet.ToArray()); } } if (buffer.Length == 0) { return; } // Background enqueue a send with our memory stream Task.Run(async() => { var socketbuf = buffer.ToArray(); try { //GameLog.Info($"transmit: {socketbuf.Length} with delay {transmitDelay}"); if (transmitDelay > 0) { await Task.Delay(transmitDelay); } Socket.BeginSend(socketbuf, 0, socketbuf.Length, 0, SendCallback, ClientState); } catch (ObjectDisposedException) { ClientState.Dispose(); } }); } catch (ObjectDisposedException e) { // Socket is gone, peace out ClientState.Dispose(); } catch (Exception e) { Game.ReportException(e); GameLog.Error($"HALP: {e}"); } }
public ThrottleResult ProcessThrottle(Client client, ClientPacket packet) { ThrottleInfo info; ThrottleResult result = ThrottleResult.Error; if (!client.ThrottleState.TryGetValue(packet.Opcode, out info)) { client.ThrottleState[packet.Opcode] = new ThrottleInfo(); info = client.ThrottleState[packet.Opcode]; } Monitor.Enter(info); try { DateTime rightnow = DateTime.Now; GameLog.Warning($"Right now is {rightnow}"); var transmitInterval = (rightnow - info.LastReceived); var acceptedInterval = (rightnow - info.LastAccepted); info.PreviousReceived = info.LastReceived; info.LastReceived = rightnow; info.TotalReceived++; GameLog.Debug($"Begin: PA: {info.PreviousAccepted} LA: {info.LastAccepted} AInterval is {acceptedInterval.TotalMilliseconds} TInterval {transmitInterval.TotalMilliseconds}"); if (info.Throttled) { result = ThrottleResult.Throttled; if (acceptedInterval.TotalMilliseconds >= ThrottleDuration && acceptedInterval.TotalMilliseconds >= Interval) { GameLog.Error($"Unthrottled: {acceptedInterval.TotalMilliseconds} > {ThrottleDuration} and {Interval}"); info.Throttled = false; info.TotalThrottled = 0; result = ThrottleResult.ThrottleEnd; info.PreviousAccepted = info.LastAccepted; info.LastAccepted = rightnow; OnThrottleStop(new ClientTrigger(client)); } else { info.TotalThrottled++; GameLog.Error($"Throttled, count is {info.TotalThrottled}"); result = ThrottleResult.Throttled; if (ThrottleDisconnectThreshold > 0 && info.TotalThrottled > ThrottleDisconnectThreshold) { result = ThrottleResult.Disconnect; OnDisconnectThreshold(new ClientTrigger(client)); } } } else { if (acceptedInterval.TotalMilliseconds <= Interval && info.LastAccepted != DateTime.MinValue) { GameLog.Debug($"TInterval {transmitInterval}, AInterval {acceptedInterval} - maximum is {Interval}, throttled"); info.Throttled = true; OnThrottleStart(new ClientTrigger(client)); result = ThrottleResult.Throttled; } else { info.PreviousAccepted = info.LastAccepted; info.LastAccepted = rightnow; info.TotalAccepted++; result = ThrottleResult.OK; GameLog.Debug($"Packet accepted, PA: {info.PreviousAccepted} LA: {info.LastAccepted}"); } } } finally { Monitor.Exit(info); } return(result); }