using System; using System.Collections.Generic; using System.Linq; using System.Text; using GenericNetplayImplementation; using WOMGeneral; using System.IO; namespace WOMServer { class Program : GNIServer { public const int NUM_CELLS_X = 512; public const int NUM_CELLS_Y = 512; public const int START_CELL_X = 256; public const int START_CELL_Y = 256; public int tick_length = 100; //Amount of ms in a tick public int ticksToAutosave = 18000; public int ticksToPing = 1000; public int autosaveCounter = 18000; public int pingCounter = 1000; public int port = 51535; public string cellFolder = "cells/"; private DataSender dataSender; public Cell[,] cells = new Cell[NUM_CELLS_X, NUM_CELLS_Y]; public bool running = true; static void Main(string[] args) { new Program().DoStuff(); } public void DoStuff() { Initialize(); } public void Initialize() { Log("Initializing..."); LoadAllCellsFromDisk(); System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(delegate { while (running) { try { System.Threading.Thread.Sleep(tick_length); autosaveCounter--; if (autosaveCounter < 0) { SaveAllCellsToDisk(); autosaveCounter = ticksToAutosave; } pingCounter--; if (pingCounter < 0) { GNIData toSend = new GNIData(true); toSend.SetData(1007, 0); BroadcastSignal(toSend); pingCounter = ticksToPing; } } catch { } } })); dataSender = new DataSender(this); StartServer(port, true, true, true); Log("Ready."); MainLoop(); } public void MainLoop() { while (running) { try { string command = Console.ReadLine(); switch (command.Split(new string[] { " " }, StringSplitOptions.None)[0].ToLower()) { case "save": SaveAllCellsToDisk(); break; case "exit": running = false; break; } } catch (Exception ex) { Log("EXCEPTION: " + ex.Message); } } } //----------------------- public override void OnDataReceived(GNIData data, uint source = 0) { switch (data.keyType) { case GNIDataType.Short: switch (data.keyInt) { case 1: //Request for starting position { dataSender.SendID(source); dataSender.SendStartingPosition(source); //Send players for (int i = 0; i < this.clients.Count; i++) { GNIData toSend = new GNIData(true); toSend.SetData(1004, (int)clients[i].clientID); SendSignal(source, toSend); } break; } case 2: //Request for cell dataSender.SendCell(source, new Address(data.valueBytes)); break; case 3: //Change tile //Get address MemoryStream ms = new MemoryStream(data.valueBytes); byte[] addressBuffer = new byte[6]; ms.Read(addressBuffer, 0, 6); Address address = new Address(addressBuffer); //Change tile byte[] tileBuffer = new byte[ms.Length - 6]; ms.Read(tileBuffer, 0, tileBuffer.Length); GetCell(address.cellX, address.cellY).unmodified = false; GetCell(address.cellX, address.cellY).tiles[address.x, address.y].Deserialize(tileBuffer); //Reserialize the tile (client serialization may be suboptimal) and send it to all byte[] tileBuffer2 = GetCell(address.cellX, address.cellY).tiles[address.x, address.y].Serialize(); dataSender.SendTileToAll(address, tileBuffer2); break; case 4: //Update position { GNIData toSend = new GNIData(true); toSend.keyType = GNIDataType.Short; toSend.keyInt = (int)source; toSend.valueType = GNIDataType.ByteArray; toSend.valueBytes = data.valueBytes; BroadcastSignal(toSend); break; } } break; } base.OnDataReceived(data, source); } public override void OnClientConnected(GNIClientInformation client) { GNIData toSend = new GNIData(true); toSend.SetData(1004, (int)client.clientID); BroadcastSignal(toSend); base.OnClientConnected(client); } public override void OnClientDisconnected(GNIClientInformation client) { DropPlayer(client); base.OnClientDisconnected(client); } public void DropPlayer(GNIClientInformation client) { GNIData toSend = new GNIData(true); toSend.SetData(1005, (int)client.clientID); BroadcastSignal(toSend); } //----------------------- public Cell GetCell(int x, int y) { if (cells[x, y] == null) { cells[x, y] = new Cell(x, y); } return cells[x, y]; } public void LoadAllCellsFromDisk() { Log("Loading cells from disk..."); string[] cellNames = Directory.GetFiles("cells"); for (int i = 0; i < cellNames.Length; i++) { FileStream fs = new FileStream(cellNames[i], FileMode.Open); byte[] buffer = new byte[fs.Length]; fs.Read(buffer, 0, buffer.Length); fs.Close(); Cell result = new Cell(buffer); cells[result.x, result.y] = result; } Log("Cells loaded!"); } public void SaveAllCellsToDisk() { Log("Saving all cells to disk..."); for (int iy = 0; iy < NUM_CELLS_Y; iy++) { for (int ix = 0; ix < NUM_CELLS_X; ix++) { if (cells[ix, iy] != null) { byte[] toWrite = SerializeCell(ix, iy); FileStream fs = new FileStream(cellFolder + ix + "-" + iy + ".wmc", FileMode.Create); fs.Write(toWrite, 0, toWrite.Length); fs.Close(); } } } Log("All cells saved to disk."); } public byte[] SerializeCell(int x, int y) { return cells[x, y].Serialize(); } //----------------------- public void Log(string message) { Console.WriteLine(message); } } }