public void AddItem(int x, int y, ItemObject itemObject) { GameLog.DebugFormat("{0}, {1}, {2} qty {3} id {4}", x, y, itemObject.Name, itemObject.Count, itemObject.Id); if (itemObject.Id == 0) { World.Insert(itemObject); } if (itemObject == null) { GameLog.DebugFormat("ItemObject is null, aborting"); return; } // Add the ItemObject to the world at the given location. itemObject.X = (byte)x; itemObject.Y = (byte)y; itemObject.Map = this; lock (_lock) { EntityTree.Add(itemObject); Objects.Add(itemObject); } NotifyNearbyAoiEntry(itemObject); }
public bool Use(User target) { GameLog.DebugFormat("warp: {0} from {1} ({2},{3}) to {4} ({5}, {6}", target.Name, SourceMap.Name, X, Y, DestinationMapName, DestinationX, DestinationY); switch (WarpType) { case WarpType.Map: Map map; if (SourceMap.World.WorldData.TryGetValueByIndex(DestinationMapName, out map)) { target.Teleport(map.Id, DestinationX, DestinationY); return(true); } GameLog.ErrorFormat("User {0} tried to warp to nonexistent map {1} from {2}: {3},{4}", target.Name, DestinationMapName, SourceMap.Name, X, Y); break; case WarpType.WorldMap: WorldMap wmap; if (SourceMap.World.WorldData.TryGetValue(DestinationMapName, out wmap)) { SourceMap.Remove(target); target.SendWorldMap(wmap); SourceMap.World.WorldData.Get <Map>(Hybrasyl.Constants.LAG_MAP).Insert(target, 5, 5, false); return(true); } GameLog.ErrorFormat("User {0} tried to warp to nonexistent worldmap {1} from {2}: {3},{4}", target.Name, DestinationMapName, SourceMap.Name, X, Y); break; } return(false); }
private void ControlMessage_SpawnMonster(HybrasylControlMessage message) { var monster = (Monster)message.Arguments[0]; var map = (Map)message.Arguments[1]; GameLog.DebugFormat("monolith: spawning monster {0} on map {1}", monster.Name, map.Name); map.InsertCreature(monster); }
private void PacketHandler_0x03_Login(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); GameLog.DebugFormat("cid {0}: Login request for {1}", client.ConnectionId, name); if (!World.PlayerExists(name)) { client.LoginMessage("That character does not exist", 3); GameLog.InfoFormat("cid {0}: attempt to login as nonexistent character {1}", client.ConnectionId, name); return; } if (World.TryGetUser(name, out User loginUser)) { if (loginUser.VerifyPassword(password)) { GameLog.DebugFormat("cid {0}: password verified for {1}", client.ConnectionId, name); if (Game.World.WorldData.ContainsKey <User>(name)) { GameLog.InfoFormat("cid {0}: {1} logging on again, disconnecting previous connection", client.ConnectionId, name); client.LoginMessage("That character is already online. Please try again.", 3); World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.LogoffUser, name)); return; } GameLog.DebugFormat("cid {0} ({1}): logging in", client.ConnectionId, name); client.LoginMessage("\0", 0); client.SendMessage("Welcome to Hybrasyl!", 3); GameLog.DebugFormat("cid {0} ({1}): sending redirect to world", client.ConnectionId, name); var redirect = new Redirect(client, this, Game.World, name, client.EncryptionSeed, client.EncryptionKey); GameLog.InfoFormat("cid {0} ({1}): login successful, redirecting to world server", client.ConnectionId, name); loginUser.Login.LastLogin = DateTime.Now; loginUser.Login.LastLoginFrom = ((IPEndPoint)client.Socket.RemoteEndPoint).Address.ToString(); loginUser.Save(); client.Redirect(redirect); } else { GameLog.WarningFormat("cid {0} ({1}): password incorrect", client.ConnectionId, name); client.LoginMessage("Incorrect password", 3); loginUser.Login.LastLoginFailure = DateTime.Now; loginUser.Login.LoginFailureCount++; loginUser.Save(); } } else { // Something bad has happened client.LoginMessage("An unknown error occurred. Please contact Hybrasyl support.", 3); } }
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(); } }
public void Enqueue(ClientPacket packet) { GameLog.DebugFormat("Enqueueing ClientPacket {0}", packet.Opcode); ClientState.ReceiveBufferAdd(packet); if (!packet.ShouldEncrypt || (packet.ShouldEncrypt && EncryptionKey != null)) { FlushReceiveBuffer(); } }
public bool Load() { IsWall = new bool[X, Y]; var filename = Path.Combine(World.MapFileDirectory, $"lod{Id}.map"); if (File.Exists(filename)) { RawData = File.ReadAllBytes(filename); Checksum = Crc16.Calculate(RawData); int index = 0; for (int y = 0; y < Y; ++y) { for (int x = 0; x < X; ++x) { var bg = RawData[index++] | RawData[index++] << 8; var lfg = RawData[index++] | RawData[index++] << 8; var rfg = RawData[index++] | RawData[index++] << 8; if (lfg != 0 && (Game.Collisions[lfg - 1] & 0x0F) == 0x0F) { IsWall[x, y] = true; } if (rfg != 0 && (Game.Collisions[rfg - 1] & 0x0F) == 0x0F) { IsWall[x, y] = true; } ushort lfgu = (ushort)lfg; ushort rfgu = (ushort)rfg; if (Game.DoorSprites.ContainsKey(lfgu)) { // This is a left-right door GameLog.DebugFormat("Inserting LR door at {0}@{1},{2}: Collision: {3}", Name, x, y, IsWall[x, y]); InsertDoor((byte)x, (byte)y, IsWall[x, y], true, Game.IsDoorCollision(lfgu)); } else if (Game.DoorSprites.ContainsKey(rfgu)) { GameLog.DebugFormat("Inserting UD door at {0}@{1},{2}: Collision: {3}", Name, x, y, IsWall[x, y]); // THis is an up-down door InsertDoor((byte)x, (byte)y, IsWall[x, y], false, Game.IsDoorCollision(rfgu)); } } } return(true); } return(false); }
/// <summary> /// Atomically update the last time we received a packet (in ticks). /// This also automatically marks the client as not idle. /// </summary> public void UpdateLastReceived(bool updateIdle = true) { Interlocked.Exchange(ref _lastReceived, DateTime.Now.Ticks); if (updateIdle) { Interlocked.Exchange(ref _idle, 0); } GameLog.DebugFormat("cid {0}: lastReceived now {1}", ConnectionId, _lastReceived); }
public void RemoveItem(ItemObject itemObject) { // Remove the ItemObject from the world at the specified location. GameLog.DebugFormat("Removing {0} qty {1} id {2}", itemObject.Name, itemObject.Count, itemObject.Id); NotifyNearbyAoiDeparture(itemObject); lock (_lock) { EntityTree.Remove(itemObject); Objects.Remove(itemObject); } }
public void RemoveGold(Gold gold) { // Remove the gold from the world at the specified location. GameLog.DebugFormat("Removing {0} qty {1} id {2}", gold.Name, gold.Amount, gold.Id); NotifyNearbyAoiDeparture(gold); lock (_lock) { EntityTree.Remove(gold); Objects.Remove(gold); } World.Remove(gold); }
public void Enqueue(ServerPacket packet) { GameLog.DebugFormat("Enqueueing ServerPacket {0}", packet.Opcode); if (!Connected) { Disconnect(); throw new ObjectDisposedException($"cid {ConnectionId}"); } else { ClientState.SendBufferAdd(packet); } }
public Server(int port) { Clients = new ConcurrentDictionary <IntPtr, Client>(); Port = port; PacketHandlers = new WorldPacketHandler[256]; ControlMessageHandlers = new ControlMessageHandler[64]; Throttles = new Dictionary <byte, IPacketThrottle>(); ExpectedConnections = new ConcurrentDictionary <uint, Redirect>(); for (int i = 0; i < 256; ++i) { PacketHandlers[i] = (c, p) => GameLog.DebugFormat("Server: Unhandled opcode 0x{0:X2}", p.Opcode); } }
public void NotifyNearbyAoiEntry(VisibleObject objectToAdd) { foreach (var obj in EntityTree.GetObjects(objectToAdd.GetViewport())) { if (obj is User) { GameLog.DebugFormat("Notifying {0} of object {1} at {2},{3} with sprite {4}", obj.Name, objectToAdd.Name, objectToAdd.X, objectToAdd.Y, objectToAdd.Sprite); var user = obj as User; user.AoiEntry(objectToAdd); } } }
/// <summary> /// Check to see if a client is idle /// </summary> public void CheckIdle() { var now = DateTime.Now.Ticks; var idletime = new TimeSpan(now - _lastReceived); if (idletime.TotalSeconds > Constants.IDLE_TIME) { GameLog.DebugFormat("cid {0}: idle for {1} seconds, marking as idle", ConnectionId, idletime.TotalSeconds); ToggleIdle(); GameLog.DebugFormat("cid {0}: ToggleIdle: {1}", ConnectionId, IsIdle()); } else { GameLog.DebugFormat("cid {0}: idle for {1} seconds, not idle", ConnectionId, idletime.TotalSeconds); } }
public void Enqueue(ClientPacket packet) { GameLog.DebugFormat("Enqueueing ClientPacket {0}", packet.Opcode); if (!Connected) { Disconnect(); throw new ObjectDisposedException($"cid {ConnectionId}"); } else { ClientState.ReceiveBufferAdd(packet); if (!packet.ShouldEncrypt || (packet.ShouldEncrypt && EncryptionKey != null)) { FlushReceiveBuffer(); } } }
public void AddGold(int x, int y, Gold gold) { GameLog.DebugFormat("{0}, {1}, {2} qty {3} id {4}", x, y, gold.Name, gold.Amount, gold.Id); if (gold == null) { GameLog.DebugFormat("ItemObject is null, aborting"); return; } // Add the gold to the world at the given location. gold.X = (byte)x; gold.Y = (byte)y; gold.Map = this; lock (_lock) { EntityTree.Add(gold); Objects.Add(gold); } NotifyNearbyAoiEntry(gold); }
private void ContinueReceiving(ClientState state, Client client) { // Continue getting dem bytes try { state.WorkSocket.BeginReceive(state.Buffer, state.BytesReceived, state.Buffer.Length - state.BytesReceived, 0, new AsyncCallback(this.ReadCallback), state); GameLog.DebugFormat("Triggering receive callback"); } catch (ObjectDisposedException e) { GameLog.Fatal(e.Message); //client.Disconnect(); state.WorkSocket.Close(); } catch (SocketException e) { GameLog.Fatal(e.Message); client.Disconnect(); } }
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(); }
/// <summary> /// Toggle a given door's state (open/closed) and send updates to users nearby. /// </summary> /// <param name="x">The X coordinate of the door.</param> /// <param name="y">The Y coordinate of the door.</param> /// <returns></returns> public void ToggleDoor(byte x, byte y) { var coords = new Tuple <byte, byte>(x, y); GameLog.DebugFormat("Door {0}@{1},{2}: Open: {3}, changing to {4}", Name, x, y, Doors[coords].Closed, !Doors[coords].Closed); Doors[coords].Closed = !Doors[coords].Closed; // There are several examples of doors in Temuair that trigger graphic // changes but do not trigger collision updates (e.g. 3-panel doors in // Piet & Undine). if (Doors[coords].UpdateCollision) { GameLog.DebugFormat("Door {0}@{1},{2}: updateCollision is set, collisions are now {3}", Name, x, y, !Doors[coords].Closed); IsWall[x, y] = !IsWall[x, y]; } GameLog.DebugFormat("Toggling door at {0},{1}", x, y); GameLog.DebugFormat("Door is now in state: Open: {0} Collision: {1}", Doors[coords].Closed, IsWall[x, y]); var updateViewport = GetViewport(x, y); foreach (var obj in EntityTree.GetObjects(updateViewport)) { if (obj is User) { var user = obj as User; GameLog.DebugFormat("Sending door packet to {0}: X {1}, Y {2}, Open {3}, LR {4}", user.Name, x, y, Doors[coords].Closed, Doors[coords].IsLeftRight); user.SendDoorUpdate(x, y, Doors[coords].Closed, Doors[coords].IsLeftRight); } } }
public byte[] GetBytes() { var buffer = Encoding.ASCII.GetBytes(Name); GameLog.DebugFormat("buffer is {0} and Name is {1}", BitConverter.ToString(buffer), Name); // X quadrant, offset, Y quadrant, offset, length of the name, the name, plus a 64-bit(?!) ID var bytes = new List <Byte>(); GameLog.DebugFormat("{0}, {1}, {2}, {3}, {4}, mappoint ID is {5}", XQuadrant, XOffset, YQuadrant, YOffset, Name.Length, Id); bytes.Add((byte)XQuadrant); bytes.Add((byte)XOffset); bytes.Add((byte)YQuadrant); bytes.Add((byte)YOffset); bytes.Add((byte)Name.Length); bytes.AddRange(buffer); bytes.AddRange(BitConverter.GetBytes(Id)); return(bytes.ToArray()); }
/// <summary> /// Determine whether either heartbeat has "expired" (meaning REAP_HEARTBEAT_INTERVAL has /// passed since we received a heartbeat response). /// </summary> /// <returns>True or false, indicating expiration.</returns> public bool IsHeartbeatExpired() { // If we have no record of sending a heartbeat, obviously it hasn't expired if (_tickHeartbeatSent == 0 && _byteHeartbeatSent == 0) { return(false); } var tickSpan = new TimeSpan(_tickHeartbeatReceived - _tickHeartbeatSent); var byteSpan = new TimeSpan(_byteHeartbeatReceived - _byteHeartbeatSent); GameLog.DebugFormat("cid {0}: tick heartbeat elapsed seconds {1}, byte heartbeat elapsed seconds {2}", ConnectionId, tickSpan.TotalSeconds, byteSpan.TotalSeconds); if (tickSpan.TotalSeconds > Constants.REAP_HEARTBEAT_INTERVAL || byteSpan.TotalSeconds > Constants.REAP_HEARTBEAT_INTERVAL) { // DON'T FEAR THE REAPER GameLog.InfoFormat("cid {0}: heartbeat expired", ConnectionId); return(true); } return(false); }
public byte[] GetBytes() { // Returns the representation of the worldmap as an array of bytes, // suitable to passing to a map packet. var buffer = Encoding.ASCII.GetBytes(ClientMap); var bytes = new List <Byte> { (byte)ClientMap.Length }; bytes.AddRange(buffer); bytes.Add((byte)Points.Count); bytes.Add(0x00); foreach (var mappoint in Points) { bytes.AddRange(mappoint.GetBytes()); } GameLog.DebugFormat("I am sending the following map packet:"); GameLog.DebugFormat("{0}", BitConverter.ToString(bytes.ToArray())); return(bytes.ToArray()); }
public void InsertCreature(Creature toInsert) { World.Insert(toInsert); Insert(toInsert, toInsert.X, toInsert.Y); GameLog.DebugFormat("Monster {0} with id {1} spawned.", toInsert.Name, toInsert.Id); }
public void FlushReceiveBuffer() { lock (ClientState.ReceiveLock) { try { ClientPacket packet; while (ClientState.ReceiveBufferTake(out packet)) { if (packet.ShouldEncrypt) { packet.Decrypt(this); } if (packet.Opcode == 0x39 || packet.Opcode == 0x3A) { packet.DecryptDialog(); } try { if (Server is Lobby) { GameLog.DebugFormat("Lobby: 0x{0:X2}", packet.Opcode); var handler = (Server as Lobby).PacketHandlers[packet.Opcode]; handler.Invoke(this, packet); GameLog.DebugFormat("Lobby packet done"); UpdateLastReceived(); } else if (Server is Login) { GameLog.Debug($"Login: 0x{packet.Opcode:X2}"); var handler = (Server as Login).PacketHandlers[packet.Opcode]; handler.Invoke(this, packet); GameLog.DebugFormat("Login packet done"); UpdateLastReceived(); } else { UpdateLastReceived(packet.Opcode != 0x45 && packet.Opcode != 0x75); GameLog.Debug($"Queuing: 0x{packet.Opcode:X2}"); //packet.DumpPacket(); // Check for throttling var throttleResult = Server.PacketThrottleCheck(this, packet); if (throttleResult == ThrottleResult.OK || throttleResult == ThrottleResult.ThrottleEnd || throttleResult == ThrottleResult.SquelchEnd) { World.MessageQueue.Add(new HybrasylClientMessage(packet, ConnectionId)); } else if (packet.Opcode == 0x06) { World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.TriggerRefresh, ConnectionId)); } } } catch (Exception e) { Game.ReportException(e); GameLog.ErrorFormat("EXCEPTION IN HANDLING: 0x{0:X2}: {1}", packet.Opcode, e); } } } catch (Exception e) { Game.ReportException(e); Console.WriteLine(e); throw; } } }
public void RemoveCreature(Creature toRemove) { World.Remove(toRemove); Remove(toRemove); GameLog.DebugFormat("Removing creature {0} (id {1})", toRemove.Name, toRemove.Id); }
public void DumpPacket() { // Dump the packet to the console. GameLog.DebugFormat("Dumping packet:"); GameLog.DebugFormat(BitConverter.ToString(Data)); }