fuU1>U84XF0()fp`Y&72X~xWL5{I|a
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
Lo^wyTNWS|o;SVEq
diff --git a/logic/Client/MainPage.xaml b/logic/Client/MainPage.xaml
new file mode 100644
index 00000000..c2416bfe
--- /dev/null
+++ b/logic/Client/MainPage.xaml
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/logic/Client/MainPage.xaml.cs b/logic/Client/MainPage.xaml.cs
new file mode 100644
index 00000000..8164420c
--- /dev/null
+++ b/logic/Client/MainPage.xaml.cs
@@ -0,0 +1,700 @@
+using System;
+using System.Windows;
+using System.Threading.Tasks;
+using Microsoft.Maui.Dispatching;
+using Microsoft.Maui.Controls;
+using System.Drawing;
+using Grpc.Core;
+using Google.Protobuf;
+using System.Runtime.CompilerServices;
+using Protobuf;
+using Microsoft.Maui.Controls.Shapes;
+
+namespace Client
+{
+ public partial class MainPage : ContentPage
+ {
+
+ public MainPage()
+ {
+ Console.WriteLine("Hello World");
+ timer = Dispatcher.CreateTimer();
+ timer.Interval = TimeSpan.FromMicroseconds(50);
+ timer.Tick += new EventHandler(Refresh);
+ timer.Start();
+ Application.Current.UserAppTheme = AppTheme.Light; //Light Theme Mode
+ InitializeComponent();
+ SetStatusBars();
+ InitiateObjects();
+ Map map = new Map(MainGrid, 0, 2, 2);
+ }
+
+ /* Set the StatusBars */
+ private void SetStatusBars()
+ {
+ redPlayer = new PlayerStatusBar(MainGrid, 0, 1, 0);
+ bluePlayer = new PlayerStatusBar(MainGrid, 1, 1, 1);
+ gameStatusBar = new GameStatusBar(MainGrid, 0, 4);
+ }
+
+ /* initiate the Lists of Objects and CountList */
+ private void InitiateObjects()
+ {
+ listOfAll = new List();
+ listOfShip = new List();
+ listOfBuilding = new List();
+ listOfBullet = new List();
+ listOfResource = new List();
+ listOfHome = new List();
+ countMap = new Dictionary();
+ }
+
+ /* Get the Map to default map */
+ private void GetMap(MessageOfMap obj)
+ {
+ int[,] map = new int[50, 50];
+ try
+ {
+ for (int i = 0; i < 50; i++)
+ {
+ for (int j = 0; j < 50; j++)
+ {
+ map[i, j] = Convert.ToInt32(obj.Row[i].Col[j]) + 4;//与proto一致
+ }
+ }
+ }
+ catch
+ {
+ mapFlag = false;
+ }
+ finally
+ {
+ defaultMap = map;
+ mapFlag = true;
+ }
+ }
+
+ private void DrawMap()
+ {
+ resourceArray = new Label[countMap[(int)MapPatchType.Resource]];
+ resourcePositionIndex = new (int x, int y)[countMap[(int)MapPatchType.Resource]];
+ buildingArray = new Label[countMap[(int)MapPatchType.Building]];
+ buildingPositionIndex = new (int x, int y)[countMap[(int)MapPatchType.Building]];
+ // factoryArray = new Label[countMap[(int)MapPatchType.Factory]];
+ // factoryPositionIndex = new int[countMap[(int)MapPatchType.Factory]];
+ // communityArray = new Label[countMap[(int)MapPatchType.Community]];
+ // communityPositionIndex = new int[countMap[(int)MapPatchType.Community]];
+ // fortressArray = new Label[countMap[(int)MapPatchType.Fortress]];
+ // fortressPositionIndex = new int[countMap[(int)MapPatchType.Fortress]];
+ // wormHoleArray = new Label[countMap[(int)MapPatchType.WormHole]];
+ // wormHolePositionIndex = new int[countMap[(int)MapPatchType.WormHole]];
+ int counterOfResource = 0;
+ int counterOfBuilding = 0;
+ // int counterOfFactory = 0;
+ // int counterOfCommunity = 0;
+ // int counterOfFortress = 0;
+ // int counterOfWormHole = 0;
+ for (int i = 0; i < defaultMap.GetLength(0); i++)
+ {
+ for (int j = 0; j < defaultMap.GetLength(1); j++)
+ {
+ mapPatches[i, j] = new()
+ {
+ WidthRequest = unitWidth,
+ HeightRequest = unitHeight,
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ Margin = new Thickness(unitWidth * j, unitHeight * i, 0, 0)
+ };
+ MapPatchType mapPatchType = new MapPatchType();
+ mapPatchType = (MapPatchType)defaultMap[i, j];
+ switch (mapPatchType)
+ {
+ case MapPatchType.RedHome:
+ mapPatches[i, j].Color = Colors.Red; break; //Red Home
+ case MapPatchType.BlueHome:
+ mapPatches[i, j].Color = Colors.Blue; break; //Blue Home
+ case MapPatchType.Ruin:
+ mapPatches[i, j].Color = Colors.Black; break; // Ruin
+ case MapPatchType.Shadow:
+ mapPatches[i, j].Color = Colors.Gray; break; // Shadow
+ case MapPatchType.Asteroid:
+ mapPatches[i, j].Color = Colors.Brown; break; // Asteroid
+ case MapPatchType.Resource:
+ mapPatches[i, j].Color = Colors.Yellow; //Resource
+ resourcePositionIndex[counterOfResource] = (i, j);
+ resourceArray[counterOfResource] = new Label()
+ {
+ FontSize = unitFontSize,
+ WidthRequest = unitWidth,
+ HeightRequest = unitHeight,
+ Text = Convert.ToString(-1),
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center,
+ BackgroundColor = Colors.Transparent
+ };
+ counterOfResource++;
+ break;
+
+ case MapPatchType.Building:
+ mapPatches[i, j].Color = Colors.Orange; //Building
+ buildingPositionIndex[counterOfBuilding] = (i, j);
+ buildingArray[counterOfBuilding] = new Label()
+ {
+ FontSize = unitFontSize,
+ WidthRequest = unitWidth,
+ HeightRequest = unitHeight,
+ Text = Convert.ToString(-1),
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center,
+ BackgroundColor = Colors.Transparent
+ };
+ counterOfBuilding++;
+ break;
+
+ // case MapPatchType.Factory:
+ // mapPatches[i, j].Color = Colors.Orange; //Factory
+ // factoryPositionIndex[counterOfFactory] = 50 * i + j;
+ // resourceArray[counterOfResource] = new Label()
+ // {
+ // FontSize = unitFontSize,
+ // WidthRequest = unitWidth,
+ // HeightRequest = unitHeight,
+ // Text = Convert.ToString(-1),
+ // HorizontalOptions = LayoutOptions.Start,
+ // VerticalOptions = LayoutOptions.Start,
+ // HorizontalTextAlignment = TextAlignment.Center,
+ // VerticalTextAlignment = TextAlignment.Center,
+ // BackgroundColor = Colors.Transparent
+ // };
+ // counterOfFactory++;
+ // break;
+ // case MapPatchType.Community:
+ // mapPatches[i, j].Color = Colors.Green; //Community
+ // communityPositionIndex[counterOfCommunity] = 50 * i + j;
+ // communityArray[counterOfCommunity] = new Label()
+ // {
+ // FontSize = unitFontSize,
+ // WidthRequest = unitWidth,
+ // HeightRequest = unitHeight,
+ // Text = Convert.ToString(-1),
+ // HorizontalOptions = LayoutOptions.Start,
+ // VerticalOptions = LayoutOptions.Start,
+ // HorizontalTextAlignment = TextAlignment.Center,
+ // VerticalTextAlignment = TextAlignment.Center,
+ // BackgroundColor = Colors.Transparent
+ // };
+ // counterOfCommunity++;
+ // break;
+ // case MapPatchType.Fortress:
+ // mapPatches[i, j].Color = Colors.Azure; //Fortress
+ // fortressPositionIndex[counterOfFortress] = 50 * i + j;
+ // fortressArray[counterOfFortress] = new Label()
+ // {
+ // FontSize = unitFontSize,
+ // WidthRequest = unitWidth,
+ // HeightRequest = unitHeight,
+ // Text = Convert.ToString(-1),
+ // HorizontalOptions = LayoutOptions.Start,
+ // VerticalOptions = LayoutOptions.Start,
+ // HorizontalTextAlignment = TextAlignment.Center,
+ // VerticalTextAlignment = TextAlignment.Center,
+ // BackgroundColor = Colors.Transparent
+ // };
+ // counterOfFortress++;
+ // break;
+ // case MapPatchType.WormHole:
+ // mapPatches[i, j].Color = Colors.Purple; //Purple
+ // wormHolePositionIndex[counterOfWormHole] = 50 * i + j;
+ // wormHoleArray[counterOfWormHole] = new Label()
+ // {
+ // FontSize = unitFontSize,
+ // WidthRequest = unitWidth,
+ // HeightRequest = unitHeight,
+ // Text = Convert.ToString(-1),
+ // HorizontalOptions = LayoutOptions.Start,
+ // VerticalOptions = LayoutOptions.Start,
+ // HorizontalTextAlignment = TextAlignment.Center,
+ // VerticalTextAlignment = TextAlignment.Center,
+ // BackgroundColor = Colors.Transparent
+ // };
+ // counterOfWormHole++;
+ // break;
+ default:
+ break;
+ }
+ MapGrid.Children.Add(mapPatches[i, j]);
+ }
+ }
+ hasDrawed = true;
+ }
+
+ private async void OnReceive()
+ {
+ try
+ {
+ while (responseStream != null && await responseStream.ResponseStream.MoveNext())
+ {
+ lock (drawPicLock)
+ {
+ listOfShip.Clear();
+ listOfBuilding.Clear();
+ listOfBullet.Clear();
+ listOfResource.Clear();
+ listOfHome.Clear();
+ listOfAll.Clear();
+ MessageToClient content = responseStream.ResponseStream.Current;
+ MessageOfMap mapMassage = new MessageOfMap();
+ bool mapMessageExist = false;
+ switch (content.GameState)
+ {
+ case GameState.GameStart:
+ foreach (var obj in content.ObjMessage)
+ {
+ switch (obj.MessageOfObjCase)
+ {
+ case MessageOfObj.MessageOfObjOneofCase.ShipMessage:
+ listOfShip.Add(obj.ShipMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.BuildingMessage:
+ listOfBuilding.Add(obj.BuildingMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.BulletMessage:
+ listOfBullet.Add(obj.BulletMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.ResourceMessage:
+ listOfResource.Add(obj.ResourceMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.HomeMessage:
+ listOfHome.Add(obj.HomeMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.MapMessage:
+ mapMassage = obj.MapMessage;
+ break;
+ }
+ }
+ listOfAll.Add(content.AllMessage);
+ countMap.Clear();
+ countMap.Add((int)MapPatchType.Resource, listOfResource.Count);
+ countMap.Add((int)MapPatchType.Building, listOfBuilding.Count);
+ GetMap(mapMassage);
+ break;
+ case GameState.GameRunning:
+ foreach (var obj in content.ObjMessage)
+ {
+ switch (obj.MessageOfObjCase)
+ {
+ case MessageOfObj.MessageOfObjOneofCase.ShipMessage:
+ listOfShip.Add(obj.ShipMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.BuildingMessage:
+ listOfBuilding.Add(obj.BuildingMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.BulletMessage:
+ listOfBullet.Add(obj.BulletMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.ResourceMessage:
+ listOfResource.Add(obj.ResourceMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.HomeMessage:
+ listOfHome.Add(obj.HomeMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.MapMessage:
+ mapMassage = obj.MapMessage;
+ mapMessageExist = true;
+ break;
+ }
+ }
+ listOfAll.Add(content.AllMessage);
+ if (mapMessageExist)
+ {
+ countMap.Clear();
+ countMap.Add((int)MapPatchType.Resource, listOfResource.Count);
+ countMap.Add((int)MapPatchType.Building, listOfBuilding.Count);
+ GetMap(mapMassage);
+ mapMessageExist = false;
+ }
+ break;
+
+ case GameState.GameEnd:
+ DisplayAlert("Info", "Game End", "OK");
+ foreach (var obj in content.ObjMessage)
+ {
+ switch (obj.MessageOfObjCase)
+ {
+ case MessageOfObj.MessageOfObjOneofCase.ShipMessage:
+ listOfShip.Add(obj.ShipMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.BuildingMessage:
+ listOfBuilding.Add(obj.BuildingMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.BulletMessage:
+ listOfBullet.Add(obj.BulletMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.ResourceMessage:
+ listOfResource.Add(obj.ResourceMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.HomeMessage:
+ listOfHome.Add(obj.HomeMessage);
+ break;
+
+ case MessageOfObj.MessageOfObjOneofCase.MapMessage:
+ mapMassage = obj.MapMessage;
+ break;
+ }
+ }
+ listOfAll.Add(content.AllMessage);
+ break;
+ }
+ }
+ if (responseStream == null)
+ {
+ throw new Exception("Unconnected");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ /*
+ #TODO
+ Show the error message
+ */
+ }
+ }
+
+ private int FindIndexOfResource(MessageOfResource obj)
+ {
+ for (int i = 0; i < listOfResource.Count; i++)
+ {
+ if (resourcePositionIndex[i].x == obj.X && resourcePositionIndex[i].y == obj.Y)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int FindIndexOfBuilding(MessageOfBuilding obj)
+ {
+ for (int i = 0; i < listOfBuilding.Count; i++)
+ {
+ if (buildingPositionIndex[i].x == obj.X && buildingPositionIndex[i].y == obj.Y)
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private void Refresh(object sender, EventArgs e)
+ {
+ try
+ {
+ lock (drawPicLock)
+ {
+ if (!isClientStocked)
+ {
+ MapGrid.Children.Clear();
+ foreach (var data in listOfAll)
+ {
+ gameStatusBar.SetGameTimeValue(data);
+ }
+ if (!hasDrawed && mapFlag)
+ {
+ DrawMap();
+ }
+ foreach (var data in listOfHome)
+ {
+ if (data.Team == PlayerTeam.Down)
+ {
+ redPlayer.SetPlayerValue(data);
+ }
+ else
+ {
+ bluePlayer.SetPlayerValue(data);
+ }
+ DrawHome(data);
+ }
+ foreach (var data in listOfBuilding)
+ {
+ if (data.BuildingType == BuildingType.Wormhole)
+ {
+ gameStatusBar.SetWormHoleValue(data);
+ }
+ DrawBuilding(data);
+ }
+ foreach (var data in listOfBullet)
+ {
+ DrawBullet(data);
+ }
+ foreach (var data in listOfResource)
+ {
+ DrawResource(data);
+ }
+ foreach (var data in listOfShip)
+ {
+ if (data.Team == PlayerTeam.Down)
+ {
+ redPlayer.SetShipValue(data);
+ }
+ else
+ {
+ bluePlayer.SetShipValue(data);
+ }
+ // TODO: Dynamic change the ships' label
+ DrawShip(data);
+ }
+ }
+ }
+ }
+ finally
+ {
+
+ }
+ counter++;
+ }
+
+ private void DrawHome(MessageOfHome data)
+ {
+ Ellipse iconOfHome = new()
+ {
+ WidthRequest = 2 * characterRadiusTimes * unitWidth,
+ HeightRequest = 2 * characterRadiusTimes * unitHeight,
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ Margin = new Thickness(unitHeight * data.Y / 1000.0 - unitWidth * characterRadiusTimes, unitWidth * data.X / 1000.0 - unitWidth * characterRadiusTimes, 0, 0),
+ Fill = data.Team == PlayerTeam.Down ? Colors.Red : Colors.Blue
+ };
+ MapGrid.Children.Add(iconOfHome);
+ }
+
+ private void DrawBuilding(MessageOfBuilding data)
+ {
+ int hp = data.Hp;
+ //TODO: calculate the percentage of Hp
+ int idx = FindIndexOfBuilding(data);
+ buildingArray[idx].FontSize = unitFontSize;
+ buildingArray[idx].WidthRequest = unitWidth;
+ buildingArray[idx].HeightRequest = unitHeight;
+ buildingArray[idx].Text = Convert.ToString(hp);
+ buildingArray[idx].Margin = new Thickness(unitHeight * data.Y / 1000.0 - unitWidth * characterRadiusTimes, unitWidth * data.X / 1000.0 - unitWidth * characterRadiusTimes, 0, 0);
+ switch (data.BuildingType)
+ {
+ case BuildingType.Factory:
+ buildingArray[idx].BackgroundColor = Colors.Chocolate;
+ break;
+ case BuildingType.Community:
+ buildingArray[idx].BackgroundColor = Colors.Green;
+ break;
+ case BuildingType.Fortress:
+ buildingArray[idx].BackgroundColor = Colors.Azure;
+ break;
+ case BuildingType.Wormhole:
+ buildingArray[idx].BackgroundColor = Colors.Purple;
+ break;
+ }
+ MapGrid.Children.Add(buildingArray[idx]);
+ }
+
+ private void DrawBullet(MessageOfBullet data)
+ {
+ Ellipse iconOfBullet = new()
+ {
+ WidthRequest = 2 * bulletRadiusTimes * unitWidth,
+ HeightRequest = 2 * bulletRadiusTimes * unitHeight,
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ Margin = new Thickness(unitHeight * data.Y / 1000.0 - unitWidth * bulletRadiusTimes, unitWidth * data.X / 1000.0 - unitWidth * bulletRadiusTimes, 0, 0),
+ Fill = data.Team == PlayerTeam.Down ? Colors.Red : Colors.Blue
+ };
+ switch (data.Type)
+ {
+ case BulletType.Plasma:
+ iconOfBullet.Fill = Colors.Yellow;
+ break;
+ case BulletType.Laser:
+ iconOfBullet.Fill = Colors.Orange;
+ break;
+ case BulletType.Missile:
+ iconOfBullet.Fill = Colors.Purple;
+ break;
+ case BulletType.ElectricArc:
+ iconOfBullet.Fill = Colors.Green;
+ break;
+ }
+ MapGrid.Children.Add(iconOfBullet);
+ }
+
+ private void DrawResource(MessageOfResource data)
+ {
+ int idx = FindIndexOfResource(data);
+ resourceArray[idx].FontSize = unitFontSize;
+ resourceArray[idx].WidthRequest = unitWidth;
+ resourceArray[idx].HeightRequest = unitHeight;
+ resourceArray[idx].Text = Convert.ToString(data.Progress);
+ resourceArray[idx].Margin = new Thickness(unitHeight * data.Y / 1000.0 - unitWidth * characterRadiusTimes, unitWidth * data.X / 1000.0 - unitWidth * characterRadiusTimes, 0, 0);
+ MapGrid.Children.Add(resourceArray[idx]);
+ }
+
+ private void DrawShip(MessageOfShip data)
+ {
+ Ellipse iconOfShip = new()
+ {
+ WidthRequest = 2 * characterRadiusTimes * unitWidth,
+ HeightRequest = 2 * characterRadiusTimes * unitHeight,
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ Margin = new Thickness(unitHeight * data.Y / 1000.0 - unitWidth * characterRadiusTimes, unitWidth * data.X / 1000.0 - unitWidth * characterRadiusTimes, 0, 0),
+ Fill = data.Team == PlayerTeam.Down ? Colors.Red : Colors.Blue
+ };
+ Label nameOfShip = new()
+ {
+ FontSize = unitFontSize,
+ WidthRequest = unitWidth,
+ HeightRequest = unitHeight,
+ Text = data.ShipType.ToString()[0] + data.ShipId.ToString(),
+ HorizontalOptions = LayoutOptions.Start,
+ VerticalOptions = LayoutOptions.Start,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center,
+ BackgroundColor = Colors.Transparent,
+ Margin = new Thickness(unitHeight * data.Y / 1000.0 - unitWidth * characterRadiusTimes, unitWidth * data.X / 1000.0 - unitWidth * characterRadiusTimes, 0, 0)
+ };
+ MapGrid.Children.Add(iconOfShip);
+ MapGrid.Children.Add(nameOfShip);
+ }
+
+ private readonly IDispatcherTimer timer;
+ private long counter;
+
+ AsyncServerStreamingCall? responseStream;
+ private bool isClientStocked;
+
+ private PlayerStatusBar redPlayer;
+ private PlayerStatusBar bluePlayer;
+ private GameStatusBar gameStatusBar;
+
+ private bool isPlaybackMode;
+ private long playerID;
+ private double unit;
+ private double unitFontSize = 10;
+ private double unitHeight = 10.6;
+ private double unitWidth = 10.6;
+ private readonly BoxView[,] mapPatches = new BoxView[50, 50];
+ private readonly double characterRadiusTimes = 400;
+ private readonly double bulletRadiusTimes = 200;
+
+
+
+
+ private List listOfAll;
+ private List listOfShip;
+ private List listOfBuilding;
+ private List listOfBullet;
+ private List listOfResource;
+ private List listOfHome;
+ private int gameTime;
+
+ private Label[] resourceArray;
+ private (int x, int y)[] resourcePositionIndex;
+ private Label[] buildingArray;
+ private (int x, int y)[] buildingPositionIndex;
+ // private Label[] factoryArray;
+ // private int[] factoryPositionIndex;
+ // private Label[] communityArray;
+ // private int[] communityPositionIndex;
+ // private Label[] fortressArray;
+ // private int[] fortressPositionIndex;
+ // private Label[] wormHoleArray;
+ // private int[] wormHolePositionIndex;
+ private Dictionary countMap;
+
+ private object drawPicLock = new object();
+
+ private bool mapFlag = false;
+ private bool hasDrawed = false;
+ public int[,] defaultMap = new int[,] {
+ { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },//6墙,1-5出生点
+ { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },//7草
+ { 6, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6 },//8机
+ { 6, 0, 0, 0, 0, 6, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 0, 0, 0, 6 },//9大门
+ { 6, 0, 0, 0, 0, 6, 6, 6, 6, 7, 0, 0, 0, 0, 0, 15, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 15, 0, 0, 0, 6 },//10紧急出口
+ { 6, 6, 0, 0, 0, 0, 9, 6, 6, 7, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 6, 6, 6, 6, 6, 11, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },//11窗
+ { 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 7, 7, 6, 6, 7, 7, 6, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 13, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 6 },//12-14门
+ { 6, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 7, 7, 7, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6 },//15箱
+ { 6, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 0, 6 },
+ { 6, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 7, 7, 6, 0, 6 },
+ { 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 7, 6, 0, 6 },
+ { 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 6, 12, 6, 6, 6, 6, 6, 6, 11, 6, 6, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 0, 6 },
+ { 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 0, 6 },
+ { 6, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 7, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 6 },
+ { 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 6, 6, 7, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 11, 6, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 6 },
+ { 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 6, 7, 0, 0, 6 },
+ { 6, 7, 7, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 6, 6, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 6 },
+ { 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 0, 0, 5, 0, 7, 7, 6, 0, 0, 0, 0, 0, 0, 7, 6, 6, 6, 6, 15, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 6, 7, 7, 0, 0, 0, 0, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 6 },
+ { 6, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 6, 6, 0, 10, 0, 6 },
+ { 6, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 6, 6, 6, 7, 0, 0, 0, 6 },
+ { 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 7, 0, 2, 0, 0, 6 },
+ { 6, 0, 6, 0, 0, 0, 0, 0, 0, 6, 11, 6, 6, 6, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 11, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 11, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 6, 12, 6, 6, 6, 0, 0, 0, 0, 6, 6, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 6, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 7, 7, 0, 0, 0, 0, 6 },
+ { 6, 0, 6, 7, 0, 0, 0, 8, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 0, 0, 0, 0, 6 },
+ { 6, 0, 6, 6, 6, 6, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,6, 7, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 7, 7, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 6, 7, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 6, 6, 6, 6, 6, 7, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 6 },
+ { 6, 6, 0, 0, 7, 7, 6, 7, 7, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 6 },
+ { 6, 6, 15, 0, 0, 0, 7, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 11, 6, 0, 0, 0, 0, 0, 6 },
+ { 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6,6, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 15, 0, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0,8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 0, 0, 0, 6, 6, 6, 11, 6, 0, 0, 6, 6, 6, 7, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 6, 0, 6, 7, 7, 6, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 14, 6, 6, 6, 0, 0, 0, 0, 0, 7, 0, 0, 6, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7, 6, 0, 6, 6, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7, 6, 6, 6, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 6, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 6, 6, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 11, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 6, 6, 6, 6, 6, 7, 0, 0, 0, 10, 0, 0, 0, 0, 6, 6, 7, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 6, 0, 0, 0, 0, 7, 6, 6, 0, 0, 0, 6 },
+ { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 7, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 0, 7, 7, 6, 6, 0, 0, 0, 6 },
+ { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 }
+ };
+
+ enum MapPatchType
+ {
+ Space = 0,
+ RedHome = 1,
+ BlueHome = 2,
+ Ruin = 3,
+ Shadow = 4,
+ Asteroid = 5,
+ Resource = 6,
+ Building = 7
+ };
+
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Map.xaml b/logic/Client/Map.xaml
new file mode 100644
index 00000000..7362ab8e
--- /dev/null
+++ b/logic/Client/Map.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/logic/Client/Map.xaml.cs b/logic/Client/Map.xaml.cs
new file mode 100644
index 00000000..b40c815e
--- /dev/null
+++ b/logic/Client/Map.xaml.cs
@@ -0,0 +1,43 @@
+namespace Client;
+
+public partial class Map : ContentView
+{
+ public Map(Grid parent, int Row, int Column, int RowSpan = 2)
+ {
+ InitializeComponent();
+ parent.Children.Add(this);
+ parent.SetColumn(this, Column);
+ parent.SetRow(this, Row);
+ parent.SetRowSpan(this, RowSpan);
+ // DrawMap();
+ }
+
+// public void DrawMap()
+// {
+// for (int i = 0; i < 50; i++)
+// {
+// MapGrid.AddRowDefinition(new RowDefinition(13));
+// for (int j = 0; j < 50; j++)
+// {
+// MapGrid.AddColumnDefinition(new ColumnDefinition(13));
+// BoxView boxView = new BoxView
+// {
+// Color = Colors.Gray,
+// HeightRequest = 13,
+// WidthRequest = 13
+// };
+// Border border = new Border
+// {
+// Content = boxView,
+// HeightRequest = 13,
+// WidthRequest = 13,
+// Padding = 0,
+// StrokeThickness = 0.005
+// };
+// MapGrid.Children.Add(border);
+// Grid.SetColumn(border, i);
+// Grid.SetRow(border, j);
+// }
+// }
+// }
+}
\ No newline at end of file
diff --git a/logic/Client/MauiProgram.cs b/logic/Client/MauiProgram.cs
new file mode 100644
index 00000000..502d2308
--- /dev/null
+++ b/logic/Client/MauiProgram.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.Logging;
+
+namespace Client
+{
+ public static class MauiProgram
+ {
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ });
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+
+ return builder.Build();
+ }
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/Android/AndroidManifest.xml b/logic/Client/Platforms/Android/AndroidManifest.xml
new file mode 100644
index 00000000..bdec9b59
--- /dev/null
+++ b/logic/Client/Platforms/Android/AndroidManifest.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/logic/Client/Platforms/Android/MainActivity.cs b/logic/Client/Platforms/Android/MainActivity.cs
new file mode 100644
index 00000000..9371cc36
--- /dev/null
+++ b/logic/Client/Platforms/Android/MainActivity.cs
@@ -0,0 +1,11 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+
+namespace Client
+{
+ [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
+ public class MainActivity : MauiAppCompatActivity
+ {
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/Android/MainApplication.cs b/logic/Client/Platforms/Android/MainApplication.cs
new file mode 100644
index 00000000..2e6ebfc6
--- /dev/null
+++ b/logic/Client/Platforms/Android/MainApplication.cs
@@ -0,0 +1,16 @@
+using Android.App;
+using Android.Runtime;
+
+namespace Client
+{
+ [Application]
+ public class MainApplication : MauiApplication
+ {
+ public MainApplication(IntPtr handle, JniHandleOwnership ownership)
+ : base(handle, ownership)
+ {
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/Android/Resources/values/colors.xml b/logic/Client/Platforms/Android/Resources/values/colors.xml
new file mode 100644
index 00000000..5cd16049
--- /dev/null
+++ b/logic/Client/Platforms/Android/Resources/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #512BD4
+ #2B0B98
+ #2B0B98
+
\ No newline at end of file
diff --git a/logic/Client/Platforms/MacCatalyst/AppDelegate.cs b/logic/Client/Platforms/MacCatalyst/AppDelegate.cs
new file mode 100644
index 00000000..a921e3d4
--- /dev/null
+++ b/logic/Client/Platforms/MacCatalyst/AppDelegate.cs
@@ -0,0 +1,10 @@
+using Foundation;
+
+namespace Client
+{
+ [Register("AppDelegate")]
+ public class AppDelegate : MauiUIApplicationDelegate
+ {
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/MacCatalyst/Info.plist b/logic/Client/Platforms/MacCatalyst/Info.plist
new file mode 100644
index 00000000..0690e472
--- /dev/null
+++ b/logic/Client/Platforms/MacCatalyst/Info.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/logic/Client/Platforms/MacCatalyst/Program.cs b/logic/Client/Platforms/MacCatalyst/Program.cs
new file mode 100644
index 00000000..1e979766
--- /dev/null
+++ b/logic/Client/Platforms/MacCatalyst/Program.cs
@@ -0,0 +1,16 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace Client
+{
+ public class Program
+ {
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/Tizen/Main.cs b/logic/Client/Platforms/Tizen/Main.cs
new file mode 100644
index 00000000..926d42eb
--- /dev/null
+++ b/logic/Client/Platforms/Tizen/Main.cs
@@ -0,0 +1,17 @@
+using Microsoft.Maui;
+using Microsoft.Maui.Hosting;
+using System;
+
+namespace Client
+{
+ internal class Program : MauiApplication
+ {
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+
+ static void Main(string[] args)
+ {
+ var app = new Program();
+ app.Run(args);
+ }
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/Tizen/tizen-manifest.xml b/logic/Client/Platforms/Tizen/tizen-manifest.xml
new file mode 100644
index 00000000..f129498a
--- /dev/null
+++ b/logic/Client/Platforms/Tizen/tizen-manifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ maui-appicon-placeholder
+
+
+
+
+ http://tizen.org/privilege/internet
+
+
+
+
\ No newline at end of file
diff --git a/logic/Client/Platforms/Windows/App.xaml b/logic/Client/Platforms/Windows/App.xaml
new file mode 100644
index 00000000..79a0eb8d
--- /dev/null
+++ b/logic/Client/Platforms/Windows/App.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/logic/Client/Platforms/Windows/App.xaml.cs b/logic/Client/Platforms/Windows/App.xaml.cs
new file mode 100644
index 00000000..61333fff
--- /dev/null
+++ b/logic/Client/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,24 @@
+using Microsoft.UI.Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace Client.WinUI
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ public partial class App : MauiWinUIApplication
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/Windows/Package.appxmanifest b/logic/Client/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 00000000..29eac062
--- /dev/null
+++ b/logic/Client/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/logic/Client/Platforms/Windows/app.manifest b/logic/Client/Platforms/Windows/app.manifest
new file mode 100644
index 00000000..466affca
--- /dev/null
+++ b/logic/Client/Platforms/Windows/app.manifest
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+
+
diff --git a/logic/Client/Platforms/iOS/AppDelegate.cs b/logic/Client/Platforms/iOS/AppDelegate.cs
new file mode 100644
index 00000000..a921e3d4
--- /dev/null
+++ b/logic/Client/Platforms/iOS/AppDelegate.cs
@@ -0,0 +1,10 @@
+using Foundation;
+
+namespace Client
+{
+ [Register("AppDelegate")]
+ public class AppDelegate : MauiUIApplicationDelegate
+ {
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Platforms/iOS/Info.plist b/logic/Client/Platforms/iOS/Info.plist
new file mode 100644
index 00000000..358337bb
--- /dev/null
+++ b/logic/Client/Platforms/iOS/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ LSRequiresIPhoneOS
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+
+
diff --git a/logic/Client/Platforms/iOS/Program.cs b/logic/Client/Platforms/iOS/Program.cs
new file mode 100644
index 00000000..1e979766
--- /dev/null
+++ b/logic/Client/Platforms/iOS/Program.cs
@@ -0,0 +1,16 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace Client
+{
+ public class Program
+ {
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/PlayerStatusBar.xaml b/logic/Client/PlayerStatusBar.xaml
new file mode 100644
index 00000000..7b8cefc0
--- /dev/null
+++ b/logic/Client/PlayerStatusBar.xaml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/logic/Client/PlayerStatusBar.xaml.cs b/logic/Client/PlayerStatusBar.xaml.cs
new file mode 100644
index 00000000..1510522c
--- /dev/null
+++ b/logic/Client/PlayerStatusBar.xaml.cs
@@ -0,0 +1,140 @@
+using System;
+using Protobuf;
+
+namespace Client
+{
+ public partial class PlayerStatusBar : ContentView
+ {
+ enum PlayerRole
+ {
+ Red, //the down player
+ Blue //the up player
+ };
+ PlayerRole myRole;
+ private readonly int lengthOfHpSlide = 240;
+
+ List shipLabels = new List();
+ public PlayerStatusBar(Grid parent, int Row, int Column, int role)
+ {
+ InitializeComponent();
+ if (role == 0)
+ {
+ myRole = PlayerRole.Red;
+ }
+ else
+ {
+ myRole = PlayerRole.Blue;
+ }
+ parent.Children.Add(this);
+ parent.SetColumn(this, Column);
+ parent.SetRow(this, Row);
+ shipLabels.Add(new ShipLabel());
+ shipLabels.Add(new ShipLabel());
+ shipLabels.Add(new ShipLabel());
+ DrawSelfInfo();
+ DrawShipTable();
+ }
+
+ private void DrawSelfInfo()
+ {
+ if (myRole == PlayerRole.Red)
+ {
+ MyName.Text = "Red Player";
+ MyColor.Color = Colors.Red;
+ MyHpSlide.Color = Colors.Red;
+ }
+ else
+ {
+ MyName.Text = "Blue Player";
+ MyColor.Color = Colors.Blue;
+ MyHpSlide.Color = Colors.Blue;
+ }
+ }
+
+ private void DrawShipTable()
+ {
+ for (int shipCounter = 0; shipCounter < shipLabels.Count; shipCounter++)
+ {
+ if (myRole == PlayerRole.Red)
+ {
+ shipLabels[shipCounter].hpSlide.Color = Colors.Red;
+ }
+ else
+ {
+ shipLabels[shipCounter].hpSlide.Color = Colors.Blue;
+ }
+ Grid shipStatusGrid = new Grid();
+ shipStatusGrid.RowDefinitions.Add(new RowDefinition());
+ shipStatusGrid.RowDefinitions.Add(new RowDefinition(10));
+ shipStatusGrid.Add(shipLabels[shipCounter].status);
+ shipStatusGrid.Add(shipLabels[shipCounter].hpSlide);
+ shipStatusGrid.SetRow(shipLabels[shipCounter].status, 0);
+ shipStatusGrid.SetRow(shipLabels[shipCounter].hpSlide, 1);
+
+ ShipAllAttributesGrid.Children.Add(shipLabels[shipCounter].name);
+ ShipAllAttributesGrid.Children.Add(shipLabels[shipCounter].producer);
+ ShipAllAttributesGrid.Children.Add(shipLabels[shipCounter].constructor);
+ ShipAllAttributesGrid.Children.Add(shipLabels[shipCounter].armor);
+ ShipAllAttributesGrid.Children.Add(shipLabels[shipCounter].shield);
+ ShipAllAttributesGrid.Children.Add(shipLabels[shipCounter].weapon);
+ ShipAllAttributesGrid.Children.Add(shipStatusGrid);
+ //ShipAllAttributesGrid.Children.Add(shipLabels[shipCounter].status);
+
+ ShipAllAttributesGrid.SetRow(shipLabels[shipCounter].name, shipCounter);
+ ShipAllAttributesGrid.SetRow(shipLabels[shipCounter].producer, shipCounter);
+ ShipAllAttributesGrid.SetRow(shipLabels[shipCounter].constructor, shipCounter);
+ ShipAllAttributesGrid.SetRow(shipLabels[shipCounter].armor, shipCounter);
+ ShipAllAttributesGrid.SetRow(shipLabels[shipCounter].shield, shipCounter);
+ ShipAllAttributesGrid.SetRow(shipLabels[shipCounter].weapon, shipCounter);
+ ShipAllAttributesGrid.SetRow(shipStatusGrid, shipCounter);
+ //ShipAllAttributesGrid.SetRow(shipLabels[shipCounter].status, shipCounter);
+
+ ShipAllAttributesGrid.SetColumn(shipLabels[shipCounter].name, 0);
+ ShipAllAttributesGrid.SetColumn(shipLabels[shipCounter].producer, 1);
+ ShipAllAttributesGrid.SetColumn(shipLabels[shipCounter].constructor, 2);
+ ShipAllAttributesGrid.SetColumn(shipLabels[shipCounter].armor, 3);
+ ShipAllAttributesGrid.SetColumn(shipLabels[shipCounter].shield, 4);
+ ShipAllAttributesGrid.SetColumn(shipLabels[shipCounter].weapon, 5);
+ ShipAllAttributesGrid.SetColumn(shipStatusGrid, 5);
+ //ShipAllAttributesGrid.SetColumn(shipLabels[shipCounter].status, 6);
+ }
+ }
+
+ public void SetPlayerValue(MessageOfHome player)
+ {
+ if (player.Team == PlayerTeam.Down && myRole == PlayerRole.Red || player.Team == PlayerTeam.Up && myRole == PlayerRole.Blue)
+ {
+ MyHpData.Text = player.Hp.ToString();
+ MyHpSlide.WidthRequest = player.Hp / 100.0 * lengthOfHpSlide;
+ MyMoney.Text = player.Economy.ToString();
+ }
+ }
+
+ public void SetShipValue(MessageOfShip ship)
+ {
+ if (ship.Team == PlayerTeam.Down && myRole == PlayerRole.Red || ship.Team == PlayerTeam.Up && myRole == PlayerRole.Blue)
+ {
+ ShipLabel shipLabel = new ShipLabel();
+ shipLabel.name.Text = ship.ShipType.ToString() + ship.ShipId.ToString();
+ shipLabel.producer.Text = ship.CollectorType.ToString();
+ shipLabel.armor.Text = ship.ArmorType.ToString();
+ shipLabel.shield.Text = ship.ShieldType.ToString();
+ shipLabel.weapon.Text = ship.BulletType.ToString();
+ shipLabel.constructor.Text = ship.BuilderType.ToString();
+ shipLabel.status.Text = ship.ShipState.ToString();
+ }
+ //TODO: Dynamic change the ships
+ }
+ }
+ public class ShipLabel
+ {
+ public Label name = new Label() { Text = "name" };
+ public Label producer = new Label(){ Text = "producer" };
+ public Label constructor = new Label(){ Text = "constructor"};
+ public Label armor = new Label(){ Text = "armor"};
+ public Label shield = new Label(){ Text = "shield"};
+ public Label weapon = new Label(){ Text = "weapon"};
+ public Label status = new Label() { Text = "IDLE" };
+ public BoxView hpSlide = new BoxView() { Color = Colors.Red, WidthRequest = 80, HeightRequest = 3, HorizontalOptions = LayoutOptions.Start, VerticalOptions = LayoutOptions.End };
+ };
+}
\ No newline at end of file
diff --git a/logic/Client/Properties/PlayerBarGrid_new.xml b/logic/Client/Properties/PlayerBarGrid_new.xml
new file mode 100644
index 00000000..e661f071
--- /dev/null
+++ b/logic/Client/Properties/PlayerBarGrid_new.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/logic/Client/Properties/launchSettings.json b/logic/Client/Properties/launchSettings.json
new file mode 100644
index 00000000..c16206a8
--- /dev/null
+++ b/logic/Client/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Windows Machine": {
+ "commandName": "MsixPackage",
+ "nativeDebugging": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/logic/Client/Protos.csproj b/logic/Client/Protos.csproj
new file mode 100644
index 00000000..106e9152
--- /dev/null
+++ b/logic/Client/Protos.csproj
@@ -0,0 +1,35 @@
+
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/logic/Client/Resources/AppIcon/appicon.svg b/logic/Client/Resources/AppIcon/appicon.svg
new file mode 100644
index 00000000..5f04fcfc
--- /dev/null
+++ b/logic/Client/Resources/AppIcon/appicon.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/logic/Client/Resources/AppIcon/appiconfg.svg b/logic/Client/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 00000000..62d66d7a
--- /dev/null
+++ b/logic/Client/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/logic/Client/Resources/Fonts/OpenSans-Regular.ttf b/logic/Client/Resources/Fonts/OpenSans-Regular.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..8a58a8d0ead9b593ef22efe39eaf214e8f91c091
GIT binary patch
literal 107276
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