public void CharacterInfoEvent(Client c, string[] command) { Guid g; if(!Guid.TryParse(command[0],out g)) c.Send(new ErrorException(ClientError.INTERNAL_ERROR, "Invalid GUID")); else if(this.challengesRequests.ContainsKey(g)) { Client cl = this.challengesRequests[g]; cl.Character = new Character(int.Parse(command[1]), command[2], this.Map.ID); cl.Character.Position.X = this.Map.StartPoint.X; cl.Character.Position.Y = this.Map.StartPoint.Y; cl.Send("player-character", new string[] { cl.Character.ID.ToString(), command[2] }); this.challengesRequests.Remove(g); //Aknowledge the other clients of this one foreach(Client oc in this.NetConnector.clients) { if(oc.ID != cl.ID) { oc.Send("character", new string[] { cl.Character.ID.ToString(), cl.Character.Name, cl.Character.Position.X.ToString(), cl.Character.Position.Y.ToString() }); cl.Send("character", new string[] { oc.Character.ID.ToString(), oc.Character.Name, oc.Character.Position.X.ToString(), oc.Character.Position.Y.ToString() }); } } } }
//Raises an event from its name public static void Raise(string eventName, Client c, string[] command) { //Boooh, switch, ugly as hell, but Reflection is a bit too hard to try raising static events dynamically. try { switch(eventName) { case "ping": Events.Ping(c, command); break; case "mapserver": Events.MapServer(c, command); break; case "exit": case "quit": Events.Quit(c, command); break; case "auth": Events.Auth(c, command); break; case "character-list": Events.CharacterList(c, command); break; case "set-character": Events.SetCharacter(c, command); break; case "getmap": Events.GetMap(c, command); break; case "get-position": Events.GetPosition(c, command); break; case "character-info": Events.CharacterInfo(c, command); break; case "ok": break; case "pong": break; case "server": break; case "moveleft": Events.MoveLeft(c, command); break; case "moveup": Events.MoveUp(c, command); break; case "movedown": Events.MoveDown(c, command); break; case "moveright": Events.MoveRight(c, command); break; case "error": Log.Write("[" + command[0] + "] " + command[1], Log.ErrorLevel.WARNING); break; default: Events.EventNotFound(c, new string[] { eventName }); break; } } catch(Exception e) { Log.Write("Exception catched: " + e.Message, Log.ErrorLevel.WARNING); c.Send(new ErrorException(ClientError.INTERNAL_ERROR, "Internal error")); } }
//Auth event callback : Authenticates the client from the data of the Head server, by a challenge check (GUID). //Usage: auth:<challenge> public void AuthEvent(Client c, string[] command) { Guid g; if(Guid.TryParse(command[0], out g)) { this.challengesRequests.Add(g, c); this.Client.Send("character-info", command); } else c.Send(new ErrorException(ClientError.INTERNAL_ERROR, "Malformed Guid")); }
public void CharacterListEvent(Client c, string[] command) { if(c.ClientID == null) { c.Send(new ErrorException(ClientError.NOT_AUTHED, "Auth first")); return; } c.Send("character-list-begin"); var chars = c.ListCharacters(); foreach(Character row in chars) c.Send("character", new string[]{row.ID.ToString(), row.Name}); c.Send("character-list-end"); }
//Waits and accepts a connection from an incoming client. Threaded. public void AcceptConnection() { Log.Write("Now listening for incoming connections.", Log.ErrorLevel.NOTICE); while(true) { Socket s = this.sock.Accept(); IPEndPoint remoteEndPoint = s.RemoteEndPoint as IPEndPoint; Client c = new Client(remoteEndPoint.Address, remoteEndPoint.Port, s); if(this.ClientConnect != null) this.ClientConnect(c); this.clients.Add (c); c.Send ("server", new string[]{ MainClass.ServerName }); } }
public void CharacterInfoEvent(Client c, string[] command) { if(c.MapServer) { Guid g; if(Guid.TryParse(command[0], out g)) { if(this.Challenges.ContainsKey(g)) { Character ch = this.Challenges[g]; c.Send("character-info", new string[] { command[0], ch.ID.ToString(), ch.Name }); } } else c.Send(new ErrorException(ClientError.INTERNAL_ERROR, "Malformed Guid")); } else c.Send(new ErrorException(ClientError.ACCESS_DENIED, "Access denied")); }
public void MoveUpEvent(Client c, string[] command) { if(c.Character.Position.Y > 0) { this.NetConnector.Broadcast("moveup", new string[] { c.ID.ToString() }, new int[] { c.ID }); c.Character.Position.Y--; } else this.GetPositionEvent(c, command); }
//Ping, reply pong with correct challenge public void PingEvent(Client c, string[] command) { c.Send("pong:" + command[0]); }
public void GetPositionEvent(Client c, string[] command) { c.Send("position", new string[] { c.Character.ID.ToString(), c.Character.Position.X.ToString(), c.Character.Position.Y.ToString() }); }
public void MoveRightEvent(Client c, string[] command) { c.Character.Position.X++; this.NetConnector.Broadcast("moveright", new string[] { c.ID.ToString() }, new int[] { c.ID }); }
//Callback called when a client disconnects public void ClientDisconnect(Client c) { Log.Write ("Client #" + c.ID + " disconnected.", Log.ErrorLevel.NOTICE); if(c.Character != null) { foreach(Client cl in this.NetConnector.clients) { if(cl.ID != c.ID) cl.Send("character-out", new string[] { c.Character.ID.ToString()}); } } }
//GetMap event callback : returns a fragment of the map to the client //Usage: getmap public void GetMapEvent(Client c, string[] command) { c.Send("change-tileset", new string[] { this.Map.Tileset }); short startX = c.Character.Position.X; short startY = c.Character.Position.Y; short t; for(t = 4; t*4 < startX; t += 4); startX = t; for(t = 4; t*4 < startY; t += 4); startY = t; startX -= 16; startY -= 16; Chunk ch; for(short i = 0; i < 32; i+=4) { for(short j = 0; j < 32; j += 4) { if((ch = this.Map.GetChunk(new Coordinate((short)(startX + i), (short)(startY + j)))) != null) { c.Send("chunk", ch.ToStringArray()); Thread.Sleep(5); } } } }
public void ClientDisconnect(Client c) { if(this.MapClients.ContainsKey(c.ID)) { Log.Write("Unregistered MapServer using map "+ this.MapClients[c.ID].MapName + "(" + this.MapClients[c.ID].MapID + ")", Log.ErrorLevel.DEBUG); this.MapClients.Remove(c.ID); } Log.Write ("Client #" + c.ID + " disconnected.", Log.ErrorLevel.NOTICE); }
//Callback called when a client connects public void ClientConnect(Client c) { Log.Write("Client connected: #" + c.ID.ToString(), Log.ErrorLevel.DEBUG); //c.Character = new Character(); }
public void Disconnect(Client c, bool notify = true) { if(notify) c.Send("bye"); Console.WriteLine(c.ToString()); if(this.ClientDisconnect != null) this.ClientDisconnect(c); c.Disconnect(); this.clients.Remove(c); }
//Default event called when a command has not triggered another event public void EventNotFound(Client c, string[] command) { c.Send(new ErrorException(ClientError.UNKNOWN_COMMAND, "Unknown command: " + command[0])); }
public void AuthEvent(Client c, string[] command) { if(!c.Authentify(command[0], command[1])) c.Send(new ErrorException(ClientError.INVALID_LOGIN, "Invalid login/password")); }
public void SetCharacterEvent(Client c, string[] command) { var chars = c.ListCharacters(); int id = int.Parse(command[0]); foreach(Character ch in chars) { if(ch.ID == id) { MapServerClient msc = this.GetMapServer(ch.LastMap); if(msc == null) { c.Send(new ErrorException(ClientError.INTERNAL_ERROR, "Internal error")); return; } Guid g = Guid.NewGuid(); this.Challenges.Add(g, ch); c.Send("connect", new string[] { g.ToString(), msc.c.Address.ToString(), msc.c.Port.ToString() }); return; } } c.Send(new ErrorException(ClientError.UNKNOWN_CHARACTER, "Unknown character")); }
//MapServer event callback: sets the map provided by the map server sending the command. //Note: the client sending this command has to be authed as a map server. //Usage: mapserver:<mapid>.<mapname> //mapid: Map identifier, alphanumeric. //mapname: the name of the map, in human-fancy form. public void MapServerEvent(Client c, string[] command) { if(c.MapServer) { Log.Write("Client #" + c.ID + " is now defined as a map server, with map '" + command[0] + "'.", Log.ErrorLevel.DEBUG); MapServerClient msp = new MapServerClient(c); this.MapClients.Add (c.ID, msp); msp.MapID = command[0]; msp.MapName = command[1]; c.Port = int.Parse(command[2]); } else c.Send(new ErrorException(ClientError.ACCESS_DENIED, "Access denied")); }
public MapServerClient(Client c) { this.c = c; }
//Client disconnection, we disconnect it public void QuitEvent(Client c, string[] command) { this.NetConnector.Disconnect(c); }