Title Screen
Polished UI for the title screen Added login, registration and session management to CultClient Connected title screen to CultClient login and registration
This commit is contained in:
parent
28c06289bf
commit
95947355c2
37 changed files with 4639 additions and 2433 deletions
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using LiteNetLib;
|
||||
using MessagePack;
|
||||
using UniRx;
|
||||
|
|
@ -10,14 +12,30 @@ public static class CultClient {
|
|||
public static Action<string> Logger = s =>
|
||||
MainThreadDispatcher.Post(_=>Debug.Log(s),null);
|
||||
|
||||
public static NetManager Client;
|
||||
public static event Action<string> OnError;
|
||||
public static int Ping;
|
||||
|
||||
private static NetManager _client;
|
||||
private static NetPeer _peer;
|
||||
private static Dictionary<Type, NotAnActionCollection> _messageCallbacks = new Dictionary<Type, NotAnActionCollection>();
|
||||
private static Guid _token;
|
||||
private static MD5 _hasher = MD5.Create();
|
||||
|
||||
public static bool Verified => _token != Guid.Empty;
|
||||
public static bool Connected => _client != null;
|
||||
|
||||
public static void Send<T>(T m) where T : Message
|
||||
{
|
||||
Logger($"Sending message {MessagePackSerializer.SerializeToJson(m as Message)}");
|
||||
_peer.Send(m as Message);
|
||||
if (Connected)
|
||||
{
|
||||
if (Verified || m is LoginMessage || m is RegisterMessage || m is VerifyMessage)
|
||||
{
|
||||
Logger($"Sending message {MessagePackSerializer.SerializeToJson(m as Message)}");
|
||||
_peer.Send(m as Message);
|
||||
}
|
||||
else Logger("Cannot send message, client is not verified!");
|
||||
}
|
||||
else Logger("Cannot send message, client is not connected!");
|
||||
}
|
||||
|
||||
public static void ClearMessageListeners()
|
||||
|
|
@ -32,38 +50,84 @@ public static class CultClient {
|
|||
((ActionCollection<T>)_messageCallbacks[typeof(T)]).Add(callback);
|
||||
}
|
||||
|
||||
public static void Login(string auth, string password)
|
||||
{
|
||||
if (8 < password.Length && password.Length < 32)
|
||||
Send(new LoginMessage
|
||||
{
|
||||
Auth = auth,
|
||||
Password = _hasher.ComputeHash(Encoding.UTF8.GetBytes(password))
|
||||
});
|
||||
else Logger("Invalid Password");
|
||||
}
|
||||
|
||||
public static void Register(string email, string username, string password)
|
||||
{
|
||||
if (8 < password.Length && password.Length < 32)
|
||||
Send(new RegisterMessage
|
||||
{
|
||||
Email = email,
|
||||
Name = username,
|
||||
Password = _hasher.ComputeHash(Encoding.UTF8.GetBytes(password))
|
||||
});
|
||||
else Logger("Invalid Password");
|
||||
}
|
||||
|
||||
public static void Connect(string host = "localhost", int port = 3075)
|
||||
{
|
||||
EventBasedNetListener listener = new EventBasedNetListener();
|
||||
Client = new NetManager(listener)
|
||||
_client = new NetManager(listener)
|
||||
{
|
||||
// UnsyncedEvents = true,
|
||||
// MergeEnabled = true,
|
||||
// NatPunchEnabled = true
|
||||
};
|
||||
Client.Start(3074);
|
||||
_peer = Client.Connect(host, port, "aetheria-cc65a44d");
|
||||
Observable.EveryUpdate().Subscribe(_ => Client.PollEvents());
|
||||
_client.Start(3074);
|
||||
_peer = _client.Connect(host, port, "aetheria-cc65a44d");
|
||||
Observable.EveryUpdate().Subscribe(_ => _client.PollEvents());
|
||||
listener.NetworkErrorEvent += (point, code) => Logger($"{point.Address}: Error {code}");
|
||||
listener.NetworkReceiveEvent += (peer, reader, method) =>
|
||||
{
|
||||
Logger($"Received message: {MessagePackSerializer.ConvertToJson(new ReadOnlyMemory<byte>(reader.RawData))}");
|
||||
var message = MessagePackSerializer.Deserialize<Message>(reader.RawData);
|
||||
var type = message.GetType();
|
||||
|
||||
if (!Verified)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case LoginSuccessMessage loginSuccess:
|
||||
_token = loginSuccess.Session;
|
||||
return;
|
||||
case ErrorMessage error:
|
||||
OnError?.Invoke(error.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_messageCallbacks.ContainsKey(type))
|
||||
typeof(ActionCollection<>).MakeGenericType(new[] {type}).GetMethod("Invoke").Invoke(_messageCallbacks[type], new object[] {message});
|
||||
typeof(ActionCollection<>).MakeGenericType(new[] {type}).GetMethod("Invoke")
|
||||
.Invoke(_messageCallbacks[type], new object[] {message});
|
||||
else
|
||||
Logger(
|
||||
$"Received {type.Name} message but no one is listening for it so I'll just leave it here " +
|
||||
$"¯\\_(ツ)_/¯\n{MessagePackSerializer.ConvertToJson(new ReadOnlyMemory<byte>(reader.RawData))}");
|
||||
|
||||
};
|
||||
|
||||
listener.PeerConnectedEvent += peer =>
|
||||
{
|
||||
Logger($"Peer {peer.EndPoint.Address}:{peer.EndPoint.Port} connected.");
|
||||
_peer = peer;
|
||||
// onConnect();
|
||||
};
|
||||
|
||||
listener.PeerDisconnectedEvent += (peer, info) =>
|
||||
{
|
||||
Logger($"Peer {peer.EndPoint.Address}:{peer.EndPoint.Port} disconnected: {info.Reason}.");
|
||||
_peer = null;
|
||||
};
|
||||
// listener.NetworkLatencyUpdateEvent += (peer, latency) => Logger($"Ping received: {latency} ms");
|
||||
|
||||
listener.NetworkLatencyUpdateEvent +=
|
||||
(peer, latency) => Ping = latency; //Logger($"Ping received: {latency} ms");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
102
Assets/Scripts/FlatButton.cs
Normal file
102
Assets/Scripts/FlatButton.cs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class FlatButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
|
||||
{
|
||||
public event Action<FlatButton> OnClick;
|
||||
public float StateDamping;
|
||||
// public RectTransform Tab;
|
||||
public Image Fill;
|
||||
public Image Outline;
|
||||
public TextMeshProUGUI Label;
|
||||
public VerticalLayoutGroup LabelLayout;
|
||||
public FlatButtonState CurrentState = FlatButtonState.Unselected;
|
||||
public bool DisableClickWhenSelected = true;
|
||||
|
||||
public FlatButtonAppearance UnselectedAppearance;
|
||||
public FlatButtonAppearance SelectedAppearance;
|
||||
public FlatButtonAppearance HoverAppearance;
|
||||
public FlatButtonAppearance ClickAppearance;
|
||||
|
||||
private RectOffset _defaultPadding;
|
||||
private float _currentPadding;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_defaultPadding = LabelLayout.padding;
|
||||
_currentPadding = _defaultPadding.left;
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
if (CurrentState == FlatButtonState.Unselected)
|
||||
CurrentState = FlatButtonState.Hover;
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
if (CurrentState == FlatButtonState.Hover)
|
||||
CurrentState = FlatButtonState.Unselected;
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (!DisableClickWhenSelected || CurrentState != FlatButtonState.Selected)
|
||||
{
|
||||
Fill.color = ClickAppearance.FillColor;
|
||||
Outline.color = ClickAppearance.OutlineColor;
|
||||
OnClick?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
FlatButtonAppearance appearance;
|
||||
switch (CurrentState)
|
||||
{
|
||||
case FlatButtonState.Unselected:
|
||||
appearance = UnselectedAppearance;
|
||||
break;
|
||||
case FlatButtonState.Selected:
|
||||
appearance = SelectedAppearance;
|
||||
break;
|
||||
case FlatButtonState.Hover:
|
||||
appearance = HoverAppearance;
|
||||
break;
|
||||
default:
|
||||
appearance = new FlatButtonAppearance();
|
||||
break;
|
||||
}
|
||||
|
||||
Fill.color = Color.Lerp(Fill.color, appearance.FillColor, StateDamping * Time.deltaTime);
|
||||
Outline.color = Color.Lerp(Outline.color, appearance.OutlineColor, StateDamping * Time.deltaTime);
|
||||
_currentPadding = Mathf.Lerp(_currentPadding, appearance.LayoutPadding, StateDamping * Time.deltaTime);
|
||||
LabelLayout.padding = new RectOffset
|
||||
{
|
||||
bottom = _defaultPadding.bottom,
|
||||
top = _defaultPadding.top,
|
||||
left = (int) _currentPadding,
|
||||
right = (int) _currentPadding
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum FlatButtonState
|
||||
{
|
||||
Unselected,
|
||||
Selected,
|
||||
Hover
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct FlatButtonAppearance
|
||||
{
|
||||
public Color FillColor;
|
||||
public Color OutlineColor;
|
||||
public int LayoutPadding;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2ddfc923291e13a458e7e78f2100c021
|
||||
guid: 9ec664fdf25c943478e0ca99c935c2fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
|
||||
public class Scr_Log_In : MonoBehaviour
|
||||
{
|
||||
|
||||
public void Change_Scene()
|
||||
{
|
||||
SceneManager.LoadScene("Main");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -10,6 +10,17 @@ public class NameAttribute : Attribute
|
|||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class RethinkTableAttribute : Attribute
|
||||
{
|
||||
public string TableName;
|
||||
|
||||
public RethinkTableAttribute(string tableName)
|
||||
{
|
||||
TableName = tableName;
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateOrderAttribute : Attribute
|
||||
{
|
||||
public int Order;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public abstract class DatabaseEntry
|
|||
[IgnoreMember] public GameContext Context { get; set; }
|
||||
}
|
||||
|
||||
[RethinkTable("Users")]
|
||||
[MessagePackObject]
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class Player : DatabaseEntry, INamedEntry
|
||||
|
|
@ -58,8 +59,8 @@ public class Player : DatabaseEntry, INamedEntry
|
|||
[JsonProperty("username")] [Key(3)]
|
||||
public string Username;
|
||||
|
||||
[JsonProperty("salt")] [Key(4)]
|
||||
public string Salt;
|
||||
[JsonProperty("corporation")] [Key(4)]
|
||||
public Guid Corporation;
|
||||
|
||||
[IgnoreMember] public string EntryName
|
||||
{
|
||||
|
|
@ -68,6 +69,7 @@ public class Player : DatabaseEntry, INamedEntry
|
|||
}
|
||||
}
|
||||
|
||||
[RethinkTable("Galaxy")]
|
||||
[MessagePackObject]
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class Corporation : DatabaseEntry, INamedEntry
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ public class PingMessage : Message
|
|||
[MessagePackObject]
|
||||
public class LoginMessage : Message
|
||||
{
|
||||
[Key(0)] public string Email;
|
||||
[Key(1)] public string Password;
|
||||
[Key(0)] public string Auth;
|
||||
[Key(1)] public byte[] Password;
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
|
|
@ -37,7 +37,7 @@ public class RegisterMessage : Message
|
|||
{
|
||||
[Key(0)] public string Name;
|
||||
[Key(1)] public string Email;
|
||||
[Key(2)] public string Password;
|
||||
[Key(2)] public byte[] Password;
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using MessagePack;
|
|||
using Newtonsoft.Json;
|
||||
using Unity.Mathematics;
|
||||
|
||||
[RethinkTable("Galaxy")]
|
||||
[MessagePackObject]
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class ZoneData : DatabaseEntry, INamedEntry
|
||||
|
|
@ -34,6 +35,7 @@ public class ZoneData : DatabaseEntry, INamedEntry
|
|||
}
|
||||
}
|
||||
|
||||
[RethinkTable("Galaxy")]
|
||||
[MessagePackObject]
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class Station : DatabaseEntry, INamedEntry
|
||||
|
|
@ -57,6 +59,9 @@ public class Station : DatabaseEntry, INamedEntry
|
|||
[JsonProperty("selling")] [Key(6)]
|
||||
public Dictionary<Guid, float> SellPrices = new Dictionary<Guid, float>();
|
||||
|
||||
[JsonProperty("zone")] [Key(7)]
|
||||
public Guid Zone;
|
||||
|
||||
[IgnoreMember] public string EntryName
|
||||
{
|
||||
get => Name;
|
||||
|
|
@ -64,6 +69,7 @@ public class Station : DatabaseEntry, INamedEntry
|
|||
}
|
||||
}
|
||||
|
||||
[RethinkTable("Galaxy")]
|
||||
[MessagePackObject]
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class PlanetData : DatabaseEntry, INamedEntry
|
||||
|
|
@ -77,6 +83,9 @@ public class PlanetData : DatabaseEntry, INamedEntry
|
|||
[JsonProperty("mass")] [Key(3)]
|
||||
public float Mass;
|
||||
|
||||
[JsonProperty("zone")] [Key(4)]
|
||||
public Guid Zone;
|
||||
|
||||
[IgnoreMember] public string EntryName
|
||||
{
|
||||
get => Name;
|
||||
|
|
@ -84,6 +93,7 @@ public class PlanetData : DatabaseEntry, INamedEntry
|
|||
}
|
||||
}
|
||||
|
||||
[RethinkTable("Galaxy")]
|
||||
[MessagePackObject]
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class OrbitData : DatabaseEntry
|
||||
|
|
@ -99,4 +109,7 @@ public class OrbitData : DatabaseEntry
|
|||
|
||||
[JsonProperty("period")] [Key(4)]
|
||||
public float Period;
|
||||
|
||||
[JsonProperty("zone")] [Key(5)]
|
||||
public Guid Zone;
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Switch_state : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c062bd8d0dfb2714a8098c6299ac8741
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -6,96 +6,7 @@ using UnityEngine;
|
|||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class TabButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
|
||||
public class TabButton : FlatButton
|
||||
{
|
||||
public event Action<TabButton> OnClick;
|
||||
public float StateDamping;
|
||||
public RectTransform Tab;
|
||||
public Image Fill;
|
||||
public Image Outline;
|
||||
public TextMeshProUGUI Label;
|
||||
public VerticalLayoutGroup LabelLayout;
|
||||
public TabButtonState CurrentState = TabButtonState.Unselected;
|
||||
|
||||
public TabButtonAppearance UnselectedAppearance;
|
||||
public TabButtonAppearance SelectedAppearance;
|
||||
public TabButtonAppearance HoverAppearance;
|
||||
public TabButtonAppearance ClickAppearance;
|
||||
|
||||
private RectOffset _defaultPadding;
|
||||
private float _currentPadding;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_defaultPadding = LabelLayout.padding;
|
||||
_currentPadding = _defaultPadding.left;
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
if (CurrentState == TabButtonState.Unselected)
|
||||
CurrentState = TabButtonState.Hover;
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
if (CurrentState == TabButtonState.Hover)
|
||||
CurrentState = TabButtonState.Unselected;
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
if (CurrentState != TabButtonState.Selected)
|
||||
{
|
||||
Fill.color = ClickAppearance.FillColor;
|
||||
Outline.color = ClickAppearance.OutlineColor;
|
||||
OnClick?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
TabButtonAppearance appearance;
|
||||
switch (CurrentState)
|
||||
{
|
||||
case TabButtonState.Unselected:
|
||||
appearance = UnselectedAppearance;
|
||||
break;
|
||||
case TabButtonState.Selected:
|
||||
appearance = SelectedAppearance;
|
||||
break;
|
||||
case TabButtonState.Hover:
|
||||
appearance = HoverAppearance;
|
||||
break;
|
||||
default:
|
||||
appearance = new TabButtonAppearance();
|
||||
break;
|
||||
}
|
||||
|
||||
Fill.color = Color.Lerp(Fill.color, appearance.FillColor, StateDamping * Time.deltaTime);
|
||||
Outline.color = Color.Lerp(Outline.color, appearance.OutlineColor, StateDamping * Time.deltaTime);
|
||||
_currentPadding = Mathf.Lerp(_currentPadding, appearance.LayoutPadding, StateDamping * Time.deltaTime);
|
||||
LabelLayout.padding = new RectOffset
|
||||
{
|
||||
bottom = _defaultPadding.bottom,
|
||||
top = _defaultPadding.top,
|
||||
left = (int) _currentPadding,
|
||||
right = (int) _currentPadding
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum TabButtonState
|
||||
{
|
||||
Unselected,
|
||||
Selected,
|
||||
Hover
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public struct TabButtonAppearance
|
||||
{
|
||||
public Color FillColor;
|
||||
public Color OutlineColor;
|
||||
public int LayoutPadding;
|
||||
}
|
||||
|
|
@ -19,12 +19,12 @@ public class TabGroup : MonoBehaviour
|
|||
{
|
||||
if (_currentButton != null)
|
||||
{
|
||||
_currentButton.CurrentState = TabButtonState.Unselected;
|
||||
_currentButton.CurrentState = FlatButtonState.Unselected;
|
||||
_currentButton.Tab.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
_currentButton = thisButton;
|
||||
_currentButton.CurrentState = TabButtonState.Selected;
|
||||
_currentButton.CurrentState = FlatButtonState.Selected;
|
||||
_currentButton.Tab.gameObject.SetActive(true);
|
||||
OnTabChange?.Invoke(_currentButton);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue