using System; using System.Collections.Generic; using System.Linq; using System.Text; using GenericNetplayImplementation; using System.IO; namespace mmoRLserver { class Program : GNIServer { public bool DEBUGMODE = true; public bool running = true; public static Dictionary maps = new Dictionary(); public static Dictionary players = new Dictionary(); public List playerList = new List(); public Dictionary instances = new Dictionary(); public Dictionary> parties = new Dictionary>(); public Dictionary fastMode = new Dictionary(); public static List signalQueue = new List(); public int autoSaveCounter = 1800; public int AUTOSAVE_DELAY = 1800; public List reservedNames = new List(); public static int CURRENTVERSION = 2; StreamWriter logFile; StreamWriter nameFile; static void Main(string[] args) { new Program().DoStuff(); } public void DoStuff() { logFile = new StreamWriter("log.txt", true); logFile.WriteLine("-----------LOG START---------"); Log("Initializing..."); Initialize(); int port = 51525; if (File.Exists("mrlserver.ini")) { StreamReader sr = new StreamReader("mrlowserver.ini"); while (!sr.EndOfStream) { string configLine = sr.ReadLine(); if (configLine.StartsWith("port=")) { port = Convert.ToInt32(configLine.Split(new string[] { "=" }, StringSplitOptions.None)[1]); Log("Port changed to " + port + "."); } } sr.Close(); } if (File.Exists("names.dat")) { StreamReader sr = new StreamReader("names.dat"); while (!sr.EndOfStream) { string readName = sr.ReadLine(); reservedNames.Add(readName.ToLower()); } sr.Close(); } nameFile = new StreamWriter("names.dat", true); if (File.Exists("instances.dat")) { StreamReader sr = new StreamReader("instances.dat"); while (!sr.EndOfStream) { string instanceLine = sr.ReadLine(); if (!instanceLine.StartsWith("//")) //Comment { if (instanceLine.Replace(" ", "") != "") //Empty line { if (instanceLine.Contains("=")) //Just to make sure { string[] split = instanceLine.Split(new string[] { "=" }, StringSplitOptions.None); string[] biomes = split[1].Split(new string[] { "," }, StringSplitOptions.None); string variation = ""; if (biomes[biomes.Length - 1].Contains(";")) { string[] varSplit = biomes[biomes.Length - 1].Split(new string[] { ";" }, StringSplitOptions.None); biomes[biomes.Length - 1] = varSplit[0]; variation = varSplit[1]; } Biome[] listedBiomes = new Biome[biomes.Length]; for(int i = 0; i < biomes.Length; i++) { listedBiomes[i] = Map.StringToBiome(biomes[i]); } Instance instance = new Instance(listedBiomes, variation); instances.Add(split[0], instance); } } } } } StartServer(port, true); Log("Server started."); System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(delegate { while (running) { string input = Console.ReadLine(); string[] split = input.Split(new string[] { " " }, StringSplitOptions.None); Log(">" + input); if (input.Length > 3) { try { //--------------------------------------------------------------------- switch (input.Substring(0, 4)) { case "save": SaveAllMaps(); SaveAllPlayers(); break; case "load": LoadAllMaps(); break; case "exit": running = false; break; case "item": { int itemType = Convert.ToInt32(split[1]); string loc = split[2]; int x = Convert.ToInt32(split[3]); int y = Convert.ToInt32(split[4]); Item toSpawn = new Item(itemType, x, y); maps[loc].items.Add(toSpawn); Log("Created item " + toSpawn.id + " in " + loc); } break; case "grit": { string playerName = split[1]; int amount = Convert.ToInt32(split[2]); int itemType = Convert.ToInt32(split[3]); Item toSpawn = new Item(itemType); toSpawn.SetAmount(amount); Player player = GetPlayer(playerName); player.items.Add(toSpawn); for (int i = 0; i < amount; i++) { SendSignal(player.client, new GNIData("gi", toSpawn.id)); } Log("Gave item " + toSpawn.id + " to " + playerName); } break; case "grxp": { string playerName = split[1]; int amount = Convert.ToInt32(split[2]); GetPlayer(playerName).GainExperience(amount); GetPlayer(playerName).RecalculateStats(); Log("Gave " + playerName + " " + amount + " experience"); } break; case "gral": { string playerName = split[1]; Player player = GetPlayer(playerName); player.GainExperience(500000); for (int i = 0; i < 200; i++) { Item toSpawn = new Item(i); GetPlayer(playerName).items.Add(toSpawn); SendSignal(GetPlayer(playerName).client, new GNIData("gi", toSpawn.id)); } Log("Gave " + playerName + " everything."); } break; } //----------------------------------------------------------------- } catch (Exception ex) { Log("ERROR: " + ex.Message); } } } })); System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(delegate { while (true) { try { List signals = new List(); foreach(QueuedSignal qs in signalQueue) { signals.Add(qs); } signalQueue.Clear(); for (int i = 0; i < signals.Count; i++) { SendSignal(signals[i].recipient, signals[i].data); } } catch (Exception) { } System.Threading.Thread.Sleep(1000); } })); while(running) { System.Threading.Thread.Sleep(1000); BroadcastSignal(new GNIData() { keyType = GNIDataType.None, valueType = GNIDataType.None }); autoSaveCounter--; if (autoSaveCounter <= 0) { SaveAllMaps(); SaveAllPlayers(); autoSaveCounter = AUTOSAVE_DELAY; } } BroadcastSignal(new GNIData("exit", 0)); nameFile.Close(); logFile.Close(); } public void Initialize() { //Make sure there's a player folder if (!Directory.Exists("players")) Directory.CreateDirectory("players"); //Load all existing maps from disk if (!LoadAllMaps()) { //Otherwise, generate the starting map. Map starterMap = new Map("starter"); starterMap.biome = Biome.START; maps.Add(starterMap.id, starterMap); } } public override void OnDataReceived(GNIData data, uint source = 0) { switch (data.keyString) { //==Logging in== case "version": if (data.valueInt == CURRENTVERSION) SendSignal(source, new GNIData("key", 0)); else SendSignal(source, new GNIData("error", "Outdated version. Please update to the release build at 7drl.roguetemple.com.")); break; case "key": PlayerLogsIn(GetClient(source), data.valueString); break; //============== case "loc": { Player player = players[source]; player.location = data.valueString; BroadcastSignal(new GNIData("loc" + player.id, data.valueString)); //Use 'Recovery' skill if (player.HasSkill(1)) { if (!maps[player.location].turnBased) { if (player.HP < 25) player.RecoverTo(25); } } //Check if any other players are in the same location; send the player positions of them for (int i = 0; i < playerList.Count; i++) { if (playerList[i].location == data.valueString) { GNIData toSend = new GNIData() { keyType = GNIDataType.Short, valueType = GNIDataType.Short, keyInt = playerList[i].id, valueInt = playerList[i].y * 100 + playerList[i].x }; SendSignal(source, toSend); } } //HandleTurn(source); } break; case "chat": BroadcastSignal(new GNIData("msg", "@3<" + players[source].name + "> " + data.valueString)); Log("<" + players[source].name + "> " + data.valueString); break; case "map": { string requestedMap = data.valueString; SendMap(requestedMap, source); } break; case "name": if (!reservedNames.Contains(data.valueString.ToLower())) { AddName(data.valueString.ToLower()); Log("Player '" + players[source].name + "' has identified as '" + data.valueString + "'."); players[source].name = data.valueString; EnterWorld(players[source]); } else { SendSignal(source, new GNIData("noname", 0)); } break; case "attack": { string loc = players[source].location; int x = GetX(data.valueInt); int y = GetY(data.valueInt); Monster monster = maps[loc].GetMonsterAtPosition(x, y); if (monster == null) SendSignal(source, new GNIData("air", 0)); else { AttackResult attackResult = monster.BeAttacked(players[source]); if (attackResult == AttackResult.Hit) //Hit, Monster survives { SendSignal(source, new GNIData("hit", 0)); } else if (attackResult == AttackResult.Dead) //Monster dies { KillMonster(monster, players[source], maps[players[source].location]); } else { SendSignal(source, new GNIData("miss", 0)); } } HandleTurn(source, true); } break; case "startparty": { Player player = players[source]; Player invitee = GetPlayer(data.valueString); if (invitee.party == "") { player.party = player.name; invitee.party = player.name; player.instanceTarget = player.name; invitee.instanceTarget = player.name; List members = new List(); members.Add(player); members.Add(invitee); parties.Add(player.name, members); SendSignal(source, new GNIData("partycreated", 0)); SendSignal(invitee.client, new GNIData("joinparty", player.name)); } else { SendSignal(source, new GNIData("partyfailed", 0)); } } break; case "addparty": { string partyName = players[source].name; Player invitee = GetPlayer(data.valueString); if (invitee.party == "") { SendToParty(partyName, new GNIData("newmember", invitee.name)); invitee.party = partyName; invitee.instanceTarget = partyName; parties[partyName].Add(invitee); SendSignal(source, new GNIData("invitesuccess", 0)); string partyString = partyName; for (int i = 1; i < parties[partyName].Count; i++) { partyString += "," + parties[partyName][i]; } SendSignal(invitee.client, new GNIData("joinparty", partyString)); } else { SendSignal(source, new GNIData("invitefailed", 0)); } } break; case "leaveparty": { LeaveParty(players[source]); } break; case "disbandparty": { DisbandParty(players[source].name); } break; case "togglefast": { if (IsFast(players[source].party)) SetFast(players[source].party, false); else { SetFast(players[source].party, true); if (players[source].finishedTurn) HandleTurn(source); } } break; case "learn": { if (players[source].Learn(data.valueInt)) { HandleTurn(source); SendSignal(source, new GNIData("teach", data.valueInt)); } else { SendSignal(source, new GNIData("faillearn", 0)); } } break; case "discover": { Skill toDiscover = Skill.GetSkill(data.valueInt); if (players[source].HasSkill(data.valueInt)) { SendSignal(source, new GNIData("nodisc", 2)); } else if (players[source].KnowsAboutSkill(data.valueInt)) { SendSignal(source, new GNIData("nodisc", 2)); } else { bool canLearn = true; for (int i = 0; i < toDiscover.requiredSkills.Length; i++) { if (!players[source].HasSkill(toDiscover.requiredSkills[i])) canLearn = false; } if (canLearn) { players[source].AddLearnable(data.valueInt); HandleTurn(source); SendSignal(source, new GNIData("disc", data.valueInt)); } else { SendSignal(source, new GNIData("nodisc", 1)); } } } break; case "ai": //Add item { Item foundItem = null; for (int i = 0; i < players[source].items.Count; i++) { if (players[source].items[i].id == data.valueInt) foundItem = players[source].items[i]; } if (foundItem != null) { foundItem.AddAmount(1); } else { players[source].items.Add(new Item(data.valueInt)); } } break; case "ri": //Remove item { Item foundItem = null; for (int i = 0; i < players[source].items.Count; i++) { if (players[source].items[i].id == data.valueInt) foundItem = players[source].items[i]; } if (foundItem != null) { foundItem.amount--; if (foundItem.amount <= 0) players[source].items.Remove(foundItem); } } break; case "equip": { if (players[source].EquipItem(data.valueInt)) { HandleTurn(source); SendSignal(source, new GNIData("equip" + new Item(data.valueInt).equipmentType, data.valueInt)); } else { SendSignal(source, new GNIData("error", "Data desynchronization. Please relog.")); } } break; case "unequip": players[source].UnEquipItem(data.valueInt); HandleTurn(source); SendSignal(source, new GNIData("unequip", 0)); break; case "gainxp": players[source].GainExperience(data.valueInt); players[source].RecalculateStats(); break; case "skipturn": HandleTurn(source); break; case "town": { string requestedMap = "town_" + data.valueString; SendMap(requestedMap, source, true); } break; case "refresh": { GNIData toSend = new GNIData() { keyType = GNIDataType.String, valueType = GNIDataType.ByteArray, keyString = "smap", valueBytes = maps[players[source].location].Serialize() }; SendSignal(source, toSend); players[source].RecalculateStats(); SendSignal(source, new GNIData("finishrefresh", 0)); } break; } switch (data.keyInt) { case 17: //Position update case 18: { players[source].y = (int)Math.Floor((float)data.valueInt / 100f); players[source].x = data.valueInt - (players[source].y * 100); //Check if this is relevant for any other players for (int i = 0; i < playerList.Count; i++) { if (playerList[i].location == players[source].location) { GNIData toSend = new GNIData() { keyType = GNIDataType.Short, valueType = GNIDataType.Short, keyInt = players[source].id, valueInt = data.valueInt }; SendSignal(playerList[i].client, toSend); } } if (!players[source].firstTurn) { if (data.keyInt != 18) //Silent update { HandleTurn(source); } } else players[source].firstTurn = false; } break; } if (data.keyString.StartsWith("object")) { //Change object on server map string[] split = data.keyString.Split(new string[] { "|" }, StringSplitOptions.None); maps[players[source].location].objects[Convert.ToInt32(split[1]), Convert.ToInt32(split[2])] = new Object(data.valueInt); //Then relay info to people already on the map for (int i = 0; i < playerList.Count; i++) { if(playerList[i].location == players[source].location) SendSignal(playerList[i].client, data); } } else if (data.keyString.StartsWith("itemadd")) { //Add item on server map string[] split = data.keyString.Split(new string[] { "|" }, StringSplitOptions.None); maps[players[source].location].items.Add(new Item(data.valueInt, Convert.ToInt32(split[1]), Convert.ToInt32(split[2]))); //Then relay info to people already on the map for (int i = 0; i < playerList.Count; i++) { if (playerList[i].location == players[source].location) SendSignal(playerList[i].client, data); } } else if (data.keyString.StartsWith("itemrem")) { //Add item on server map string[] split = data.keyString.Split(new string[] { "|" }, StringSplitOptions.None); Item toRemove = null; for (int i = 0; i < maps[players[source].location].items.Count; i++) { if (maps[players[source].location].items[i].id == data.valueInt) { if (maps[players[source].location].items[i].x == Convert.ToInt32(split[1]) && maps[players[source].location].items[i].y == Convert.ToInt32(split[2])) { toRemove = maps[players[source].location].items[i]; } } } if (toRemove != null) maps[players[source].location].items.Remove(toRemove); //Then relay info to other people already on the map - original already deleted it for (int i = 0; i < playerList.Count; i++) { if (playerList[i].location == players[source].location && playerList[i].client.clientID != source) SendSignal(playerList[i].client, data); } } } //Handle turn in player's instance or wait for other players public void HandleTurn(uint playerID, bool force = false) { Player player = players[playerID]; player.finishedTurn = true; if (maps[player.location].turnBased || force) { if (player.party == "") { HandleLocationTurn(player.location); GNIData toSend = new GNIData(true); toSend.valueType = GNIDataType.None; toSend.keyString = "t"; toSend.keyType = GNIDataType.String; //Use 'Regeneration' skill if (player.HasSkill(2)) player.Recover(1); SendSignal(playerID, toSend); } else { bool allFinished = true; List p = parties[player.party]; for (int i = 0; i < p.Count; i++) { if (p[i].location == player.location) { if (!p[i].finishedTurn) allFinished = false; } } if (allFinished || IsFast(player.party) || force) { HandleLocationTurn(player.location); GNIData toSend = new GNIData(true); toSend.valueType = GNIDataType.None; toSend.keyString = "t"; toSend.keyType = GNIDataType.String; //Everybody can start the turn again for (int i = 0; i < p.Count; i++) { if (p[i].location == player.location) { p[i].finishedTurn = false; //Use 'Regeneration' skill if (p[i].HasSkill(2)) p[i].Recover(1); } } SendToParty(player.party, toSend, player.location); } else { GNIData toSend = new GNIData(true); toSend.valueType = GNIDataType.None; toSend.keyString = "w"; toSend.keyType = GNIDataType.String; SendSignal(playerID, toSend); } } } } public void HandleLocationTurn(string location) { Map map = maps[location]; List allPlayers = playerList; List playersAtLocation = new List(); for(int i = 0; i < allPlayers.Count; i++) { if(allPlayers[i] != null) { if (allPlayers[i].location == location) playersAtLocation.Add(allPlayers[i]); } } for (int i = 0; i < map.monsters.Count; i++) { Monster monster = map.monsters[i]; string outcome = map.monsters[i].HandleTurn(map, playersAtLocation); string[] split = outcome.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries); for (int ii = 0; ii < split.Length; ii++) { string[] split2 = split[ii].Split(new string[] { "," }, StringSplitOptions.None); string action = split2[0]; int originalX = Convert.ToInt32(split2[1]); int originalY = Convert.ToInt32(split2[2]); switch (action) { //Monster moves in direction case "mc": case "mu": case "md": case "ml": case "mr": SendToArea(location, new GNIData(action, GetXY(originalX, originalY))); break; case "ma": SendSignal(monster.targetPlayer.client, new GNIData("ma", GetXY(originalX, originalY))); SendSignal(monster.targetPlayer.client, new GNIData("hp", monster.targetPlayer.HP)); if (monster.targetPlayer.dead) { KillPlayer(monster.targetPlayer); } break; case "mm": SendSignal(monster.targetPlayer.client, new GNIData("mm", GetXY(originalX, originalY))); break; } } } } public override void OnClientConnected(GNIClientInformation client) { Log("Client connected!"); SendSignal(client, new GNIData("version", 0)); } public void PlayerLogsIn(GNIClientInformation client, string userKey) { try { Player player = null; bool loaded = false; //Load player's character string fileName = "players/" + userKey + ".mrc"; if (File.Exists(fileName)) { FileStream fs = new FileStream(fileName, FileMode.Open); BinaryReader br = new BinaryReader(fs); byte[] serializedCharacter = br.ReadBytes((int)fs.Length); br.Close(); fs.Close(); player = new Player(client); player.DeSerialize(serializedCharacter); loaded = true; } else { player = CreateNewPlayer(client); SendSignal(client, new GNIData("newchar", 0)); } player.key = userKey; //Add to both lists players.Add(client.clientID, player); playerList.Add(player); StartPlayerGame(player); if (loaded) { EnterWorld(player); } } catch (Exception ex) //Stop connection rather than loading (and breaking) character data { Log("U_ERROR: " + ex.Message); SendSignal(client, new GNIData("error", "Error while creating or loading character.")); } } public void StartPlayerGame(Player player) { player.finishedTurn = false; GNIClientInformation client = player.client; //Give player his ID SendSignal(client, new GNIData("id", player.id)); //Send player his learnables for (int i = 0; i < player.learnPool.Count; i++) { SendSignal(client, new GNIData("pool", player.learnPool[i].id)); } //Send player his skills for (int i = 0; i < player.skills.Count; i++) { SendSignal(client, new GNIData("steach", player.skills[i].id)); } //Send player his items for (int i = 0; i < player.items.Count; i++) { for (int ii = 0; ii < player.items[i].amount; ii++) { SendSignal(client, new GNIData("gi", player.items[i].id)); //And equip it if (player.items[i].equipped) { SendSignal(client, new GNIData("sequip" + player.items[i].equipmentType, player.items[i].id)); } } } //Send player his name SendSignal(client, new GNIData("myname", player.name)); //Send player his stats player.RecalculateStats(); //Send player his x and y SendSignal(client, new GNIData("setx", player.x)); SendSignal(client, new GNIData("sety", player.y)); //Tell player about other players for (int i = 0; i < playerList.Count; i++) { if (playerList[i].id != player.id) { SendSignal(client, new GNIData("name" + playerList[i].id, playerList[i].name)); SendSignal(client, new GNIData("loc" + playerList[i].id, playerList[i].location)); if (playerList[i].location == player.location) { GNIData toSend = new GNIData() { keyType = GNIDataType.Short, valueType = GNIDataType.Short, keyInt = playerList[i].id, valueInt = playerList[i].y * 100 + playerList[i].x }; SendSignal(client, toSend); } } } SendSignal(client, new GNIData("msg", "@0Welcome to mmoRL!")); SendMap(player.location, client.clientID); player.ready = true; } public override void OnClientDisconnected(GNIClientInformation client) { if (players.ContainsKey(client.clientID)) { //Leave any party he's in LeaveParty(players[client.clientID]); //Remove from both lists Player toRemove = null; for (int i = 0; i < playerList.Count; i++) { if (playerList[i].client.clientID == client.clientID) toRemove = playerList[i]; } if (toRemove != null) { playerList.Remove(toRemove); } players.Remove(client.clientID); if (toRemove != null) { Log(toRemove.name + " disconnected!"); BroadcastSignal(new GNIData("left", toRemove.id)); BroadcastSignal(new GNIData("msg", "@6" + toRemove.name + " has left mmoRL!")); } //Serialize the player if he's not dead if (toRemove != null) { SavePlayer(toRemove); } if (toRemove != null) { toRemove.ready = false; } } } public Player CreateNewPlayer(GNIClientInformation client) { Player toReturn = new Player(client); toReturn.AddLearnable(1); //Recovery toReturn.AddLearnable(2); //Regeneration toReturn.AddLearnable(3); //Crafting toReturn.location = "starter"; return toReturn; } public void SavePlayer(Player player) { if (!player.dead) { FileStream fs = new FileStream("players/" + player.key + ".mrc", FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(player.Serialize()); bw.Close(); fs.Close(); } } public void SendMap(string requestedMap, uint source, bool isTown = false) { Player player = players[source]; if (!instances.ContainsKey(requestedMap)) player.instanceTarget = ""; string target = requestedMap; if (player.instanceTarget != "") target = requestedMap + "_" + player.instanceTarget; else target = requestedMap + "_" + player.name; if (maps.ContainsKey(target)) { requestedMap = target; //Fetch his instance } else if (instances.ContainsKey(requestedMap)) { //Generate a new instance for the guy //Start with the name string instanceName = target; //Create map Map newInstance = new Map(instanceName); //Get random possible biome newInstance.biome = instances[requestedMap].possibleBiomes[new Random().Next(instances[requestedMap].possibleBiomes.Count)]; newInstance.variation = instances[requestedMap].variation; //Register map maps.Add(newInstance.id, newInstance); //Set map as requested requestedMap = newInstance.id; } else if (isTown) { if (!maps.ContainsKey(requestedMap)) { Map newTown = new Map(requestedMap); newTown.biome = Biome.TOWN; maps.Add(requestedMap, newTown); } } maps[requestedMap].InitializeMap(player.x, player.y); GNIData toSend = new GNIData() { keyType = GNIDataType.String, valueType = GNIDataType.ByteArray, keyString = "map", valueBytes = maps[requestedMap].Serialize() }; SendSignal(source, toSend); } public void SaveAllMaps() { Log("Saving all maps..."); if (!Directory.Exists("maps")) Directory.CreateDirectory("maps"); foreach (KeyValuePair kp in maps) { try { if (kp.Value.initialized) { FileStream fs = new FileStream("maps/" + kp.Key + ".owm", FileMode.Create); BinaryWriter bw = new BinaryWriter(fs); bw.Write(kp.Value.Serialize()); bw.Close(); fs.Close(); } } catch (Exception ex) { Log("Error while saving map " + kp.Key + "!: " + ex.Message); } } Log("Saved all maps!"); } public void SaveAllPlayers() { Log("Saving all players..."); foreach (KeyValuePair kp in players) { try { if (kp.Value.ready) SavePlayer(kp.Value); } catch { } } Log("Saved all players!"); } public bool LoadAllMaps() { Log("Loading all maps..."); try { if (Directory.Exists("maps")) { string[] files = Directory.GetFiles("maps"); for (int i = 0; i < files.Length; i++) { try { if (files[i].ToLower().EndsWith(".owm")) { FileStream fs = new FileStream(files[i], FileMode.Open); BinaryReader br = new BinaryReader(fs); Map map = new Map(br.ReadBytes((int)br.BaseStream.Length)); maps[map.id] = map; br.Close(); fs.Close(); } } catch (Exception ex) { Log("Error while loading map " + files[i] + "!: " + ex.Message); } } Log("Loaded all maps!"); return true; } else { Log("No map folder found."); return false; } } catch (Exception ex) { Log("Unexpected error while loading maps!: " + ex.Message); } return false; } public void EnterWorld(Player player) { SendSignal(player.client, new GNIData("start", 0)); BroadcastSignal(new GNIData("name" + player.id, player.name)); BroadcastSignal(new GNIData("msg", "@b" + player.name + " has joined mmoRL!")); player.RecalculateStats(); } //--------------------------------- //Party stuff. Also I apologize for this mess public void LeaveParty(Player player) { string partyName = player.party; if (partyName != "") { if (parties.ContainsKey(partyName)) { parties[partyName].Remove(player); if (parties[partyName].Count <= 1 || partyName == player.name) DisbandParty(partyName); player.party = ""; } SendSignal(player.client, new GNIData("leaveparty", 0)); SendToParty(partyName, new GNIData("leftparty", player.name)); } } public void DisbandParty(string partyName) { if (parties.ContainsKey(partyName)) { for (int i = 0; i < parties[partyName].Count; i++) { parties[partyName][i].party = ""; } SendToParty(partyName, new GNIData("delparty", 0)); parties.Remove(partyName); } } public void SendToParty(string party, GNIData data, string locationRequirement = "", uint exception = uint.MaxValue) { if (parties.ContainsKey(party)) { for (int i = 0; i < parties[party].Count; i++) { if (locationRequirement == "" || parties[party][i].location == locationRequirement) { if (parties[party][i].client.clientID != exception) { SendSignal(parties[party][i].client, data); } } } } } public void SendToArea(string area, GNIData data) { for (int i = 0; i < playerList.Count; i++) { if (playerList[i] != null) { if (playerList[i].location == area) { SendSignal(playerList[i].client, data); } } } } //----------Combat and death stuff-------- public void KillPlayer(Player player) { for (int i = 0; i < player.items.Count; i++) { player.items[i].x = player.x; player.items[i].y = player.y; maps[player.location].items.Add(player.items[i]); SendToArea(player.location, new GNIData("itemadd|" + player.x + "|" + player.y, player.items[i].id)); } SendSignal(player.client, new GNIData("die", 0)); BroadcastSignal(new GNIData("msg", "@4" + player.name + " has died!")); LeaveParty(player); player.location = "heaven"; BroadcastSignal(new GNIData("loc" + player.id, "heaven")); if (File.Exists("players/" + player.key + ".mrc")) { File.Delete("players/" + player.key + ".mrc"); } player.ready = false; } public void KillMonster(Monster monster, Player killer, Map map) { if (killer != null) { killer.GainExperience(monster.experience); SendSignal(killer.client, new GNIData("xp", killer.experience)); SendSignal(killer.client, new GNIData("hitandkill", GetXY(monster.x, monster.y))); } SendToArea(map.id, new GNIData("killmonster", GetXY(monster.x, monster.y))); List generatedItems = map.MonsterDies(monster); for (int i = 0; i < generatedItems.Count; i++) { SendToArea(map.id, new GNIData("itemadd|" + monster.x + "|" + monster.y, generatedItems[i].id)); } if (map.monsters.Count == 0) map.turnBased = false; } //--------------------------------- public int GetXY(int x, int y) { return y * 100 + x; } public int GetX(int xyInt) { return xyInt - ((int)Math.Floor((float)xyInt / 100f) * 100); } public int GetY(int xyInt) { return (int)Math.Floor((float)xyInt / 100f); } public Player GetPlayer(string name) { List p = this.playerList; for (int i = 0; i < p.Count; i++) { if (p[i].name == name) return p[i]; } return null; } public bool IsFast(string party) { if (fastMode.ContainsKey(party)) return fastMode[party]; else return false; } public void SetFast(string party, bool value) { if (fastMode.ContainsKey(party)) fastMode.Remove(party); fastMode.Add(party, value); if (value) { SendToParty(party, new GNIData("msg", "Party speed set to FAST.")); //gota go fast } else { SendToParty(party, new GNIData("msg", "Party speed set to SLOW.")); } } //----------------------- public static void QueueSignal(uint recipient, GNIData data) { bool done = false; while (!done) { try { signalQueue.Add(new QueuedSignal(recipient, data)); done = true; } catch (Exception) { System.Threading.Thread.Sleep(11); } } } //----------------------- public void Log(string msg) { string year = DateTime.Now.Year.ToString(); string month = DateTime.Now.Month.ToString(); string day = DateTime.Now.Day.ToString(); string hours = DateTime.Now.Hour.ToString(); string minutes = DateTime.Now.Minute.ToString(); if (month.Length < 2) month = "0" + month; if (day.Length < 2) day = "0" + day; if (hours.Length < 2) hours = "0" + hours; if (minutes.Length < 2) minutes = "0" + minutes; msg = "[" + year + "/" + month + "/" + day + " " + hours + ":" + minutes + "] " + msg; Console.WriteLine(msg); logFile.WriteLine(msg); logFile.Flush(); } public void DLog(string msg) { if (DEBUGMODE) Console.WriteLine(msg); } public void AddName(string msg) { reservedNames.Add(msg); nameFile.WriteLine(msg); nameFile.Flush(); } } }