diff --git a/FNAF_Clone.sln.DotSettings.user b/FNAF_Clone.sln.DotSettings.user index 407f818..4f3470d 100644 --- a/FNAF_Clone.sln.DotSettings.user +++ b/FNAF_Clone.sln.DotSettings.user @@ -7,11 +7,13 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded \ No newline at end of file diff --git a/FNAF_Clone/Client.cs b/FNAF_Clone/Client.cs index 6955f2b..07da325 100644 --- a/FNAF_Clone/Client.cs +++ b/FNAF_Clone/Client.cs @@ -96,13 +96,14 @@ public class Client { Player.state = packet.state; } + #nullable enable private static void OnMapInit(MapInitPacket packet) { - (int id1, int id2, ConnectorType type)[] connectorsData = new (int id1, int id2, ConnectorType type)[packet.Connectors.Length / 3]; - for (int i = 0; i < packet.Connectors.Length / 3; i++){ - connectorsData[i] = (packet.Connectors[i * 3], packet.Connectors[i * 3 + 1], (ConnectorType)packet.Connectors[i * 3 + 2]); + (int id1, int id2, ConnectorType type, ClientPlayer? owner)[] connectorsData = new (int, int , ConnectorType, ClientPlayer?)[packet.Connectors.Length / 4]; + for (int i = 0; i < packet.Connectors.Length / 4; i++){ + connectorsData[i] = (packet.Connectors[i * 4], packet.Connectors[i * 4 + 1], (ConnectorType)packet.Connectors[i * 4 + 2], packet.Connectors[i * 4 + 3] == -1 ? null : GetPlayer(packet.Connectors[i * 4 + 3])); } ClientMapManager.InitMap(packet.UpsideDown); - TileConnectorProjection[] connectors = connectorsData.Select(c => new TileConnectorProjection(ClientMapManager.Get(c.id1), ClientMapManager.Get(c.id2), c.type)).ToArray(); + TileConnectorProjection[] connectors = connectorsData.Select(c => new TileConnectorProjection(ClientMapManager.Get(c.id1), ClientMapManager.Get(c.id2), c.type){Owner = c.owner}).ToArray(); ClientMapManager.InitConnectors(connectors); UIManager.SpawnMapElements(connectors.Where(c => c.Type == ConnectorType.DOOR_REMOTE).ToArray()); diff --git a/FNAF_Clone/CommandManager.cs b/FNAF_Clone/CommandManager.cs index 73cba39..cce3369 100644 --- a/FNAF_Clone/CommandManager.cs +++ b/FNAF_Clone/CommandManager.cs @@ -55,8 +55,9 @@ public class CommandManager { } private static void SendToggleRemoteDoor(Direction direction) { - if (!currentDoorBinds.TryGetValue(direction, out var val)) return; - TileConnectorProjection connector = val; + if (!currentDoorBinds.TryGetValue(direction, out var connector)) return; + if (connector.Owner != Client.Player) return; + connector.Blocked = !connector.Blocked; Client.SendCommands([PlayerCommand.SET_DOOR_REMOTE(connector.Id, connector.Blocked)]); UIManager.ChangeRemoteDoorState(connector.Id, connector.Blocked); @@ -65,6 +66,8 @@ public class CommandManager { } public static void SendChangeCamera(int id) { + if (id == Client.Player.state.officeTileId || id == Client.Opponent.state.officeTileId) return; + Client.Player.state.camera = id; UIManager.ChangeCamera(id); Client.SendCommands([PlayerCommand.SWITCH_CAM(id)]); diff --git a/FNAF_Clone/EventProcessor.cs b/FNAF_Clone/EventProcessor.cs index b5e3392..fc89e2c 100644 --- a/FNAF_Clone/EventProcessor.cs +++ b/FNAF_Clone/EventProcessor.cs @@ -1,7 +1,9 @@ using System; +using System.Linq; using FNAF_Clone.GUI; using FNAF_Clone.Map; using GlobalClassLib; +using MonoGameLibrary.Input; using PacketLib; namespace FNAF_Clone; @@ -102,10 +104,50 @@ public class EventProcessor { break; case 12: - Console.WriteLine($"E: Game started"); + Console.WriteLine("E: Game started"); UIManager.DisplayGameUI(); UIManager.StartTimer(); break; + + case 13: + Console.WriteLine($"E: power tick {e.Args[0]}: {e.Args[1]}"); + if (e.Args[0] == Client.Player.state.pid){ + Client.Player.state.power = e.Args[1]; + } + else{ + Client.Opponent.state.power = e.Args[1]; + } + + break; + + case 14: + Console.WriteLine($"E: Player {e.Args[0]} powered out"); + ClientMapManager.GetAllConnectors().Where(c => + (c.Type == ConnectorType.DOOR_REMOTE || c.Type == ConnectorType.DOOR_OFFICE) && + c.Owner == Client.GetPlayer(e.Args[0])).ToList().ForEach(c => + { + c.Blocked = false; + if(c.Type == ConnectorType.DOOR_REMOTE) + UIManager.ChangeRemoteDoorState(c.Id, false); + }); + + if (e.Args[0] == Client.Player.state.pid){ + UIManager.ChangeDoorState(Direction.EAST, false); + UIManager.ChangeDoorState(Direction.NORTH, false); + UIManager.ChangeDoorState(Direction.WEST, false); + CommandManager.AllowGameControls(false); + UIManager.ChangeMonitorState(false); + } + else{ + UIManager.ChangeDoorStateOpponent(Direction.EAST, false); + UIManager.ChangeDoorStateOpponent(Direction.NORTH, false); + UIManager.ChangeDoorStateOpponent(Direction.WEST, false); + UIManager.ChangeMonitorStateOpponent(false); + } + + break; + + } } } diff --git a/FNAF_Clone/GUI/PowerIndicator.cs b/FNAF_Clone/GUI/PowerIndicator.cs new file mode 100644 index 0000000..3555002 --- /dev/null +++ b/FNAF_Clone/GUI/PowerIndicator.cs @@ -0,0 +1,26 @@ +using GlobalClassLib; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace FNAF_Clone.GUI; + +public class PowerIndicator : TextUIElement { + private string label; + private ClientPlayer player; + private int lastPowerValue; + + public PowerIndicator(Point corner1, SpriteFont font, ClientPlayer player, string label, Alignment alignment = Alignment.LEFT) : base(corner1, font, alignment, autoBounds:true) { + this.player = player; + this.label = label; + lastPowerValue = player.state.power; + Text = GetText(); + } + + public override void Update() { + if (player.state.power == lastPowerValue) return; + lastPowerValue = player.state.power; + Text = GetText(); + } + + private string GetText() => $"{label}{(int)(((float)player.state.power / Power.MAX_POWER_VALUE) * 100)}"; +} \ No newline at end of file diff --git a/FNAF_Clone/GUI/TimerUIElement.cs b/FNAF_Clone/GUI/TimerUIElement.cs index 6310a48..4df57b5 100644 --- a/FNAF_Clone/GUI/TimerUIElement.cs +++ b/FNAF_Clone/GUI/TimerUIElement.cs @@ -9,8 +9,9 @@ public class TimerUIElement : TextUIElement{ private Stopwatch stopwatch = new(); - public TimerUIElement(Point corner1, SpriteFont font) : base(corner1, corner1, font) { + public TimerUIElement(Point corner1, SpriteFont font) : base(corner1, font) { Text = "00:00.000"; + Bounds = (corner1, corner1 + new Point((int)Measure().X, (int)Measure().Y)); } public override void Update() { diff --git a/FNAF_Clone/GUI/UIManager.cs b/FNAF_Clone/GUI/UIManager.cs index 97f1d81..b54afb4 100644 --- a/FNAF_Clone/GUI/UIManager.cs +++ b/FNAF_Clone/GUI/UIManager.cs @@ -79,28 +79,18 @@ public class UIManager { timerElement = new(new(0, 0), PixelMonoFont); overlayScreen.AddElement("timer", timerElement); + officeScreen.AddElement("power-p1-office", new PowerIndicator(new(timerElement.Bounds.Item1.X, timerElement.Bounds.Item2.Y + 5), PixelMonoFont, Client.Player, "POWER: ")); + + + TextUIElement powerLabel = (TextUIElement) + monitorScreen.AddElement("power-label", new TextUIElement(new(510, 150), PixelMonoFont){Text = "POWER:"}); + TextUIElement powerP1 = (TextUIElement) + monitorScreen.AddElement("power-p2", new PowerIndicator(new(powerLabel.Bounds.Item1.X + 10, powerLabel.Bounds.Item2.Y + 10), PixelMonoFont, Client.Opponent, ""){Color = new Color(220, 10, 10, 255)}); + monitorScreen.AddElement("power-p1", new PowerIndicator( new (powerP1.Bounds.Item1.X, powerP1.Bounds.Item2.Y + 5), PixelMonoFont, Client.Player, ""){Color = new Color(15, 190, 247, 255)}); winScreen.AddElement("win-text", new TextUIElement(new(320, 180), PixelMonoFont, TextUIElement.Alignment.CENTER){Text = "YOU WIN", Color = Color.Green}); loseScreen.AddElement("lose-text", new TextUIElement(new(320, 180), PixelMonoFont, TextUIElement.Alignment.CENTER){Text = "YOU LOSE", Color = Color.Red}); - // overlayScreen.AddElement("test", new TextBoxUIElement(PixelMonoFont, Point.Zero, new(200, 100))); - - // Main menu - // TextUIElement serverIpLabel = (TextUIElement) menuScreen.AddElement("server-ip-label", new TextUIElement(new (20, 20), PixelMonoFont){Text = "ENTER SERVER IP: ", Color = Color.Gray}); - // TextBoxUIElement serverIpTextBox = (TextBoxUIElement)menuScreen.AddElement("server-ip-textbox", - // new TextBoxUIElement(PixelMonoFont, - // new(serverIpLabel.Bounds.Item1.X + (int)serverIpLabel.Measure().X, serverIpLabel.Bounds.Item1.Y), - // new(640, serverIpLabel.Bounds.Item2.Y + (int)serverIpLabel.Measure().Y))); - // serverIpTextBox.OnFocused = () => { - // serverIpTextBox.Color = Color.LightGreen; - // serverIpLabel.Color = Color.DarkGreen; - // }; - // serverIpTextBox.OnUnfocused = () => { - // serverIpTextBox.Color = Color.White; - // serverIpLabel.Color = Color.Gray; - // }; - - MenuInputField usernameField = (MenuInputField)menuScreen.AddElement("username-field", new MenuInputField(PixelMonoFont, new(20, 20), "USERNAME: ")); MenuInputField field = (MenuInputField)menuScreen.AddElement("server-ip-field", new MenuInputField(PixelMonoFont, new(usernameField.Bounds.Item1.X, usernameField.Bounds.Item2.Y + 20), "SERVER IP: ", "127.0.0.1")); UIElement connectButton = menuScreen.AddElement("server-ip-submit", new TextUIElement(new Point(field.Bounds.Item1.X, field.Bounds.Item2.Y), PixelMonoFont) diff --git a/FNAF_Clone/GameMain.cs b/FNAF_Clone/GameMain.cs index 4805b4b..362a266 100644 --- a/FNAF_Clone/GameMain.cs +++ b/FNAF_Clone/GameMain.cs @@ -37,8 +37,6 @@ public class GameMain() : Core("fnafkooo", 1280, 720, false) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); - - // TODO: Add your update logic here InputManager.NextInputCycle(); Screen.UpdateAll(); diff --git a/FNAF_Clone/Map/ClientMapManager.cs b/FNAF_Clone/Map/ClientMapManager.cs index 87dcb4b..7f1df2d 100644 --- a/FNAF_Clone/Map/ClientMapManager.cs +++ b/FNAF_Clone/Map/ClientMapManager.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Runtime.InteropServices.JavaScript; using GlobalClassLib; @@ -18,7 +19,7 @@ public class ClientMapManager { for (int i = 0; i < 5; i++){ for (int j = 0; j < 2; j++){ - map[i, j] = new MapTileProjection(CoordsToId(i, j)); // TODO: implement ownership + map[i, j] = new MapTileProjection(CoordsToId(i, j)); } map[i, 2] = new MapTileProjection(CoordsToId(i, 2)); for (int j = 3; j < 5; j++){ @@ -26,8 +27,6 @@ public class ClientMapManager { } } - - } public static void InitConnectors(TileConnectorProjection[] connectors) { @@ -42,6 +41,21 @@ public class ClientMapManager { public static TileConnectorProjection[] GetConnectors(int tileId) => Get(IdToCoords(tileId)).GetAllConnectors(); + public static TileConnectorProjection[] GetAllConnectors() { + List connectors = new(); + + for (int i = 0; i < 5; i++){ + for (int j = 0; j < 5; j++){ + MapTileProjection tile = map[i, j]; + Array.ForEach(tile.GetAllConnectors(), c => { + if(tile.Id < c.OtherTile(tile).Id) + connectors.Add(c); + }); + } + } + + return connectors.ToArray(); + } public const int ID_X_OFFSET = 5; // map grid height diff --git a/FNAF_Clone/Map/MapTileProjection.cs b/FNAF_Clone/Map/MapTileProjection.cs index 9c425d9..1be47a5 100644 --- a/FNAF_Clone/Map/MapTileProjection.cs +++ b/FNAF_Clone/Map/MapTileProjection.cs @@ -3,6 +3,7 @@ using GlobalClassLib; namespace FNAF_Clone.Map; public class MapTileProjection : GlobalMapTile { + public ClientPlayer? Owner { get; set; } public MapTileProjection(int id) : base(id, ClientMapManager.IdToCoords(id)) { } } \ No newline at end of file diff --git a/FNAF_Clone/Map/TileConnectorProjection.cs b/FNAF_Clone/Map/TileConnectorProjection.cs index c6f25d9..e4154b5 100644 --- a/FNAF_Clone/Map/TileConnectorProjection.cs +++ b/FNAF_Clone/Map/TileConnectorProjection.cs @@ -3,11 +3,12 @@ using GlobalClassLib; namespace FNAF_Clone.Map; public class TileConnectorProjection : GlobalTileConnector { + public ClientPlayer? Owner { get; set; } public TileConnectorProjection(MapTileProjection tile1, MapTileProjection tile2, ConnectorType type) : base(tile1, tile2, type) { } public TileConnectorProjection(MapTileProjection tile2, ConnectorType type) : base(tile2, type) { } - public override TileConnectorProjection Clone() => new(Tiles.tile1, Tiles.tile2, Type); + public override TileConnectorProjection Clone() => new(Tiles.tile1, Tiles.tile2, Type){Owner = Owner}; } \ No newline at end of file diff --git a/FNAF_Server/CommandProcessor.cs b/FNAF_Server/CommandProcessor.cs index e6d32d9..4dd2eef 100644 --- a/FNAF_Server/CommandProcessor.cs +++ b/FNAF_Server/CommandProcessor.cs @@ -21,9 +21,17 @@ public class CommandProcessor { Server.SendUpdateToAll([GameEvent.TOGGLE_MONITOR(pid, monitorState)]); break; case 2: - bool doorState = playerCommand.Args[1] == 1; // TODO: block office doors + bool doorState = playerCommand.Args[1] == 1; currentPlayer.state.doorStates[playerCommand.Args[0]] = doorState; - MapManager.Get(currentPlayer.state.officeTileId).GetConnector(currentPlayer.state.neighbouringTiles[playerCommand.Args[0]]).Blocked = doorState; + TileConnector? officeDoor = MapManager.Get(currentPlayer.state.officeTileId).GetConnector(currentPlayer.state.neighbouringTiles[playerCommand.Args[0]]); + officeDoor.Blocked = doorState; + + if (doorState){ + GameLogic.PowerConsumers[officeDoor] = (GameLogic.OfficeDoorUsage, pid); + } + else{ + GameLogic.PowerConsumers.Remove(officeDoor); + } Console.WriteLine($"C: Player {pid} {(doorState ? "closed" : "opened")} door {playerCommand.Args[0]}"); Server.SendUpdateToAll([GameEvent.TOGGLE_DOOR_OFFICE(pid,playerCommand.Args[0] ,doorState)]); @@ -31,7 +39,15 @@ public class CommandProcessor { case 3: TileConnector? door = MapManager.Get(playerCommand.Args[0]).GetConnector(playerCommand.Args[1]); if(door == null) return; + door.Blocked = playerCommand.Args[2] == 1; + if (door.Blocked){ + GameLogic.PowerConsumers[door] = (GameLogic.RemoteDoorUsage, pid); + } + else{ + GameLogic.PowerConsumers.Remove(door); + } + Console.WriteLine($"C: Player {pid} {(door.Blocked ? "closed" : "opened")} door {(playerCommand.Args[0], playerCommand.Args[1])}"); Server.SendUpdateToAll([GameEvent.TOGGLE_DOOR_REMOTE(pid, (playerCommand.Args[0], playerCommand.Args[1]), door.Blocked)]); break; diff --git a/FNAF_Server/Enemies/MovementOpportunity.cs b/FNAF_Server/Enemies/MovementOpportunity.cs index 6e1a1f2..efd98f4 100644 --- a/FNAF_Server/Enemies/MovementOpportunity.cs +++ b/FNAF_Server/Enemies/MovementOpportunity.cs @@ -12,7 +12,7 @@ public class MovementOpportunity { public bool ConstantChance{ get; private set; } private Stopwatch stopwatch = new(); - private int stopwatchOffset = 0; + private long stopwatchOffset = 0; private Random random = new(); @@ -37,9 +37,10 @@ public class MovementOpportunity { } public bool Check() { - if (stopwatch.ElapsedMilliseconds + stopwatchOffset >= Interval){ - stopwatchOffset = (int)(stopwatch.ElapsedMilliseconds - Interval); - stopwatch.Restart(); + if (stopwatch.ElapsedMilliseconds - stopwatchOffset >= Interval){ + int overshoot = (int)(stopwatch.ElapsedMilliseconds - stopwatchOffset - Interval); + stopwatchOffset = stopwatch.ElapsedMilliseconds - overshoot; + // stopwatch.Restart(); return true; } return false; diff --git a/FNAF_Server/GameLogic.cs b/FNAF_Server/GameLogic.cs index 2ab1f39..4026467 100644 --- a/FNAF_Server/GameLogic.cs +++ b/FNAF_Server/GameLogic.cs @@ -16,27 +16,42 @@ public class GameLogic { public static MapTile P1Office; public static MapTile P2Office; public static MapTile[] Offices =>[P1Office, P2Office]; + + public static int OfficeDoorUsage{ get; set; } = 10; + public static int RemoteDoorUsage{ get; set; } = 3; + + // public const int POWER_MAX = 1000; + // public static int P1Power{ get; set; } = Power.MAX_POWER_VALUE; + // public static int P2Power{ get; set; } = Power.MAX_POWER_VALUE; + // public static int[] PowerValues =>[P1Power, P2Power]; + + public static Dictionary PowerConsumers{ get; set; } = new(); public static void Init() { // Create map MapManager.InitMap(); P1Office = MapManager.Get(10); P2Office = MapManager.Get(14); - + // + // foreach (var player in Server.Players.Values){ + // player.state.power = Power.MAX_POWER_VALUE; + // } + //Send map to client TileConnector[] connectors = MapManager.GetAllConnectors(); - int[] connectorsConverted = new int[connectors.Length * 3]; + int[] connectorsConverted = new int[connectors.Length * 4]; for (int i = 0; i < connectors.Length; i++){ - connectorsConverted[i * 3] = connectors[i].Tiles.tile1.Id; - connectorsConverted[i * 3 + 1] = connectors[i].Tiles.tile2.Id; - connectorsConverted[i * 3 + 2] = (int)connectors[i].Type; + connectorsConverted[i * 4] = connectors[i].Tiles.tile1.Id; + connectorsConverted[i * 4 + 1] = connectors[i].Tiles.tile2.Id; + connectorsConverted[i * 4 + 2] = (int)connectors[i].Type; + connectorsConverted[i * 4 + 3] = connectors[i].Owner == null ? -1 : connectors[i].Owner.state.pid; } Server.SendPacket(new MapInitPacket{Connectors = connectorsConverted, UpsideDown = false}, Server.P1.peer); Server.SendPacket(new MapInitPacket{Connectors = connectorsConverted, UpsideDown = true}, Server.P2.peer); EnemyManager.AddEnemy(new LurkEnemy(0)).Spawn(MapManager.Get(12)); EnemyManager.AddEnemy(new NekoEnemy(0)).Spawn(MapManager.Get(2)); - EnemyManager.AddEnemy(new SpotEnemy(10)).Spawn(MapManager.Get(12)); + EnemyManager.AddEnemy(new SpotEnemy(0)).Spawn(MapManager.Get(12)); Thread.Sleep(3000); secondCycleTimer.Start(); @@ -44,6 +59,24 @@ public class GameLogic { } public static void Update() { if(secondCycleTimer.Check()) NSecondUpdate = true; + + if (NSecondUpdate){ + (int p1, int p2) powerUsage = CalculatePowerUsage(); + Server.P1.state.power -= powerUsage.p1; + Server.P2.state.power -= powerUsage.p2; + + foreach (var player in Server.Players.Values){ + if (player.state.power < 0){ + player.state.poweredOut = true; + player.state.power = 0; + PowerOut(player); + } + // Server.SendUpdateToAll([GameEvent.POWER_OUT(player.state.pid)]); + } + + Server.SendUpdateToAll([GameEvent.POWER_TICK(Server.P1.state.pid, Server.P1.state.power), GameEvent.POWER_TICK(Server.P2.state.pid, Server.P2.state.power)]); + + } EnemyManager.Update(); @@ -55,4 +88,28 @@ public class GameLogic { Server.Stop(); Console.WriteLine("Player " + player.state.pid + " won!"); } + + private static (int p1Usage, int p2Usage) CalculatePowerUsage() { + int p1Usage = 0; + int p2Usage = 0; + + foreach (var consumer in PowerConsumers){ + if (consumer.Value.pid == Server.P1.state.pid){ + p1Usage += consumer.Value.usage; + } + else if (consumer.Value.pid == Server.P2.state.pid){ + p2Usage += consumer.Value.usage; + } + } + + return (p1Usage, p2Usage); + } + + private static void PowerOut(ServerPlayer player) { + foreach (var door in MapManager.GetDoors(player)){ + door.Blocked = false; + } + PowerConsumers.Where(c => c.Value.pid == player.state.pid).ToList().ForEach(c => PowerConsumers.Remove(c.Key)); + Server.SendUpdateToAll([GameEvent.POWER_OUT(player.state.pid)]); + } } \ No newline at end of file diff --git a/FNAF_Server/Map/MapManager.cs b/FNAF_Server/Map/MapManager.cs index 4ad343e..afcc85f 100644 --- a/FNAF_Server/Map/MapManager.cs +++ b/FNAF_Server/Map/MapManager.cs @@ -4,6 +4,9 @@ namespace FNAF_Server.Map; public static class MapManager { private static MapTile[,] map = new MapTile[5, 5]; + private static List doors = new(); + private static List doorsP1 = new(); + private static List doorsP2 = new(); public static MapTile Get((int x, int y) coords) => map[coords.x, coords.y]; public static MapTile Get(int tileId) => Get(IdToCoords(tileId)); @@ -27,14 +30,14 @@ public static class MapManager { [(3,2)] = [(4,2,1)] }; - public static void InitMap() { // TODO: make map size not hardcoded + public static void InitMap() { for (int i = 0; i < 5; i++){ for (int j = 0; j < 2; j++){ - map[i, j] = new MapTile(CoordsToId(i, j), null); // TODO: implement ownership + map[i, j] = new MapTile(CoordsToId(i, j)){Owner = Server.P1}; } - map[i, 2] = new MapTile(CoordsToId(i, 2), null); + map[i, 2] = new MapTile(CoordsToId(i, 2)); for (int j = 3; j < 5; j++){ - map[i, j] = new MapTile(CoordsToId(i, j), null); + map[i, j] = new MapTile(CoordsToId(i, j)){Owner = Server.P2}; } } @@ -44,12 +47,15 @@ public static class MapManager { } foreach (var con in halfConnectors){ - map[con.Key.x1, con.Key.y1].AddConnectors(con.Value.Select(c => new TileConnector(map[c.x2, c.y2], c.type, c.value)).ToArray()); + map[con.Key.x1, con.Key.y1].AddConnectors(con.Value.Select(c => new TileConnector(map[c.x2, c.y2], c.type, c.value){Owner = Server.P1}).ToArray()); } foreach (var con in halfConnectors){ - map[4 - con.Key.x1, 4 - con.Key.y1].AddConnectors(con.Value.Select(c => new TileConnector(map[4 - c.x2, 4 - c.y2], c.type, c.value)).ToArray()); + map[4 - con.Key.x1, 4 - con.Key.y1].AddConnectors(con.Value.Select(c => new TileConnector(map[4 - c.x2, 4 - c.y2], c.type, c.value){Owner = Server.P2}).ToArray()); } + doors = GetAllConnectors().Where(c => c.Type == ConnectorType.DOOR_OFFICE || c.Type == ConnectorType.DOOR_REMOTE).ToList(); + doorsP1 = doors.Where(c => c.Owner == Server.P1).ToList(); + doorsP2 = doors.Where(c => c.Owner == Server.P2).ToList(); } public static TileConnector[] GetAllConnectors() { @@ -72,4 +78,7 @@ public static class MapManager { public const int ID_X_OFFSET = 5; // map grid height public static int CoordsToId(int x, int y) => x * ID_X_OFFSET + y; public static (int, int) IdToCoords(int id) => (id / ID_X_OFFSET, id % ID_X_OFFSET); + + public static TileConnector[] GetDoors() => doors.ToArray(); + public static TileConnector[] GetDoors(ServerPlayer player) => player == Server.P1 ? doorsP1.ToArray() : doorsP2.ToArray(); } \ No newline at end of file diff --git a/FNAF_Server/Map/MapTile.cs b/FNAF_Server/Map/MapTile.cs index 81661b2..9f36a63 100644 --- a/FNAF_Server/Map/MapTile.cs +++ b/FNAF_Server/Map/MapTile.cs @@ -4,10 +4,9 @@ using GlobalClassLib; namespace FNAF_Server.Map; public class MapTile : GlobalMapTile { - public ServerPlayer Owner{ get; private set; } + public ServerPlayer? Owner{ get; set; } - public MapTile(int id, ServerPlayer owner) : base(id, MapManager.IdToCoords(id)) { - Owner = owner; + public MapTile(int id) : base(id, MapManager.IdToCoords(id)) { } // public int Id { get; private set; } diff --git a/FNAF_Server/Map/TileConnector.cs b/FNAF_Server/Map/TileConnector.cs index 8b45a75..ffe09dc 100644 --- a/FNAF_Server/Map/TileConnector.cs +++ b/FNAF_Server/Map/TileConnector.cs @@ -4,6 +4,7 @@ namespace FNAF_Server.Map; public class TileConnector : GlobalTileConnector { public int Value{ get; set; } + public ServerPlayer? Owner{ get; set; } public TileConnector(MapTile tile1, MapTile tile2, ConnectorType type, int value) : base(tile1, tile2, type) { Value = value; } @@ -40,5 +41,5 @@ public class TileConnector : GlobalTileConnector { // VENT // } - public override TileConnector Clone() => new(Tiles.tile1, Tiles.tile2, Type, Value); + public override TileConnector Clone() => new(Tiles.tile1, Tiles.tile2, Type, Value){Owner = Owner}; } \ No newline at end of file diff --git a/FNAF_Server/Server.cs b/FNAF_Server/Server.cs index f1dd325..dc8ef7b 100644 --- a/FNAF_Server/Server.cs +++ b/FNAF_Server/Server.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Diagnostics; using System.Threading; using FNAF_Server.Map; +using GlobalClassLib; using LiteNetLib; using LiteNetLib.Utils; using PacketLib; @@ -104,7 +105,9 @@ public class Server { state = new PlayerState { pid = peer.Id, camera = GameLogic.START_CAMERA, - doorStates = [false, false, false] + doorStates = [false, false, false], + power = Power.MAX_POWER_VALUE, + poweredOut = false }, username = packet.username }); diff --git a/GlobalClassLib/Power.cs b/GlobalClassLib/Power.cs new file mode 100644 index 0000000..5c81423 --- /dev/null +++ b/GlobalClassLib/Power.cs @@ -0,0 +1,5 @@ +namespace GlobalClassLib; + +public static class Power { + public const int MAX_POWER_VALUE = 1000; +} \ No newline at end of file diff --git a/PacketLib/GameEvent.cs b/PacketLib/GameEvent.cs index 4c7315b..94a9dc7 100644 --- a/PacketLib/GameEvent.cs +++ b/PacketLib/GameEvent.cs @@ -5,8 +5,8 @@ namespace PacketLib; #nullable disable public struct GameEvent : INetSerializable{ - public static GameEvent PLAYER_JOIN(int pid) => new(){ID = 0, Args = [pid] }; // TODO: username sync - public static GameEvent PLAYER_LEAVE(int pid) => new(){ID = 1, Args = [pid] }; // TODO: id constants + public static GameEvent PLAYER_JOIN(int pid) => new(){ID = 0, Args = [pid] }; + public static GameEvent PLAYER_LEAVE(int pid) => new(){ID = 1, Args = [pid] }; public static GameEvent SWITCH_CAM(int pid, int id) => new(){ID = 2, Args = [pid, id] }; public static GameEvent TOGGLE_MONITOR(int pid, bool state) => new(){ID = 3, Args = [pid, state ? 1 : 0]}; public static GameEvent TOGGLE_DOOR_OFFICE(int pid, int doorId, bool state) => new(){ID = 4, Args = [pid, doorId, state ? 1 : 0]}; @@ -21,6 +21,8 @@ public struct GameEvent : INetSerializable{ public static GameEvent PLAYER_WIN(int pid) => new(){ID = 11, Args = [pid]}; public static GameEvent GAME_START() => new(){ID = 12}; + public static GameEvent POWER_TICK(int pid, int power) => new(){ID = 13, Args = [pid, power]}; + public static GameEvent POWER_OUT(int pid) => new(){ID = 14, Args = [pid]}; public int ID{ get; set; } public bool Hideable => ID < 0; diff --git a/PacketLib/MapInitPacket.cs b/PacketLib/MapInitPacket.cs index f31830c..d29350d 100644 --- a/PacketLib/MapInitPacket.cs +++ b/PacketLib/MapInitPacket.cs @@ -1,6 +1,8 @@ namespace PacketLib; public class MapInitPacket { - public int[] Connectors { get; set; } // triplets (tile1 id, tile2 id, type) + public int[] Connectors { get; set; } // quadruplets (tile1 id, tile2 id, type, owner) + public int[] YourTiles { get; set; } + public int[] OpponentTiles { get; set; } public bool UpsideDown { get; set; } } \ No newline at end of file diff --git a/PacketLib/PlayerState.cs b/PacketLib/PlayerState.cs index 8e4abcc..2a03040 100644 --- a/PacketLib/PlayerState.cs +++ b/PacketLib/PlayerState.cs @@ -3,7 +3,7 @@ using LiteNetLib.Utils; namespace PacketLib; -public struct PlayerState : INetSerializable { // TODO: separate mutable and immutable data +public struct PlayerState : INetSerializable { // TODO: make a constructor public int pid; public int camera; public bool monitorUp; @@ -12,6 +12,9 @@ public struct PlayerState : INetSerializable { // TODO: separate mutable and imm public bool[] doorStates; public int[] neighbouringTiles; // the indexes should correspond in both arrays + public int power; + public bool poweredOut; + public void Serialize(NetDataWriter writer) { writer.Put(pid); writer.Put(camera); @@ -19,6 +22,8 @@ public struct PlayerState : INetSerializable { // TODO: separate mutable and imm writer.PutArray(doorStates); writer.Put(officeTileId); writer.PutArray(neighbouringTiles); + writer.Put(power); + writer.Put(poweredOut); } public void Deserialize(NetDataReader reader) { @@ -28,6 +33,8 @@ public struct PlayerState : INetSerializable { // TODO: separate mutable and imm doorStates = reader.GetBoolArray(); officeTileId = reader.GetInt(); neighbouringTiles = reader.GetIntArray(); + power = reader.GetInt(); + poweredOut = reader.GetBool(); } }