Power - spotřebovává se když jsou zavřené dveře. Hráči mohou zavírat pouze dveře na svojí polovině mapy. Oprava bugu v MovementOpportunity, který způsoboval zpožďování intervalu.

This commit is contained in:
Perry 2026-03-12 22:33:35 +01:00
parent 7656707177
commit 25a62af483
22 changed files with 240 additions and 59 deletions

View file

@ -7,11 +7,13 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEventChannel_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F384e456bc26f45f5a6a6a20ae50c6e0dd1a400_003Ffb_003Fca10f160_003FEventChannel_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEventChannel_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F384e456bc26f45f5a6a6a20ae50c6e0dd1a400_003Ffb_003Fca10f160_003FEventChannel_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGame_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa69b121f85054691b2a8d28643003c23136600_003Fc7_003F517f8541_003FGame_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGame_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa69b121f85054691b2a8d28643003c23136600_003Fc7_003F517f8541_003FGame_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AINetSerializable_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3d47105f47a240929625d0f531812b9e1c000_003F0f_003Fe2eeb2cd_003FINetSerializable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AINetSerializable_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3d47105f47a240929625d0f531812b9e1c000_003F0f_003Fe2eeb2cd_003FINetSerializable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AInputManager_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4e0fe18725844db38e9480edfd0e34983e00_003F41_003Fc6f0d8ab_003FInputManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AKeyValuePair_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F384e456bc26f45f5a6a6a20ae50c6e0dd1a400_003Fe8_003F7272ae72_003FKeyValuePair_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AKeyValuePair_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F384e456bc26f45f5a6a6a20ae50c6e0dd1a400_003Fe8_003F7272ae72_003FKeyValuePair_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AList_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003Fe4_003F9c3fcf71_003FList_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AList_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003Fe4_003F9c3fcf71_003FList_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetManager_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3d47105f47a240929625d0f531812b9e1c000_003Fd6_003Fec041615_003FNetManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetManager_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3d47105f47a240929625d0f531812b9e1c000_003Fd6_003Fec041615_003FNetManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetSerializer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3d47105f47a240929625d0f531812b9e1c000_003Fcc_003F8a34584a_003FNetSerializer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetSerializer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3d47105f47a240929625d0f531812b9e1c000_003Fcc_003F8a34584a_003FNetSerializer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThread_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003Fb3_003F92670209_003FThread_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThread_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003Fb3_003F92670209_003FThread_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelpers_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003F48_003F95b0ef9d_003FThrowHelpers_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003Ffb_003Fa0fd6fc3_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AThrowHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003Ffb_003Fa0fd6fc3_003FThrowHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATitleContainer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa69b121f85054691b2a8d28643003c23136600_003F62_003F374a72ad_003FTitleContainer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATitleContainer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa69b121f85054691b2a8d28643003c23136600_003F62_003F374a72ad_003FTitleContainer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AValueTuple_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003F09_003F312b9770_003FValueTuple_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AValueTuple_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5e56f40aa42e4fc4b94786ec57da7544d1a400_003F09_003F312b9770_003FValueTuple_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

View file

@ -96,13 +96,14 @@ public class Client {
Player.state = packet.state; Player.state = packet.state;
} }
#nullable enable
private static void OnMapInit(MapInitPacket packet) { private static void OnMapInit(MapInitPacket packet) {
(int id1, int id2, ConnectorType type)[] connectorsData = new (int id1, int id2, ConnectorType type)[packet.Connectors.Length / 3]; (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 / 3; i++){ for (int i = 0; i < packet.Connectors.Length / 4; i++){
connectorsData[i] = (packet.Connectors[i * 3], packet.Connectors[i * 3 + 1], (ConnectorType)packet.Connectors[i * 3 + 2]); 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); 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); ClientMapManager.InitConnectors(connectors);
UIManager.SpawnMapElements(connectors.Where(c => c.Type == ConnectorType.DOOR_REMOTE).ToArray()); UIManager.SpawnMapElements(connectors.Where(c => c.Type == ConnectorType.DOOR_REMOTE).ToArray());

View file

@ -55,8 +55,9 @@ public class CommandManager {
} }
private static void SendToggleRemoteDoor(Direction direction) { private static void SendToggleRemoteDoor(Direction direction) {
if (!currentDoorBinds.TryGetValue(direction, out var val)) return; if (!currentDoorBinds.TryGetValue(direction, out var connector)) return;
TileConnectorProjection connector = val; if (connector.Owner != Client.Player) return;
connector.Blocked = !connector.Blocked; connector.Blocked = !connector.Blocked;
Client.SendCommands([PlayerCommand.SET_DOOR_REMOTE(connector.Id, connector.Blocked)]); Client.SendCommands([PlayerCommand.SET_DOOR_REMOTE(connector.Id, connector.Blocked)]);
UIManager.ChangeRemoteDoorState(connector.Id, connector.Blocked); UIManager.ChangeRemoteDoorState(connector.Id, connector.Blocked);
@ -65,6 +66,8 @@ public class CommandManager {
} }
public static void SendChangeCamera(int id) { public static void SendChangeCamera(int id) {
if (id == Client.Player.state.officeTileId || id == Client.Opponent.state.officeTileId) return;
Client.Player.state.camera = id; Client.Player.state.camera = id;
UIManager.ChangeCamera(id); UIManager.ChangeCamera(id);
Client.SendCommands([PlayerCommand.SWITCH_CAM(id)]); Client.SendCommands([PlayerCommand.SWITCH_CAM(id)]);

View file

@ -1,7 +1,9 @@
using System; using System;
using System.Linq;
using FNAF_Clone.GUI; using FNAF_Clone.GUI;
using FNAF_Clone.Map; using FNAF_Clone.Map;
using GlobalClassLib; using GlobalClassLib;
using MonoGameLibrary.Input;
using PacketLib; using PacketLib;
namespace FNAF_Clone; namespace FNAF_Clone;
@ -102,10 +104,50 @@ public class EventProcessor {
break; break;
case 12: case 12:
Console.WriteLine($"E: Game started"); Console.WriteLine("E: Game started");
UIManager.DisplayGameUI(); UIManager.DisplayGameUI();
UIManager.StartTimer(); UIManager.StartTimer();
break; 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;
} }
} }
} }

View file

@ -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)}";
}

View file

@ -9,8 +9,9 @@ public class TimerUIElement : TextUIElement{
private Stopwatch stopwatch = new(); 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"; Text = "00:00.000";
Bounds = (corner1, corner1 + new Point((int)Measure().X, (int)Measure().Y));
} }
public override void Update() { public override void Update() {

View file

@ -79,28 +79,18 @@ public class UIManager {
timerElement = new(new(0, 0), PixelMonoFont); timerElement = new(new(0, 0), PixelMonoFont);
overlayScreen.AddElement("timer", timerElement); 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}); 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}); 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 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")); 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) UIElement connectButton = menuScreen.AddElement("server-ip-submit", new TextUIElement(new Point(field.Bounds.Item1.X, field.Bounds.Item2.Y), PixelMonoFont)

View file

@ -38,8 +38,6 @@ public class GameMain() : Core("fnafkooo", 1280, 720, false) {
Keyboard.GetState().IsKeyDown(Keys.Escape)) Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit(); Exit();
// TODO: Add your update logic here
InputManager.NextInputCycle(); InputManager.NextInputCycle();
Screen.UpdateAll(); Screen.UpdateAll();

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.JavaScript; using System.Runtime.InteropServices.JavaScript;
using GlobalClassLib; using GlobalClassLib;
@ -18,7 +19,7 @@ public class ClientMapManager {
for (int i = 0; i < 5; i++){ for (int i = 0; i < 5; i++){
for (int j = 0; j < 2; j++){ 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)); map[i, 2] = new MapTileProjection(CoordsToId(i, 2));
for (int j = 3; j < 5; j++){ for (int j = 3; j < 5; j++){
@ -26,8 +27,6 @@ public class ClientMapManager {
} }
} }
} }
public static void InitConnectors(TileConnectorProjection[] connectors) { 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[] GetConnectors(int tileId) => Get(IdToCoords(tileId)).GetAllConnectors();
public static TileConnectorProjection[] GetAllConnectors() {
List<TileConnectorProjection> 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 public const int ID_X_OFFSET = 5; // map grid height

View file

@ -3,6 +3,7 @@ using GlobalClassLib;
namespace FNAF_Clone.Map; namespace FNAF_Clone.Map;
public class MapTileProjection : GlobalMapTile<TileConnectorProjection, MapTileProjection> { public class MapTileProjection : GlobalMapTile<TileConnectorProjection, MapTileProjection> {
public ClientPlayer? Owner { get; set; }
public MapTileProjection(int id) : base(id, ClientMapManager.IdToCoords(id)) { public MapTileProjection(int id) : base(id, ClientMapManager.IdToCoords(id)) {
} }
} }

View file

@ -3,11 +3,12 @@ using GlobalClassLib;
namespace FNAF_Clone.Map; namespace FNAF_Clone.Map;
public class TileConnectorProjection : GlobalTileConnector<MapTileProjection, TileConnectorProjection> { public class TileConnectorProjection : GlobalTileConnector<MapTileProjection, TileConnectorProjection> {
public ClientPlayer? Owner { get; set; }
public TileConnectorProjection(MapTileProjection tile1, MapTileProjection tile2, ConnectorType type) : base(tile1, tile2, type) { public TileConnectorProjection(MapTileProjection tile1, MapTileProjection tile2, ConnectorType type) : base(tile1, tile2, type) {
} }
public TileConnectorProjection(MapTileProjection tile2, ConnectorType type) : base(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};
} }

View file

@ -21,9 +21,17 @@ public class CommandProcessor {
Server.SendUpdateToAll([GameEvent.TOGGLE_MONITOR(pid, monitorState)]); Server.SendUpdateToAll([GameEvent.TOGGLE_MONITOR(pid, monitorState)]);
break; break;
case 2: 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; 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]}"); Console.WriteLine($"C: Player {pid} {(doorState ? "closed" : "opened")} door {playerCommand.Args[0]}");
Server.SendUpdateToAll([GameEvent.TOGGLE_DOOR_OFFICE(pid,playerCommand.Args[0] ,doorState)]); Server.SendUpdateToAll([GameEvent.TOGGLE_DOOR_OFFICE(pid,playerCommand.Args[0] ,doorState)]);
@ -31,7 +39,15 @@ public class CommandProcessor {
case 3: case 3:
TileConnector? door = MapManager.Get(playerCommand.Args[0]).GetConnector(playerCommand.Args[1]); TileConnector? door = MapManager.Get(playerCommand.Args[0]).GetConnector(playerCommand.Args[1]);
if(door == null) return; if(door == null) return;
door.Blocked = playerCommand.Args[2] == 1; 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])}"); 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)]); Server.SendUpdateToAll([GameEvent.TOGGLE_DOOR_REMOTE(pid, (playerCommand.Args[0], playerCommand.Args[1]), door.Blocked)]);
break; break;

View file

@ -12,7 +12,7 @@ public class MovementOpportunity {
public bool ConstantChance{ get; private set; } public bool ConstantChance{ get; private set; }
private Stopwatch stopwatch = new(); private Stopwatch stopwatch = new();
private int stopwatchOffset = 0; private long stopwatchOffset = 0;
private Random random = new(); private Random random = new();
@ -37,9 +37,10 @@ public class MovementOpportunity {
} }
public bool Check() { public bool Check() {
if (stopwatch.ElapsedMilliseconds + stopwatchOffset >= Interval){ if (stopwatch.ElapsedMilliseconds - stopwatchOffset >= Interval){
stopwatchOffset = (int)(stopwatch.ElapsedMilliseconds - Interval); int overshoot = (int)(stopwatch.ElapsedMilliseconds - stopwatchOffset - Interval);
stopwatch.Restart(); stopwatchOffset = stopwatch.ElapsedMilliseconds - overshoot;
// stopwatch.Restart();
return true; return true;
} }
return false; return false;

View file

@ -17,26 +17,41 @@ public class GameLogic {
public static MapTile P2Office; public static MapTile P2Office;
public static MapTile[] Offices =>[P1Office, 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<object, (int usage, int pid)> PowerConsumers{ get; set; } = new();
public static void Init() { public static void Init() {
// Create map // Create map
MapManager.InitMap(); MapManager.InitMap();
P1Office = MapManager.Get(10); P1Office = MapManager.Get(10);
P2Office = MapManager.Get(14); P2Office = MapManager.Get(14);
//
// foreach (var player in Server.Players.Values){
// player.state.power = Power.MAX_POWER_VALUE;
// }
//Send map to client //Send map to client
TileConnector[] connectors = MapManager.GetAllConnectors(); 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++){ for (int i = 0; i < connectors.Length; i++){
connectorsConverted[i * 3] = connectors[i].Tiles.tile1.Id; connectorsConverted[i * 4] = connectors[i].Tiles.tile1.Id;
connectorsConverted[i * 3 + 1] = connectors[i].Tiles.tile2.Id; connectorsConverted[i * 4 + 1] = connectors[i].Tiles.tile2.Id;
connectorsConverted[i * 3 + 2] = (int)connectors[i].Type; 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 = false}, Server.P1.peer);
Server.SendPacket(new MapInitPacket{Connectors = connectorsConverted, UpsideDown = true}, Server.P2.peer); Server.SendPacket(new MapInitPacket{Connectors = connectorsConverted, UpsideDown = true}, Server.P2.peer);
EnemyManager.AddEnemy(new LurkEnemy(0)).Spawn(MapManager.Get(12)); EnemyManager.AddEnemy(new LurkEnemy(0)).Spawn(MapManager.Get(12));
EnemyManager.AddEnemy(new NekoEnemy(0)).Spawn(MapManager.Get(2)); 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); Thread.Sleep(3000);
secondCycleTimer.Start(); secondCycleTimer.Start();
@ -45,6 +60,24 @@ public class GameLogic {
public static void Update() { public static void Update() {
if(secondCycleTimer.Check()) NSecondUpdate = true; 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(); EnemyManager.Update();
NSecondUpdate = false; NSecondUpdate = false;
@ -55,4 +88,28 @@ public class GameLogic {
Server.Stop(); Server.Stop();
Console.WriteLine("Player " + player.state.pid + " won!"); 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)]);
}
} }

View file

@ -4,6 +4,9 @@ namespace FNAF_Server.Map;
public static class MapManager { public static class MapManager {
private static MapTile[,] map = new MapTile[5, 5]; private static MapTile[,] map = new MapTile[5, 5];
private static List<TileConnector> doors = new();
private static List<TileConnector> doorsP1 = new();
private static List<TileConnector> doorsP2 = new();
public static MapTile Get((int x, int y) coords) => map[coords.x, coords.y]; public static MapTile Get((int x, int y) coords) => map[coords.x, coords.y];
public static MapTile Get(int tileId) => Get(IdToCoords(tileId)); public static MapTile Get(int tileId) => Get(IdToCoords(tileId));
@ -27,14 +30,14 @@ public static class MapManager {
[(3,2)] = [(4,2,1)] [(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 i = 0; i < 5; i++){
for (int j = 0; j < 2; j++){ 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++){ 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){ 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){ 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() { public static TileConnector[] GetAllConnectors() {
@ -72,4 +78,7 @@ public static class MapManager {
public const int ID_X_OFFSET = 5; // map grid height 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 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 (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();
} }

View file

@ -4,10 +4,9 @@ using GlobalClassLib;
namespace FNAF_Server.Map; namespace FNAF_Server.Map;
public class MapTile : GlobalMapTile<TileConnector, MapTile> { public class MapTile : GlobalMapTile<TileConnector, MapTile> {
public ServerPlayer Owner{ get; private set; } public ServerPlayer? Owner{ get; set; }
public MapTile(int id, ServerPlayer owner) : base(id, MapManager.IdToCoords(id)) { public MapTile(int id) : base(id, MapManager.IdToCoords(id)) {
Owner = owner;
} }
// public int Id { get; private set; } // public int Id { get; private set; }

View file

@ -4,6 +4,7 @@ namespace FNAF_Server.Map;
public class TileConnector : GlobalTileConnector<MapTile,TileConnector> { public class TileConnector : GlobalTileConnector<MapTile,TileConnector> {
public int Value{ get; set; } public int Value{ get; set; }
public ServerPlayer? Owner{ get; set; }
public TileConnector(MapTile tile1, MapTile tile2, ConnectorType type, int value) : base(tile1, tile2, type) { public TileConnector(MapTile tile1, MapTile tile2, ConnectorType type, int value) : base(tile1, tile2, type) {
Value = value; Value = value;
} }
@ -40,5 +41,5 @@ public class TileConnector : GlobalTileConnector<MapTile,TileConnector> {
// VENT // 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};
} }

View file

@ -3,6 +3,7 @@ using System.Collections;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using FNAF_Server.Map; using FNAF_Server.Map;
using GlobalClassLib;
using LiteNetLib; using LiteNetLib;
using LiteNetLib.Utils; using LiteNetLib.Utils;
using PacketLib; using PacketLib;
@ -104,7 +105,9 @@ public class Server {
state = new PlayerState { state = new PlayerState {
pid = peer.Id, pid = peer.Id,
camera = GameLogic.START_CAMERA, camera = GameLogic.START_CAMERA,
doorStates = [false, false, false] doorStates = [false, false, false],
power = Power.MAX_POWER_VALUE,
poweredOut = false
}, },
username = packet.username username = packet.username
}); });

5
GlobalClassLib/Power.cs Normal file
View file

@ -0,0 +1,5 @@
namespace GlobalClassLib;
public static class Power {
public const int MAX_POWER_VALUE = 1000;
}

View file

@ -5,8 +5,8 @@ namespace PacketLib;
#nullable disable #nullable disable
public struct GameEvent : INetSerializable{ public struct GameEvent : INetSerializable{
public static GameEvent PLAYER_JOIN(int pid) => new(){ID = 0, Args = [pid] }; // TODO: username sync public static GameEvent PLAYER_JOIN(int pid) => new(){ID = 0, Args = [pid] };
public static GameEvent PLAYER_LEAVE(int pid) => new(){ID = 1, Args = [pid] }; // TODO: id constants 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 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_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]}; 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 PLAYER_WIN(int pid) => new(){ID = 11, Args = [pid]};
public static GameEvent GAME_START() => new(){ID = 12}; 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 int ID{ get; set; }
public bool Hideable => ID < 0; public bool Hideable => ID < 0;

View file

@ -1,6 +1,8 @@
namespace PacketLib; namespace PacketLib;
public class MapInitPacket { 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; } public bool UpsideDown { get; set; }
} }

View file

@ -3,7 +3,7 @@ using LiteNetLib.Utils;
namespace PacketLib; 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 pid;
public int camera; public int camera;
public bool monitorUp; public bool monitorUp;
@ -12,6 +12,9 @@ public struct PlayerState : INetSerializable { // TODO: separate mutable and imm
public bool[] doorStates; public bool[] doorStates;
public int[] neighbouringTiles; // the indexes should correspond in both arrays public int[] neighbouringTiles; // the indexes should correspond in both arrays
public int power;
public bool poweredOut;
public void Serialize(NetDataWriter writer) { public void Serialize(NetDataWriter writer) {
writer.Put(pid); writer.Put(pid);
writer.Put(camera); writer.Put(camera);
@ -19,6 +22,8 @@ public struct PlayerState : INetSerializable { // TODO: separate mutable and imm
writer.PutArray(doorStates); writer.PutArray(doorStates);
writer.Put(officeTileId); writer.Put(officeTileId);
writer.PutArray(neighbouringTiles); writer.PutArray(neighbouringTiles);
writer.Put(power);
writer.Put(poweredOut);
} }
public void Deserialize(NetDataReader reader) { public void Deserialize(NetDataReader reader) {
@ -28,6 +33,8 @@ public struct PlayerState : INetSerializable { // TODO: separate mutable and imm
doorStates = reader.GetBoolArray(); doorStates = reader.GetBoolArray();
officeTileId = reader.GetInt(); officeTileId = reader.GetInt();
neighbouringTiles = reader.GetIntArray(); neighbouringTiles = reader.GetIntArray();
power = reader.GetInt();
poweredOut = reader.GetBool();
} }
} }