Experimental Ignorance integration

This commit is contained in:
cxxpxr 2021-08-19 04:38:45 -04:00
parent 7e7ab81a9b
commit 83096a908a
114 changed files with 10152 additions and 204 deletions

View file

@ -12,5 +12,6 @@ namespace LightReflectiveMirror.LoadBalancing
public string AuthKey = "AuthKey"; public string AuthKey = "AuthKey";
public ushort EndpointPort = 7070; public ushort EndpointPort = 7070;
public bool ShowDebugLogs = false; public bool ShowDebugLogs = false;
public int RandomlyGeneratedIDLength = 5;
} }
} }

View file

@ -23,6 +23,8 @@ namespace LightReflectiveMirror.LoadBalancing
const string API_PATH = "/api/stats"; const string API_PATH = "/api/stats";
readonly string CONFIG_PATH = System.Environment.GetEnvironmentVariable("LRM_LB_CONFIG_PATH") ?? "config.json"; readonly string CONFIG_PATH = System.Environment.GetEnvironmentVariable("LRM_LB_CONFIG_PATH") ?? "config.json";
private Random _cachedRandom = new();
public static Config conf; public static Config conf;
public static Program instance; public static Program instance;

View file

@ -28,14 +28,13 @@ namespace LightReflectiveMirror.LoadBalancing
public string GenerateServerID() public string GenerateServerID()
{ {
const int LENGTH = 5;
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var randomID = ""; var randomID = "";
var random = _cachedRandom;
do do
{ {
var random = new System.Random(); randomID = new string(Enumerable.Repeat(chars, conf.RandomlyGeneratedIDLength)
randomID = new string(Enumerable.Repeat(chars, LENGTH)
.Select(s => s[random.Next(s.Length)]).ToArray()); .Select(s => s[random.Next(s.Length)]).ToArray());
} }
while (cachedRooms.ContainsKey(randomID)); while (cachedRooms.ContainsKey(randomID));

View file

@ -1,5 +1,7 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
namespace LightReflectiveMirror namespace LightReflectiveMirror
@ -9,13 +11,16 @@ namespace LightReflectiveMirror
//======================== //========================
// Required Settings // Required Settings
//======================== //========================
public string TransportDLL = "MultiCompiled.dll";
public string TransportClass = "kcp2k.KcpTransport"; public string TransportClass = "kcp2k.KcpTransport";
public string AuthenticationKey = "Secret Auth Key"; public string AuthenticationKey = "Secret Auth Key";
public ushort TransportPort = 7777; public ushort TransportPort = 7777;
public int UpdateLoopTime = 10; public int UpdateLoopTime = 10;
public int UpdateHeartbeatInterval = 100; public int UpdateHeartbeatInterval = 100;
// this wont be used if you are using load balancer
// load balancer will generate instead.
public int RandomlyGeneratedIDLength = 5;
//======================== //========================
// Endpoint REST API Settings // Endpoint REST API Settings
//======================== //========================
@ -37,5 +42,10 @@ namespace LightReflectiveMirror
public string LoadBalancerAddress = "127.0.0.1"; public string LoadBalancerAddress = "127.0.0.1";
public ushort LoadBalancerPort = 7070; public ushort LoadBalancerPort = 7070;
public LRMRegions LoadBalancerRegion = LRMRegions.NorthAmerica; public LRMRegions LoadBalancerRegion = LRMRegions.NorthAmerica;
public static string GetTransportDLL()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "MultiCompiled_WIN.dll" : "MultiCompiled_LINUX.dll";
}
} }
} }

View file

@ -41,7 +41,7 @@ namespace LightReflectiveMirror
WriteLogMessage("Loading Assembly... ", ConsoleColor.White, true); WriteLogMessage("Loading Assembly... ", ConsoleColor.White, true);
try try
{ {
var asm = Assembly.LoadFile(Path.GetFullPath(conf.TransportDLL)); var asm = Assembly.LoadFile(Path.GetFullPath(Config.GetTransportDLL()));
WriteLogMessage($"OK", ConsoleColor.Green); WriteLogMessage($"OK", ConsoleColor.Green);
WriteLogMessage("\nLoading Transport Class... ", ConsoleColor.White, true); WriteLogMessage("\nLoading Transport Class... ", ConsoleColor.White, true);

View file

@ -9,7 +9,7 @@ namespace LightReflectiveMirror
// constructor for new relay handler // constructor for new relay handler
public RelayHandler(int maxPacketSize) public RelayHandler(int maxPacketSize)
{ {
this._maxPacketSize = maxPacketSize; _maxPacketSize = maxPacketSize;
_sendBuffers = ArrayPool<byte>.Create(maxPacketSize, 50); _sendBuffers = ArrayPool<byte>.Create(maxPacketSize, 50);
} }
@ -22,14 +22,13 @@ namespace LightReflectiveMirror
private string GenerateRoomID() private string GenerateRoomID()
{ {
const int LENGTH = 5;
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var randomID = ""; var randomID = "";
var random = _cachedRandom; var random = _cachedRandom;
do do
{ {
randomID = new string(Enumerable.Repeat(chars, LENGTH) randomID = new string(Enumerable.Repeat(chars, Program.conf.RandomlyGeneratedIDLength)
.Select(s => s[random.Next(s.Length)]).ToArray()); .Select(s => s[random.Next(s.Length)]).ToArray());
} }
while (DoesServerIdExist(randomID)); while (DoesServerIdExist(randomID));
@ -74,7 +73,7 @@ namespace LightReflectiveMirror
{ {
if (room.clients.Contains(sendTo)) if (room.clients.Contains(sendTo))
{ {
SendData(clientData, channel, sendTo); SendData(clientData, channel, sendTo, clientId);
} }
} }
else else
@ -84,10 +83,21 @@ namespace LightReflectiveMirror
} }
} }
private void SendData(byte[] clientData, int channel, int sendTo) private void SendData(byte[] clientData, int channel, int sendTo, int senderId)
{ {
// 1 byte for opcode
var headerLength = 1;
var payloadLength = headerLength + clientData.Length;
if (payloadLength > _maxPacketSize)
{
Program.transport.ServerDisconnect(senderId);
Program.WriteLogMessage($"Client {senderId} tried to send more than max packet size! Disconnecting...");
return;
}
int pos = 0; int pos = 0;
byte[] sendBuffer = _sendBuffers.Rent(_maxPacketSize); byte[] sendBuffer = _sendBuffers.Rent(payloadLength);
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData); sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData);
sendBuffer.WriteBytes(ref pos, clientData); sendBuffer.WriteBytes(ref pos, clientData);
@ -96,15 +106,26 @@ namespace LightReflectiveMirror
_sendBuffers.Return(sendBuffer); _sendBuffers.Return(sendBuffer);
} }
private void SendDataToRoomHost(int clientId, byte[] clientData, int channel, Room room) private void SendDataToRoomHost(int senderId, byte[] clientData, int channel, Room room)
{ {
// 1 byte - opcode, 4 bytes for sizeof(int) client id
var headerLength = 5;
var payloadLength = headerLength + clientData.Length;
if(payloadLength > _maxPacketSize)
{
Program.transport.ServerDisconnect(senderId);
Program.WriteLogMessage($"Client {senderId} tried to send more than max packet size! Disconnecting...");
return;
}
// We are not the host, so send the data to the host. // We are not the host, so send the data to the host.
int pos = 0; int pos = 0;
byte[] sendBuffer = _sendBuffers.Rent(_maxPacketSize); byte[] sendBuffer = _sendBuffers.Rent(payloadLength);
sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData); sendBuffer.WriteByte(ref pos, (byte)OpCodes.GetData);
sendBuffer.WriteBytes(ref pos, clientData); sendBuffer.WriteBytes(ref pos, clientData);
sendBuffer.WriteInt(ref pos, clientId); sendBuffer.WriteInt(ref pos, senderId);
Program.transport.ServerSend(room.hostId, channel, new ArraySegment<byte>(sendBuffer, 0, pos)); Program.transport.ServerSend(room.hostId, channel, new ArraySegment<byte>(sendBuffer, 0, pos));
_sendBuffers.Return(sendBuffer); _sendBuffers.Return(sendBuffer);

View file

@ -58,8 +58,15 @@ namespace LightReflectiveMirror
switch (opcode) switch (opcode)
{ {
case OpCodes.CreateRoom: case OpCodes.CreateRoom: // bruh
CreateRoom(clientId, data.ReadInt(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadString(ref pos), data.ReadBool(ref pos), data.ReadInt(ref pos)); CreateRoom(clientId, data.ReadInt (ref pos),
data.ReadString(ref pos),
data.ReadBool (ref pos),
data.ReadString(ref pos),
data.ReadBool (ref pos),
data.ReadString(ref pos),
data.ReadBool (ref pos),
data.ReadInt (ref pos));
break; break;
case OpCodes.RequestID: case OpCodes.RequestID:
SendClientID(clientId); SendClientID(clientId);
@ -100,7 +107,9 @@ namespace LightReflectiveMirror
} }
catch catch
{ {
// Do Nothing. Client probably sent some invalid data. // sent invalid data, boot them hehe
Program.WriteLogMessage($"Client {clientId} sent bad data! Removing from LRM node.");
Program.transport.ServerDisconnect(clientId);
} }
} }

View file

@ -98,7 +98,7 @@ namespace LightReflectiveMirror
{ {
sendJoinPos = 0; sendJoinPos = 0;
sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP); sendJoinBuffer.WriteByte(ref sendJoinPos, (byte)OpCodes.DirectConnectIP);
Console.WriteLine(Program.instance.NATConnections[clientId].Address.ToString());
sendJoinBuffer.WriteString(ref sendJoinPos, Program.instance.NATConnections[clientId].Address.ToString()); sendJoinBuffer.WriteString(ref sendJoinPos, Program.instance.NATConnections[clientId].Address.ToString());
sendJoinBuffer.WriteInt(ref sendJoinPos, Program.instance.NATConnections[clientId].Port); sendJoinBuffer.WriteInt(ref sendJoinPos, Program.instance.NATConnections[clientId].Port);
sendJoinBuffer.WriteBool(ref sendJoinPos, true); sendJoinBuffer.WriteBool(ref sendJoinPos, true);

View file

@ -0,0 +1,288 @@
// Ignorance 1.4.x
// Ignorance. It really kicks the Unity LLAPIs ass.
// https://github.com/SoftwareGuy/Ignorance
// -----------------
// Copyright (c) 2019 - 2020 Matt Coburn (SoftwareGuy/Coburn64)
// Ignorance Transport is licensed under the MIT license. Refer
// to the LICENSE file for more information.
using ENet;
// using NetStack.Buffers;
using System;
using System.Collections.Concurrent;
using System.Threading;
using Event = ENet.Event; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using EventType = ENet.EventType; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using Object = System.Object; // fixes CS0104 ambigous reference between the same thing in UnityEngine
namespace IgnoranceTransport
{
public class IgnoranceClient
{
// Client connection address and port
public string ConnectAddress = "127.0.0.1";
public int ConnectPort = 7777;
// How many channels are expected
public int ExpectedChannels = 2;
// Native poll waiting time
public int PollTime = 1;
// Maximum Packet Size
public int MaximumPacketSize = 33554432;
// General Verbosity by default.
public int Verbosity = 1;
// Queues
public ConcurrentQueue<IgnoranceIncomingPacket> Incoming = new ConcurrentQueue<IgnoranceIncomingPacket>();
public ConcurrentQueue<IgnoranceOutgoingPacket> Outgoing = new ConcurrentQueue<IgnoranceOutgoingPacket>();
public ConcurrentQueue<IgnoranceCommandPacket> Commands = new ConcurrentQueue<IgnoranceCommandPacket>();
public ConcurrentQueue<IgnoranceConnectionEvent> ConnectionEvents = new ConcurrentQueue<IgnoranceConnectionEvent>();
public ConcurrentQueue<IgnoranceClientStats> StatusUpdates = new ConcurrentQueue<IgnoranceClientStats>();
public bool IsAlive => WorkerThread != null && WorkerThread.IsAlive;
private volatile bool CeaseOperation = false;
private Thread WorkerThread;
public void Start()
{
// Debug.Log("IgnoranceClient.Start()");
if (WorkerThread != null && WorkerThread.IsAlive)
{
// Cannot do that.
// Debug.LogError("A worker thread is already running. Cannot start another.");
return;
}
CeaseOperation = false;
ThreadParamInfo threadParams = new ThreadParamInfo()
{
Address = ConnectAddress,
Port = ConnectPort,
Channels = ExpectedChannels,
PollTime = PollTime,
PacketSizeLimit = MaximumPacketSize,
Verbosity = Verbosity
};
// Drain queues.
if (Incoming != null) while (Incoming.TryDequeue(out _)) ;
if (Outgoing != null) while (Outgoing.TryDequeue(out _)) ;
if (Commands != null) while (Commands.TryDequeue(out _)) ;
if (ConnectionEvents != null) while (ConnectionEvents.TryDequeue(out _)) ;
if (StatusUpdates != null) while (StatusUpdates.TryDequeue(out _)) ;
WorkerThread = new Thread(ThreadWorker);
WorkerThread.Start(threadParams);
// Debug.Log("Client has dispatched worker thread.");
}
public void Stop()
{
// Debug.Log("Telling client thread to stop, this may take a while depending on network load");
CeaseOperation = true;
}
// This runs in a seperate thread, be careful accessing anything outside of it's thread
// or you may get an AccessViolation/crash.
private void ThreadWorker(Object parameters)
{
// if (Verbosity > 0)
// Debug.Log("Ignorance Client: Initializing. Please stand by...");
ThreadParamInfo setupInfo;
Address clientAddress = new Address();
Peer clientPeer;
Host clientENetHost;
Event clientENetEvent;
IgnoranceClientStats icsu = default;
// Grab the setup information.
if (parameters.GetType() == typeof(ThreadParamInfo))
{
setupInfo = (ThreadParamInfo)parameters;
}
else
{
// Debug.LogError("Ignorance Client: Startup failure: Invalid thread parameters. Aborting.");
return;
}
// Attempt to initialize ENet inside the thread.
if (Library.Initialize())
{
Console.WriteLine("Ignorance Client: ENet initialized.");
}
else
{
// Debug.LogError("Ignorance Client: Failed to initialize ENet. This threads' fucked.");
return;
}
// Attempt to connect to our target.
clientAddress.SetHost(setupInfo.Address);
clientAddress.Port = (ushort)setupInfo.Port;
using (clientENetHost = new Host())
{
// TODO: Maybe try catch this
clientENetHost.Create();
clientPeer = clientENetHost.Connect(clientAddress, setupInfo.Channels);
while (!CeaseOperation)
{
bool pollComplete = false;
// Step 0: Handle commands.
while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
{
switch (commandPacket.Type)
{
default:
break;
case IgnoranceCommandType.ClientWantsToStop:
CeaseOperation = true;
break;
case IgnoranceCommandType.ClientRequestsStatusUpdate:
// Respond with statistics so far.
if (!clientPeer.IsSet)
break;
icsu.RTT = clientPeer.RoundTripTime;
icsu.BytesReceived = clientPeer.BytesReceived;
icsu.BytesSent = clientPeer.BytesSent;
icsu.PacketsReceived = clientENetHost.PacketsReceived;
icsu.PacketsSent = clientPeer.PacketsSent;
icsu.PacketsLost = clientPeer.PacketsLost;
StatusUpdates.Enqueue(icsu);
break;
}
}
// Step 1: Send out data.
// ---> Sending to Server
while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
{
// TODO: Revise this, could we tell the Peer to disconnect right here?
// Stop early if we get a client stop packet.
// if (outgoingPacket.Type == IgnorancePacketType.ClientWantsToStop) break;
int ret = clientPeer.Send(outgoingPacket.Channel, ref outgoingPacket.Payload);
}
// Step 2:
// <----- Receive Data packets
// This loops until polling is completed. It may take a while, if it's
// a slow networking day.
while (!pollComplete)
{
Packet incomingPacket;
Peer incomingPeer;
int incomingPacketLength;
// Any events worth checking out?
if (clientENetHost.CheckEvents(out clientENetEvent) <= 0)
{
// If service time is met, break out of it.
if (clientENetHost.Service(setupInfo.PollTime, out clientENetEvent) <= 0) break;
// Poll is done.
pollComplete = true;
}
// Setup the packet references.
incomingPeer = clientENetEvent.Peer;
// Now, let's handle those events.
switch (clientENetEvent.Type)
{
case EventType.None:
default:
break;
case EventType.Connect:
ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
{
NativePeerId = incomingPeer.ID,
IP = incomingPeer.IP,
Port = incomingPeer.Port
});
break;
case EventType.Disconnect:
case EventType.Timeout:
ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
{
WasDisconnect = true
});
break;
case EventType.Receive:
// Receive event type usually includes a packet; so cache its reference.
incomingPacket = clientENetEvent.Packet;
if (!incomingPacket.IsSet)
{
break;
}
incomingPacketLength = incomingPacket.Length;
// Never consume more than we can have capacity for.
if (incomingPacketLength > setupInfo.PacketSizeLimit)
{
incomingPacket.Dispose();
break;
}
IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
{
Channel = clientENetEvent.ChannelID,
NativePeerId = incomingPeer.ID,
Payload = incomingPacket
};
Incoming.Enqueue(incomingQueuePacket);
break;
}
}
}
Console.WriteLine("Ignorance Server: Shutdown commencing, disconnecting and flushing connection.");
// Flush the client and disconnect.
clientPeer.Disconnect(0);
clientENetHost.Flush();
// Fix for client stuck in limbo, since the disconnection event may not be fired until next loop.
ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
{
WasDisconnect = true
});
}
// Deinitialize
Library.Deinitialize();
}
private struct ThreadParamInfo
{
public int Channels;
public int PollTime;
public int Port;
public int PacketSizeLimit;
public int Verbosity;
public string Address;
}
}
}

View file

@ -0,0 +1,303 @@
// Ignorance 1.4.x
// Ignorance. It really kicks the Unity LLAPIs ass.
// https://github.com/SoftwareGuy/Ignorance
// -----------------
// Copyright (c) 2019 - 2020 Matt Coburn (SoftwareGuy/Coburn64)
// Ignorance Transport is licensed under the MIT license. Refer
// to the LICENSE file for more information.
using ENet;
// using NetStack.Buffers;
using System.Collections.Concurrent;
using System.Threading;
using Event = ENet.Event; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using EventType = ENet.EventType; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using Object = System.Object; // fixes CS0104 ambigous reference between the same thing in UnityEngine
namespace IgnoranceTransport
{
public class IgnoranceServer
{
// Server Properties
// - Bind Settings
public string BindAddress = "127.0.0.1";
public int BindPort = 7777;
// - Maximum allowed channels, peers, etc.
public int MaximumChannels = 2;
public int MaximumPeers = 100;
public int MaximumPacketSize = 33554432; // ENet.cs: uint maxPacketSize = 32 * 1024 * 1024 = 33554432
// - Native poll waiting time
public int PollTime = 1;
public int Verbosity = 1;
public bool IsAlive => WorkerThread != null && WorkerThread.IsAlive;
private volatile bool CeaseOperation = false;
// Queues
public ConcurrentQueue<IgnoranceIncomingPacket> Incoming = new ConcurrentQueue<IgnoranceIncomingPacket>();
public ConcurrentQueue<IgnoranceOutgoingPacket> Outgoing = new ConcurrentQueue<IgnoranceOutgoingPacket>();
public ConcurrentQueue<IgnoranceCommandPacket> Commands = new ConcurrentQueue<IgnoranceCommandPacket>();
public ConcurrentQueue<IgnoranceConnectionEvent> ConnectionEvents = new ConcurrentQueue<IgnoranceConnectionEvent>();
public ConcurrentQueue<IgnoranceConnectionEvent> DisconnectionEvents = new ConcurrentQueue<IgnoranceConnectionEvent>();
// Thread
private Thread WorkerThread;
public void Start()
{
if (WorkerThread != null && WorkerThread.IsAlive)
{
// Cannot do that.
return;
}
CeaseOperation = false;
ThreadParamInfo threadParams = new ThreadParamInfo()
{
Address = BindAddress,
Port = BindPort,
Peers = MaximumPeers,
Channels = MaximumChannels,
PollTime = PollTime,
PacketSizeLimit = MaximumPacketSize,
Verbosity = Verbosity
};
// Drain queues.
if (Incoming != null) while (Incoming.TryDequeue(out _)) ;
if (Outgoing != null) while (Outgoing.TryDequeue(out _)) ;
if (Commands != null) while (Commands.TryDequeue(out _)) ;
if (ConnectionEvents != null) while (ConnectionEvents.TryDequeue(out _)) ;
if (DisconnectionEvents != null) while (DisconnectionEvents.TryDequeue(out _)) ;
WorkerThread = new Thread(ThreadWorker);
WorkerThread.Start(threadParams);
}
public void Stop()
{
CeaseOperation = true;
}
private void ThreadWorker(Object parameters)
{
// Thread cache items
ThreadParamInfo setupInfo;
Address serverAddress = new Address();
Host serverENetHost;
Event serverENetEvent;
Peer[] serverPeerArray;
// Grab the setup information.
if (parameters.GetType() == typeof(ThreadParamInfo))
{
setupInfo = (ThreadParamInfo)parameters;
}
else
{
return;
}
// Attempt to initialize ENet inside the thread.
if (Library.Initialize())
{
}
else
{
return;
}
// Configure the server address.
serverAddress.SetHost(setupInfo.Address);
serverAddress.Port = (ushort)setupInfo.Port;
serverPeerArray = new Peer[setupInfo.Peers];
using (serverENetHost = new Host())
{
// Create the server object.
serverENetHost.Create(serverAddress, setupInfo.Peers, setupInfo.Channels);
// Loop until we're told to cease operations.
while (!CeaseOperation)
{
// Intermission: Command Handling
while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
{
switch (commandPacket.Type)
{
default:
break;
// Boot a Peer off the Server.
case IgnoranceCommandType.ServerKickPeer:
uint targetPeer = commandPacket.PeerId;
if (!serverPeerArray[targetPeer].IsSet) continue;
IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent()
{
WasDisconnect = true,
NativePeerId = targetPeer
};
DisconnectionEvents.Enqueue(iced);
// Disconnect and reset the peer array's entry for that peer.
serverPeerArray[targetPeer].DisconnectNow(0);
serverPeerArray[targetPeer] = default;
break;
}
}
// Step One:
// ---> Sending to peers
while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
{
// Only create a packet if the server knows the peer.
if (serverPeerArray[outgoingPacket.NativePeerId].IsSet)
{
int ret = serverPeerArray[outgoingPacket.NativePeerId].Send(outgoingPacket.Channel, ref outgoingPacket.Payload);
}
else
{
// A peer might have disconnected, this is OK - just log the packet if set to paranoid.
}
}
// Step 2
// <--- Receiving from peers
bool pollComplete = false;
while (!pollComplete)
{
Packet incomingPacket;
Peer incomingPeer;
int incomingPacketLength;
// Any events happening?
if (serverENetHost.CheckEvents(out serverENetEvent) <= 0)
{
// If service time is met, break out of it.
if (serverENetHost.Service(setupInfo.PollTime, out serverENetEvent) <= 0) break;
pollComplete = true;
}
// Setup the packet references.
incomingPeer = serverENetEvent.Peer;
switch (serverENetEvent.Type)
{
// Idle.
case EventType.None:
default:
break;
// Connection Event.
case EventType.Connect:
IgnoranceConnectionEvent ice = new IgnoranceConnectionEvent()
{
NativePeerId = incomingPeer.ID,
IP = incomingPeer.IP,
Port = incomingPeer.Port
};
ConnectionEvents.Enqueue(ice);
// Assign a reference to the Peer.
serverPeerArray[incomingPeer.ID] = incomingPeer;
break;
// Disconnect/Timeout. Mirror doesn't care if it's either, so we lump them together.
case EventType.Disconnect:
case EventType.Timeout:
if (!serverPeerArray[incomingPeer.ID].IsSet) break;
IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent()
{
WasDisconnect = true,
NativePeerId = incomingPeer.ID
};
DisconnectionEvents.Enqueue(iced);
// Reset the peer array's entry for that peer.
serverPeerArray[incomingPeer.ID] = default;
break;
case EventType.Receive:
// Receive event type usually includes a packet; so cache its reference.
incomingPacket = serverENetEvent.Packet;
if (!incomingPacket.IsSet)
{
break;
}
incomingPacketLength = incomingPacket.Length;
// Firstly check if the packet is too big. If it is, do not process it - drop it.
if (incomingPacketLength > setupInfo.PacketSizeLimit)
{
incomingPacket.Dispose();
break;
}
IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
{
Channel = serverENetEvent.ChannelID,
NativePeerId = incomingPeer.ID,
Payload = incomingPacket,
};
// Enqueue.
Incoming.Enqueue(incomingQueuePacket);
break;
}
}
}
// Cleanup and flush everything.
serverENetHost.Flush();
// Kick everyone.
for (int i = 0; i < serverPeerArray.Length; i++)
{
if (!serverPeerArray[i].IsSet) continue;
serverPeerArray[i].DisconnectNow(0);
}
}
// Flush again to ensure ENet gets those Disconnection stuff out.
// May not be needed; better to err on side of caution
Library.Deinitialize();
}
private struct ThreadParamInfo
{
public int Channels;
public int Peers;
public int PollTime;
public int Port;
public int PacketSizeLimit;
public int Verbosity;
public string Address;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,510 @@
// Ignorance 1.4.x
// Ignorance. It really kicks the Unity LLAPIs ass.
// https://github.com/SoftwareGuy/Ignorance
// -----------------
// Copyright (c) 2019 - 2020 Matt Coburn (SoftwareGuy/Coburn64)
// Ignorance Transport is licensed under the MIT license. Refer
// to the LICENSE file for more information.
// -----------------
// Ignorance Experimental (New) Version
// -----------------
using ENet;
using Mirror;
using System;
using System.Collections.Generic;
namespace IgnoranceTransport
{
public class Ignorance : Transport
{
public int port = 7777;
public IgnoranceLogType LogType = IgnoranceLogType.Standard;
public bool DebugDisplay = false;
public bool serverBindsAll = true;
public string serverBindAddress = string.Empty;
public int serverMaxPeerCapacity = 50;
public int serverMaxNativeWaitTime = 1;
public int clientMaxNativeWaitTime = 3;
public IgnoranceChannelTypes[] Channels = new[] { IgnoranceChannelTypes.Reliable, IgnoranceChannelTypes.Unreliable };
public int PacketBufferCapacity = 4096;
public int MaxAllowedPacketSize = 33554432;
public IgnoranceClientStats ClientStatistics;
public override bool Available()
{
return true;
}
public override void Awake()
{
if (LogType != IgnoranceLogType.Nothing)
Console.WriteLine($"Thanks for using Ignorance {IgnoranceInternals.Version}. Keep up to date, report bugs and support the developer at https://github.com/SoftwareGuy/Ignorance!");
}
public override string ToString()
{
return $"Ignorance v{IgnoranceInternals.Version}";
}
public override void ClientConnect(string address)
{
ClientState = ConnectionState.Connecting;
cachedConnectionAddress = address;
// Initialize.
InitializeClientBackend();
// Get going.
ignoreDataPackets = false;
// Start!
Client.Start();
}
public override void ClientConnect(Uri uri)
{
if (uri.Scheme != IgnoranceInternals.Scheme)
throw new ArgumentException($"You used an invalid URI: {uri}. Please use {IgnoranceInternals.Scheme}://host:port instead", nameof(uri));
if (!uri.IsDefaultPort)
// Set the communication port to the one specified.
port = uri.Port;
// Pass onwards to the proper handler.
ClientConnect(uri.Host);
}
public override bool ClientConnected() => ClientState == ConnectionState.Connected;
public override void ClientDisconnect()
{
if (Client != null)
Client.Stop();
// TODO: Figure this one out to see if it's related to a race condition.
// Maybe experiment with a while loop to pause main thread when disconnecting,
// since client might not stop on a dime.
// while(Client.IsAlive) ;
// v1.4.0b1: Probably fixed in IgnoranceClient.cs; need further testing.
// ignoreDataPackets = true;
ClientState = ConnectionState.Disconnected;
}
// v1.4.0b6: Mirror rearranged the ClientSend params, so we need to apply a fix for that or
// we end up using the obsoleted version. The obsolete version isn't a fatal error, but
// it's best to stick with the new structures.
public override void ClientSend(int channelId, ArraySegment<byte> segment)
{
if (Client == null)
{
return;
}
if (channelId < 0 || channelId > Channels.Length)
{
return;
}
// Create our struct...
Packet clientOutgoingPacket = default;
int byteCount = segment.Count;
int byteOffset = segment.Offset;
// Set our desired flags...
PacketFlags desiredFlags = (PacketFlags)Channels[channelId];
// Create the packet.
clientOutgoingPacket.Create(segment.Array, byteOffset, byteCount + byteOffset, desiredFlags);
// byteCount
// Enqueue the packet.
IgnoranceOutgoingPacket dispatchPacket = new IgnoranceOutgoingPacket
{
Channel = (byte)channelId,
Payload = clientOutgoingPacket
};
// Pass the packet onto the thread for dispatch.
Client.Outgoing.Enqueue(dispatchPacket);
}
public override bool ServerActive()
{
// Very simple check.
return Server != null && Server.IsAlive;
}
public override bool ServerDisconnect(int connectionId) => ServerDisconnectLegacy(connectionId);
public override string ServerGetClientAddress(int connectionId)
{
if (ConnectionLookupDict.TryGetValue(connectionId, out PeerConnectionData details))
return $"{details.IP}:{details.Port}";
return "(unavailable)";
}
public override void ServerSend(int connectionId, int channelId, ArraySegment<byte> segment)
{
// Debug.Log($"ServerSend({connectionId}, {channelId}, <{segment.Count} byte segment>)");
if (Server == null)
{
// Debug.LogError("Cannot enqueue data packet; our Server object is null. Something has gone wrong.");
return;
}
if (channelId < 0 || channelId > Channels.Length)
{
// Debug.LogError("Channel ID is out of bounds.");
return;
}
// Packet Struct
Packet serverOutgoingPacket = default;
int byteCount = segment.Count;
int byteOffset = segment.Offset;
PacketFlags desiredFlags = (PacketFlags)Channels[channelId];
// Create the packet.
serverOutgoingPacket.Create(segment.Array, byteOffset, byteCount + byteOffset, desiredFlags);
// Enqueue the packet.
IgnoranceOutgoingPacket dispatchPacket = new IgnoranceOutgoingPacket
{
Channel = (byte)channelId,
NativePeerId = (uint)connectionId - 1, // ENet's native peer ID will be ConnID - 1
Payload = serverOutgoingPacket
};
Server.Outgoing.Enqueue(dispatchPacket);
}
public override void ServerStart(ushort _port)
{
if (LogType != IgnoranceLogType.Nothing)
Console.WriteLine("Ignorance Server Instance starting up...");
port = _port;
InitializeServerBackend();
Server.Start();
}
public override void ServerStop()
{
if (Server != null)
{
if (LogType != IgnoranceLogType.Nothing)
Console.WriteLine("Ignorance Server Instance shutting down...");
Server.Stop();
}
ConnectionLookupDict.Clear();
}
public override Uri ServerUri()
{
UriBuilder builder = new UriBuilder
{
Scheme = IgnoranceInternals.Scheme,
Host = serverBindAddress,
Port = port
};
return builder.Uri;
}
public override void Shutdown()
{
// TODO: Nothing needed here?
}
private void InitializeServerBackend()
{
if (Server == null)
{
// Debug.LogWarning("IgnoranceServer reference for Server mode was null. This shouldn't happen, but to be safe we'll reinitialize it.");
Server = new IgnoranceServer();
}
// Set up the new IgnoranceServer reference.
if (serverBindsAll)
// MacOS is special. It's also a massive thorn in my backside.
Server.BindAddress = IgnoranceInternals.BindAllMacs;
else
// Use the supplied bind address.
Server.BindAddress = serverBindAddress;
// Sets port, maximum peers, max channels, the server poll time, maximum packet size and verbosity.
Server.BindPort = port;
Server.MaximumPeers = serverMaxPeerCapacity;
Server.MaximumChannels = Channels.Length;
Server.PollTime = serverMaxNativeWaitTime;
Server.MaximumPacketSize = MaxAllowedPacketSize;
Server.Verbosity = (int)LogType;
// Initializes the packet buffer.
// Allocates once, that's it.
if (InternalPacketBuffer == null)
InternalPacketBuffer = new byte[PacketBufferCapacity];
}
private void InitializeClientBackend()
{
if (Client == null)
{
// Debug.LogWarning("Ignorance: IgnoranceClient reference for Client mode was null. This shouldn't happen, but to be safe we'll reinitialize it.");
Client = new IgnoranceClient();
}
// Sets address, port, channels to expect, verbosity, the server poll time and maximum packet size.
Client.ConnectAddress = cachedConnectionAddress;
Client.ConnectPort = port;
Client.ExpectedChannels = Channels.Length;
Client.PollTime = clientMaxNativeWaitTime;
Client.MaximumPacketSize = MaxAllowedPacketSize;
Client.Verbosity = (int)LogType;
// Initializes the packet buffer.
// Allocates once, that's it.
if (InternalPacketBuffer == null)
InternalPacketBuffer = new byte[PacketBufferCapacity];
}
private void ProcessServerPackets()
{
IgnoranceIncomingPacket incomingPacket;
IgnoranceConnectionEvent connectionEvent;
int adjustedConnectionId;
Packet payload;
// Incoming connection events.
while (Server.ConnectionEvents.TryDequeue(out connectionEvent))
{
adjustedConnectionId = (int)connectionEvent.NativePeerId + 1;
// TODO: Investigate ArgumentException: An item with the same key has already been added. Key: <id>
ConnectionLookupDict.Add(adjustedConnectionId, new PeerConnectionData
{
NativePeerId = connectionEvent.NativePeerId,
IP = connectionEvent.IP,
Port = connectionEvent.Port
});
OnServerConnected?.Invoke(adjustedConnectionId);
}
// Handle incoming data packets.
// Console.WriteLine($"Server Incoming Queue is {Server.Incoming.Count}");
while (Server.Incoming.TryDequeue(out incomingPacket))
{
adjustedConnectionId = (int)incomingPacket.NativePeerId + 1;
payload = incomingPacket.Payload;
int length = payload.Length;
ArraySegment<byte> dataSegment;
// Copy to working buffer and dispose of it.
if (length > InternalPacketBuffer.Length)
{
byte[] oneFreshNTastyGcAlloc = new byte[length];
payload.CopyTo(oneFreshNTastyGcAlloc);
dataSegment = new ArraySegment<byte>(oneFreshNTastyGcAlloc, 0, length);
}
else
{
payload.CopyTo(InternalPacketBuffer);
dataSegment = new ArraySegment<byte>(InternalPacketBuffer, 0, length);
}
payload.Dispose();
OnServerDataReceived?.Invoke(adjustedConnectionId, dataSegment, incomingPacket.Channel);
}
// Disconnection events.
while (Server.DisconnectionEvents.TryDequeue(out IgnoranceConnectionEvent disconnectionEvent))
{
adjustedConnectionId = (int)disconnectionEvent.NativePeerId + 1;
ConnectionLookupDict.Remove(adjustedConnectionId);
// Invoke Mirror handler.
OnServerDisconnected?.Invoke(adjustedConnectionId);
}
}
private void ProcessClientPackets()
{
Packet payload;
// Handle connection events.
while (Client.ConnectionEvents.TryDequeue(out IgnoranceConnectionEvent connectionEvent))
{
if (connectionEvent.WasDisconnect)
{
// Disconnected from server.
ClientState = ConnectionState.Disconnected;
ignoreDataPackets = true;
OnClientDisconnected?.Invoke();
}
else
{
// Connected to server.
ClientState = ConnectionState.Connected;
ignoreDataPackets = false;
OnClientConnected?.Invoke();
}
}
// Now handle the incoming messages.
while (Client.Incoming.TryDequeue(out IgnoranceIncomingPacket incomingPacket))
{
// Temporary fix: if ENet thread is too fast for Mirror, then ignore the packet.
// This is seen sometimes if you stop the client and there's still stuff in the queue.
if (ignoreDataPackets)
{
break;
}
// Otherwise client recieved data, advise Mirror.
// print($"Byte array: {incomingPacket.RentedByteArray.Length}. Packet Length: {incomingPacket.Length}");
payload = incomingPacket.Payload;
int length = payload.Length;
ArraySegment<byte> dataSegment;
// Copy to working buffer and dispose of it.
if (length > InternalPacketBuffer.Length)
{
// Unity's favourite: A fresh 'n' tasty GC Allocation!
byte[] oneFreshNTastyGcAlloc = new byte[length];
payload.CopyTo(oneFreshNTastyGcAlloc);
dataSegment = new ArraySegment<byte>(oneFreshNTastyGcAlloc, 0, length);
}
else
{
payload.CopyTo(InternalPacketBuffer);
dataSegment = new ArraySegment<byte>(InternalPacketBuffer, 0, length);
}
payload.Dispose();
OnClientDataReceived?.Invoke(dataSegment, incomingPacket.Channel);
}
// Step 3: Handle other commands.
while (Client.Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
{
switch (commandPacket.Type)
{
// ...
default:
break;
}
}
// Step 4: Handle status updates.
if (Client.StatusUpdates.TryDequeue(out IgnoranceClientStats clientStats))
{
ClientStatistics = clientStats;
}
}
// Ignorance 1.4.0b5: To use Mirror's polling or not use Mirror's polling, that is up to the developer to decide
// IMPORTANT: Set Ignorance' execution order before everything else. Yes, that's -32000 !!
// This ensures it has priority over other things.
// FixedUpdate can be called many times per frame.
// Once we've handled stuff, we set a flag so that we don't poll again for this frame.
private bool fixedUpdateCompletedWork;
public void FixedUpdate()
{
if (fixedUpdateCompletedWork) return;
ProcessAndExecuteAllPackets();
// Flip the bool to signal we've done our work.
fixedUpdateCompletedWork = true;
}
// Normally, Mirror blocks Update() due to poor design decisions...
// But thanks to Vincenzo, we've found a way to bypass that block.
// Update is called once per frame. We don't have to worry about this shit now.
public override void Update()
{
// Process what FixedUpdate missed, only if the boolean is not set.
if (!fixedUpdateCompletedWork)
ProcessAndExecuteAllPackets();
// Flip back the bool, so it can be reset.
fixedUpdateCompletedWork = false;
}
// Processes and Executes All Packets.
private void ProcessAndExecuteAllPackets()
{
// Process Server Events...
if (Server.IsAlive)
ProcessServerPackets();
// Process Client Events...
if (Client.IsAlive)
{
ProcessClientPackets();
}
}
public override int GetMaxPacketSize(int channelId = 0) => MaxAllowedPacketSize;
private bool ignoreDataPackets;
private string cachedConnectionAddress = string.Empty;
private IgnoranceServer Server = new IgnoranceServer();
private IgnoranceClient Client = new IgnoranceClient();
private Dictionary<int, PeerConnectionData> ConnectionLookupDict = new Dictionary<int, PeerConnectionData>();
private enum ConnectionState { Connecting, Connected, Disconnecting, Disconnected }
private ConnectionState ClientState = ConnectionState.Disconnected;
private byte[] InternalPacketBuffer;
public bool ServerDisconnectLegacy(int connectionId)
{
if (Server == null)
{
// Debug.LogError("Cannot enqueue kick packet; our Server object is null. Something has gone wrong.");
// Return here because otherwise we will get a NRE when trying to enqueue the kick packet.
return false;
}
IgnoranceCommandPacket kickPacket = new IgnoranceCommandPacket
{
Type = IgnoranceCommandType.ServerKickPeer,
PeerId = (uint)connectionId - 1 // ENet's native peer ID will be ConnID - 1
};
// Pass the packet onto the thread for dispatch.
Server.Commands.Enqueue(kickPacket);
return true;
}
}
}

View file

@ -0,0 +1,94 @@
using System;
using ENet;
namespace IgnoranceTransport
{
// Snipped from the transport files, as this will help
// me keep things up to date.
[Serializable]
public enum IgnoranceChannelTypes
{
Reliable = PacketFlags.Reliable, // TCP Emulation.
ReliableUnsequenced = PacketFlags.Reliable | PacketFlags.Unsequenced, // TCP Emulation, but no sequencing.
Unreliable = PacketFlags.Unsequenced, // Pure UDP.
UnreliableFragmented = PacketFlags.UnreliableFragmented, // Pure UDP, but fragmented.
UnreliableSequenced = PacketFlags.None, // Pure UDP, but sequenced.
Unthrottled = PacketFlags.Unthrottled, // Apparently ENet's version of Taco Bell.
}
public class IgnoranceInternals
{
public const string Version = "1.4.0b6";
public const string Scheme = "enet";
public const string BindAllIPv4 = "0.0.0.0";
public const string BindAllMacs = "::0";
}
public enum IgnoranceLogType
{
Nothing,
Standard,
Verbose
}
// Struct optimized for cache efficiency. (Thanks Vincenzo!)
public struct IgnoranceIncomingPacket
{
public byte Channel;
public uint NativePeerId;
public Packet Payload;
}
// Struct optimized for cache efficiency. (Thanks Vincenzo!)
public struct IgnoranceOutgoingPacket
{
public byte Channel;
public uint NativePeerId;
public Packet Payload;
}
// Struct optimized for cache efficiency. (Thanks Vincenzo!)
public struct IgnoranceConnectionEvent
{
public bool WasDisconnect;
public ushort Port;
public uint NativePeerId;
public string IP;
}
public struct IgnoranceCommandPacket
{
public IgnoranceCommandType Type;
public uint PeerId;
}
public struct IgnoranceClientStats
{
// Stats only - may not always be used!
public uint RTT;
public ulong BytesReceived;
public ulong BytesSent;
public ulong PacketsReceived;
public ulong PacketsSent;
public ulong PacketsLost;
}
public enum IgnoranceCommandType
{
// Client
ClientWantsToStop,
ClientRequestsStatusUpdate,
// ENet internal
ResponseToClientStatusRequest,
// Server
ServerKickPeer
}
// TODO: Optimize struct for Cache performance.
public struct PeerConnectionData
{
public ushort Port;
public uint NativePeerId;
public string IP;
}
}

View file

@ -0,0 +1,3 @@
This is a Windows x64 build of ENet-CSharp.
If you require a version of ENet for 32 Bit computer systems (ie. Windows 7/8/10 32Bit) then please get in touch, or you can install the requirements yourself and compile it using ENet-CSharp's MSBuild-based build system. Get in touch if you want me to compile them for you, but keep in mind that I do not support them when reporting bugs.

View file

@ -0,0 +1,35 @@
ENET Pre-compiled Binary Library Blobs
==========================
This folder contains pre-compiled binaries for a variety of different platforms.
A brief summary of these folders are as follows:
- Windows, Mac, Linux
-- 64bit (x64)
- Android (Kitkat 4.4 minimum target OS)
-- ARMv7 (armeabi-v7a), ARMv8/AArch64 (arm64-v8a)
- iOS
-- FAT Library (armv7 + arm64). Targeted for iOS 8 minimum. Unsigned library.
DEBUG VERSIONS
===============
Debug versions of the libraries can be obtained at https://github.com/SoftwareGuy/ENet-CSharp/releases.
Otherwise you can also compile the library yourself with Debug enabled.
DOT POINTS
===========
1. 32bit Support for Ignorance has been removed. Originally, I did not want to support 32bit operating systems,
however due to some countries in the world still stuck in the 32bit era (Brasil, some Russian areas, etc) I added them as a
goodwill gesture. However, since those who needed the libraries have now vanished, I have stopped building 32bit versions of ENet.
COMPILE THE CODE YOURSELF
=========================
If you don't trust the above binaries then git clone the ENET-CSharp repository (http://github.com/SoftwareGuy/ENet-CSharp) and read the readme.
EXCLUSION INSTRUCTIONS
======================
No need, the meta data will cover that for you.
Still don't know what to do with these? Drop by the Mirror discord and post in the Ignorance channel.

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8e62b1f8d9ebd624a9fc425eda441bcd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0f3dc386b0074be4caf7b858e3189529
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 634f781b33ac69147bff9edd5829cfd6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,188 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1080679924113744
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4700925592147096}
- component: {fileID: 212107498293566416}
- component: {fileID: 61279514624852186}
- component: {fileID: 50354248948880112}
- component: {fileID: 114290021321007948}
- component: {fileID: 2590138469697868697}
- component: {fileID: 114121325390084138}
m_Layer: 0
m_Name: AtariBall
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4700925592147096
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080679924113744}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -3, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!212 &212107498293566416
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080679924113744}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Sprite: {fileID: 21300000, guid: 4b66f21097323d44ab40669b2fb9c53d, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!61 &61279514624852186
BoxCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080679924113744}
m_Enabled: 1
m_Density: 1
m_Material: {fileID: 6200000, guid: 97a3e4cddb8635c4eba1265f44d106bf, type: 2}
m_IsTrigger: 0
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: 0, y: 0}
m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0.5, y: 0.5}
oldSize: {x: 1, y: 1}
newSize: {x: 1, y: 1}
adaptiveTilingThreshold: 0.5
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
serializedVersion: 2
m_Size: {x: 1, y: 1}
m_EdgeRadius: 0
--- !u!50 &50354248948880112
Rigidbody2D:
serializedVersion: 4
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080679924113744}
m_BodyType: 0
m_Simulated: 0
m_UseFullKinematicContacts: 0
m_UseAutoMass: 0
m_Mass: 0.0001
m_LinearDrag: 0
m_AngularDrag: 0.05
m_GravityScale: 0
m_Material: {fileID: 0}
m_Interpolate: 0
m_SleepingMode: 1
m_CollisionDetection: 0
m_Constraints: 4
--- !u!114 &114290021321007948
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080679924113744}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
m_Name:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
visible: 0
m_AssetId:
hasSpawned: 0
--- !u!114 &2590138469697868697
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080679924113744}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2a08d5ab1f59230458264367f00c54d8, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
speed: 100
--- !u!114 &114121325390084138
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1080679924113744}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0
clientAuthority: 0
localPositionSensitivity: 0.01
localRotationSensitivity: 0.01
localScaleSensitivity: 0.01
compressRotation: 1
interpolateScale: 0
syncScale: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da367a4c269be6d4a855ee1a9a68256b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,188 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1240244544407914
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4118252415362944}
- component: {fileID: 212641192162007874}
- component: {fileID: 61279767645666242}
- component: {fileID: 50389918509199184}
- component: {fileID: 114104497298166850}
- component: {fileID: -4874889082967523790}
- component: {fileID: 114398896143473162}
m_Layer: 0
m_Name: AtariRacket
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4118252415362944
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1240244544407914}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!212 &212641192162007874
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1240244544407914}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Sprite: {fileID: 21300000, guid: 619ccff3ba2f2a04f9ddd19c264a1ecd, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!61 &61279767645666242
BoxCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1240244544407914}
m_Enabled: 1
m_Density: 1
m_Material: {fileID: 0}
m_IsTrigger: 0
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: 0, y: 0}
m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0.5, y: 0.5}
oldSize: {x: 2, y: 4}
newSize: {x: 1, y: 1}
adaptiveTilingThreshold: 0.5
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
serializedVersion: 2
m_Size: {x: 2, y: 4}
m_EdgeRadius: 0
--- !u!50 &50389918509199184
Rigidbody2D:
serializedVersion: 4
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1240244544407914}
m_BodyType: 0
m_Simulated: 1
m_UseFullKinematicContacts: 0
m_UseAutoMass: 0
m_Mass: 1
m_LinearDrag: 0
m_AngularDrag: 0.05
m_GravityScale: 0
m_Material: {fileID: 0}
m_Interpolate: 1
m_SleepingMode: 1
m_CollisionDetection: 1
m_Constraints: 4
--- !u!114 &114104497298166850
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1240244544407914}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
m_Name:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
visible: 0
m_AssetId:
hasSpawned: 0
--- !u!114 &-4874889082967523790
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1240244544407914}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b68eb08343b29a54dbd5ed7830fb9211, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
speed: 1500
--- !u!114 &114398896143473162
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1240244544407914}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0
clientAuthority: 1
localPositionSensitivity: 0.01
localRotationSensitivity: 0.01
localScaleSensitivity: 0.01
compressRotation: 1
interpolateScale: 0
syncScale: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a85b24263182aae4bbc1829bb2b73d7a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 100100000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c63e1eea85874ae43a7fdd723a38741e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e2898db03f0b9654498df19a98dc9503
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,67 @@
using UnityEngine;
using Mirror;
namespace Ignorance.Examples.PongChamp
{
public class AtariPongBall : NetworkBehaviour
{
public float speed = 100;
private Rigidbody2D rigidbody2d;
private void Awake()
{
rigidbody2d = GetComponent<Rigidbody2D>();
}
public override void OnStartServer()
{
base.OnStartServer();
// only simulate ball physics on server
rigidbody2d.simulated = true;
// Serve the ball from left player
rigidbody2d.velocity = Vector2.right * speed;
}
float HitFactor(Vector2 ballPos, Vector2 racketPos, float racketHeight)
{
// ascii art:
// || 1 <- at the top of the racket
// ||
// || 0 <- at the middle of the racket
// ||
// || -1 <- at the bottom of the racket
return (ballPos.y - racketPos.y) / racketHeight;
}
// only call this on server
[ServerCallback]
void OnCollisionEnter2D(Collision2D col)
{
// Note: 'col' holds the collision information. If the
// Ball collided with a racket, then:
// col.gameObject is the racket
// col.transform.position is the racket's position
// col.collider is the racket's collider
// did we hit a racket? then we need to calculate the hit factor
if (col.transform.GetComponent<AtariPongBall>())
{
// Calculate y direction via hit Factor
float y = HitFactor(transform.position,
col.transform.position,
col.collider.bounds.size.y);
// Calculate x direction via opposite collision
float x = col.relativeVelocity.x > 0 ? 1 : -1;
// Calculate direction, make length=1 via .normalized
Vector2 dir = new Vector2(x, y).normalized;
// Set Velocity with dir * speed
rigidbody2d.velocity = dir * speed;
}
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2a08d5ab1f59230458264367f00c54d8
timeCreated: 1426602353
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,25 @@
using UnityEngine;
using Mirror;
namespace Ignorance.Examples.PongChamp
{
public class AtariPongRacket : NetworkBehaviour
{
public float speed = 1500;
private Rigidbody2D rigidbody2d;
private void Awake()
{
rigidbody2d = GetComponent<Rigidbody2D>();
}
// need to use FixedUpdate for rigidbody
void FixedUpdate()
{
// only let the local player control the racket.
// don't control other player's rackets
if (isLocalPlayer)
rigidbody2d.velocity = new Vector2(0, Input.GetAxisRaw("Vertical")) * speed * Time.fixedDeltaTime;
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b68eb08343b29a54dbd5ed7830fb9211
timeCreated: 1426597826
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,49 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
using System.Diagnostics;
using Debug = UnityEngine.Debug;
public class OnlineTimer : NetworkBehaviour
{
private Stopwatch stopwatch;
// Start is called before the first frame update
private void Awake()
{
stopwatch = new Stopwatch();
}
public override void OnStartClient()
{
stopwatch.Reset();
stopwatch.Start();
Debug.Log("Stopwatch started!");
base.OnStartClient();
}
public void OnDisable()
{
if(stopwatch.IsRunning)
{
System.TimeSpan ts = stopwatch.Elapsed;
stopwatch.Stop();
Debug.Log("Stopwatch stopped: duration " + string.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10));
}
}
private void OnGUI()
{
if (!stopwatch.IsRunning) return;
GUI.Box(new Rect(new Vector2(2, Screen.height - 36), new Vector2(320, 32)), "ONLINE TIME: " + string.Format("{0:00}:{1:00}:{2:00}.{3:00}",
stopwatch.Elapsed.Hours, stopwatch.Elapsed.Minutes, stopwatch.Elapsed.Seconds,
stopwatch.Elapsed.Milliseconds / 10));
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0996ec573094c24890a4d4233ee871e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,178 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &542835289192032773
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 548291784780898253}
- component: {fileID: 394858453892616325}
- component: {fileID: 520653813702449573}
- component: {fileID: 440601958556739609}
- component: {fileID: 440842259441939327}
- component: {fileID: 8881572407762724401}
- component: {fileID: 5995301680282788937}
m_Layer: 0
m_Name: TenryuuBall
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &548291784780898253
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 542835289192032773}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -3, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!212 &394858453892616325
SpriteRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 542835289192032773}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_Sprite: {fileID: 21300000, guid: 824ee62c0fc357b4081855e43253a948, type: 3}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0
m_FlipY: 0
m_DrawMode: 0
m_Size: {x: 1, y: 1}
m_AdaptiveModeThreshold: 0.5
m_SpriteTileMode: 0
m_WasSpriteAssigned: 1
m_MaskInteraction: 0
m_SpriteSortPoint: 0
--- !u!50 &520653813702449573
Rigidbody2D:
serializedVersion: 4
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 542835289192032773}
m_BodyType: 0
m_Simulated: 1
m_UseFullKinematicContacts: 0
m_UseAutoMass: 0
m_Mass: 0.0001
m_LinearDrag: 0
m_AngularDrag: 0
m_GravityScale: 0
m_Material: {fileID: 6200000, guid: 97a3e4cddb8635c4eba1265f44d106bf, type: 2}
m_Interpolate: 2
m_SleepingMode: 1
m_CollisionDetection: 1
m_Constraints: 4
--- !u!114 &440601958556739609
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 542835289192032773}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3}
m_Name:
m_EditorClassIdentifier:
sceneId: 0
serverOnly: 0
visible: 0
m_AssetId:
hasSpawned: 0
--- !u!114 &440842259441939327
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 542835289192032773}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2f74aedd71d9a4f55b3ce499326d45fb, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
clientAuthority: 0
localPositionSensitivity: 0.01
localRotationSensitivity: 0.01
localScaleSensitivity: 0.01
compressRotation: 0
interpolateScale: 1
syncScale: 1
--- !u!58 &8881572407762724401
CircleCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 542835289192032773}
m_Enabled: 1
m_Density: 1
m_Material: {fileID: 0}
m_IsTrigger: 0
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: 0, y: 0}
serializedVersion: 2
m_Radius: 1.28
--- !u!114 &5995301680282788937
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 542835289192032773}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2a08d5ab1f59230458264367f00c54d8, type: 3}
m_Name:
m_EditorClassIdentifier:
syncMode: 0
syncInterval: 0.1
speed: 70

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5339554c46006dd4e91cae9ff34c095d
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 23b5913b9b8b2e1419a41acde1b49883
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -0,0 +1,128 @@
fileFormatVersion: 2
guid: 824ee62c0fc357b4081855e43253a948
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: iPhone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0dbfc247338e79a4dbe7474f69b46503
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,88 @@
fileFormatVersion: 2
guid: 03167da12fa50334e8c8641a23df41b0
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 16
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 1
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: c5a291323e0d5f34883a55625f66ca70
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,88 @@
fileFormatVersion: 2
guid: 75254f20e37ff3640beccde38f796fed
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 16
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 1
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 98b4e2aa86aa3d843821adfe71dbbac0
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,88 @@
fileFormatVersion: 2
guid: e11aad367beb44f4b8a3def9b8fc57ec
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 16
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 1
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 09819c66a21defd49b2cfc87fea685d2
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,88 @@
fileFormatVersion: 2
guid: 51f6a08479c829a49b6a15df6849e727
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 16
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 1
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 74c5541eed52f67428025c83260d8bec
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,88 @@
fileFormatVersion: 2
guid: b41679787bea72d419d10a6df7dc137f
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 16
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 1
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 3a92f998f14389948aa928ac64e8e426
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View file

@ -0,0 +1,121 @@
fileFormatVersion: 2
guid: 160d53f9f2b149c418d6d07e95438e53
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 1a75587224e4a5f468c03dbd1af78d0b
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c94e6c7a1a2b13d41b83aebf5c6ac6b6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,641 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 11
m_GIWorkflowMode: 0
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_MixedBakeMode: 2
m_BakeBackend: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 500
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 500
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 2
m_PVRDenoiserTypeDirect: 0
m_PVRDenoiserTypeIndirect: 0
m_PVRDenoiserTypeAO: 0
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 0
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &249891953
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 249891957}
- component: {fileID: 249891954}
- component: {fileID: 249891956}
- component: {fileID: 249891958}
m_Layer: 0
m_Name: NetworkManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &249891954
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 249891953}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6442dc8070ceb41f094e44de0bf87274, type: 3}
m_Name:
m_EditorClassIdentifier:
showGUI: 1
offsetX: 0
offsetY: 0
--- !u!114 &249891956
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 249891953}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8aab4c8111b7c411b9b92cf3dbc5bd4e, type: 3}
m_Name:
m_EditorClassIdentifier:
dontDestroyOnLoad: 0
runInBackground: 1
autoStartServerBuild: 1
showDebugMessages: 0
serverTickRate: 60
serverBatching: 0
serverBatchInterval: 0
offlineScene:
onlineScene:
transport: {fileID: 249891958}
networkAddress: localhost
maxConnections: 16
disconnectInactiveConnections: 1
disconnectInactiveTimeout: 60
authenticator: {fileID: 0}
playerPrefab: {fileID: 897184729387425976, guid: dc2c4328591bef748abb8df795c17202,
type: 3}
autoCreatePlayer: 1
playerSpawnMethod: 1
spawnPrefabs: []
--- !u!4 &249891957
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 249891953}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -10, y: 4, z: 5}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &249891958
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 249891953}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 872fa23ef6e77334ca452ce16f6cd091, type: 3}
m_Name:
m_EditorClassIdentifier:
port: 7777
LogType: 1
DebugDisplay: 0
serverBindsAll: 1
serverBindAddress:
serverMaxPeerCapacity: 50
serverMaxNativeWaitTime: 1
clientMaxNativeWaitTime: 3
clientStatusUpdateInterval: -1
Channels: 0100000002000000
PacketBufferCapacity: 4096
MaxAllowedPacketSize: 33554432
--- !u!1 &288173824
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 288173827}
- component: {fileID: 288173826}
- component: {fileID: 288173825}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &288173825
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 288173824}
m_Enabled: 1
--- !u!20 &288173826
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 288173824}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 1
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &288173827
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 288173824}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -1}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &379082678
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 379082679}
- component: {fileID: 379082681}
- component: {fileID: 379082680}
m_Layer: 5
m_Name: PlayersPanel
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &379082679
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 379082678}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 533055204}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &379082680
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 379082678}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_RaycastTarget: 0
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &379082681
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 379082678}
m_CullTransparentMesh: 0
--- !u!1 &522137823
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 522137826}
- component: {fileID: 522137825}
- component: {fileID: 522137824}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &522137824
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 522137823}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &522137825
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 522137823}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &522137826
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 522137823}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &533055200
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 533055204}
- component: {fileID: 533055203}
- component: {fileID: 533055202}
- component: {fileID: 533055201}
m_Layer: 5
m_Name: Canvas
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &533055201
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 533055200}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
m_BlockingObjects: 0
m_BlockingMask:
serializedVersion: 2
m_Bits: 4294967295
--- !u!114 &533055202
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 533055200}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
--- !u!223 &533055203
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 533055200}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 0
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_AdditionalShaderChannelsFlag: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
--- !u!224 &533055204
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 533055200}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 379082679}
m_Father: {fileID: 0}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 0}
--- !u!1 &707756284
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 707756286}
- component: {fileID: 707756285}
m_Layer: 0
m_Name: Directional Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &707756285
Light:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 707756284}
m_Enabled: 1
serializedVersion: 10
m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_InnerSpotAngle: 21.80208
m_CookieSize: 10
m_Shadows:
m_Type: 2
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_CullingMatrixOverride:
e00: 1
e01: 0
e02: 0
e03: 0
e10: 0
e11: 1
e12: 0
e13: 0
e20: 0
e21: 0
e22: 1
e23: 0
e30: 0
e31: 0
e32: 0
e33: 1
m_UseCullingMatrixOverride: 0
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingLayerMask: 1
m_Lightmapping: 4
m_LightShadowCasterMode: 0
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
m_UseBoundingSphereOverride: 0
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &707756286
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 707756284}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 41ad25598d342f240bd8830833bfb1c5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -411,6 +411,61 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
--- !u!1 &627350787
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 627350789}
- component: {fileID: 627350788}
m_Layer: 0
m_Name: LRM - Connector
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &627350788
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 627350787}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 872fa23ef6e77334ca452ce16f6cd091, type: 3}
m_Name:
m_EditorClassIdentifier:
port: 7778
LogType: 1
DebugDisplay: 0
serverBindsAll: 1
serverBindAddress:
serverMaxPeerCapacity: 50
serverMaxNativeWaitTime: 1
clientMaxNativeWaitTime: 3
clientStatusUpdateInterval: -1
Channels: 0100000002000000
PacketBufferCapacity: 4096
MaxAllowedPacketSize: 33554432
--- !u!4 &627350789
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 627350787}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1282001518}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &664671251 --- !u!1 &664671251
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -1160,7 +1215,7 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: m_Children:
- {fileID: 1226094909} - {fileID: 1226094909}
- {fileID: 1521806212} - {fileID: 627350789}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 3 m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -1237,17 +1292,20 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7064b1b1d0671194baf55fa8d5f564d6, type: 3} m_Script: {fileID: 11500000, guid: 7064b1b1d0671194baf55fa8d5f564d6, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
clientToServerTransport: {fileID: 1521806211} clientToServerTransport: {fileID: 627350788}
serverIP: 68.174.160.78 serverIP: 127.0.0.1
serverPort: 7777 serverPort: 7777
endpointServerPort: 8080 endpointServerPort: 8080
heartBeatInterval: 3 heartBeatInterval: 3
connectOnAwake: 1 connectOnAwake: 1
authenticationKey: Secret Auth Key authenticationKey: Secret Auth Key
diconnectedFromRelay: disconnectedFromRelay:
m_PersistentCalls: m_PersistentCalls:
m_Calls: [] m_Calls: []
useNATPunch: 1 connectedToRelay:
m_PersistentCalls:
m_Calls: []
useNATPunch: 0
NATPunchtroughPort: 1 NATPunchtroughPort: 1
useLoadBalancer: 0 useLoadBalancer: 0
loadBalancerPort: 7070 loadBalancerPort: 7070
@ -1348,60 +1406,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
--- !u!1 &1521806210
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1521806212}
- component: {fileID: 1521806211}
m_Layer: 0
m_Name: LRM - Connector
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1521806211
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1521806210}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6b0fecffa3f624585964b0d0eb21b18e, type: 3}
m_Name:
m_EditorClassIdentifier:
Port: 7777
NoDelay: 1
Interval: 10
Timeout: 10000
FastResend: 2
CongestionWindow: 0
SendWindowSize: 4096
ReceiveWindowSize: 4096
debugLog: 0
statisticsGUI: 0
statisticsLog: 0
--- !u!4 &1521806212
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1521806210}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1282001518}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1600541100 --- !u!1 &1600541100
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View file

@ -1,8 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 97a3e4cddb8635c4eba1265f44d106bf guid: 97a3e4cddb8635c4eba1265f44d106bf
timeCreated: 1426602119 timeCreated: 1426602119
licenseType: Free licenseType: Store
NativeFormatImporter: NativeFormatImporter:
userData: '' userData:
assetBundleName: '' assetBundleName:
assetBundleVariant: '' assetBundleVariant:

View file

@ -77,12 +77,12 @@ TextureImporter:
bones: [] bones: []
spriteID: 09819c66a21defd49b2cfc87fea685d2 spriteID: 09819c66a21defd49b2cfc87fea685d2
vertices: [] vertices: []
indices: '' indices:
edges: [] edges: []
weights: [] weights: []
spritePackingTag: '' spritePackingTag:
pSDRemoveMatte: 0 pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0 pSDShowRemoveMatteOption: 0
userData: '' userData:
assetBundleName: '' assetBundleName:
assetBundleVariant: '' assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cc98cd95e3fb22b4eb88082706967357
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e03829cb9e647274db0f6a7b8b1b757b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,296 @@
// Ignorance 1.4.x
// Ignorance. It really kicks the Unity LLAPIs ass.
// https://github.com/SoftwareGuy/Ignorance
// -----------------
// Copyright (c) 2019 - 2020 Matt Coburn (SoftwareGuy/Coburn64)
// Ignorance Transport is licensed under the MIT license. Refer
// to the LICENSE file for more information.
using ENet;
// using NetStack.Buffers;
using System;
using System.Collections.Concurrent;
using System.Threading;
using UnityEngine;
using Event = ENet.Event; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using EventType = ENet.EventType; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using Object = System.Object; // fixes CS0104 ambigous reference between the same thing in UnityEngine
namespace IgnoranceTransport
{
public class IgnoranceClient
{
// Client connection address and port
public string ConnectAddress = "127.0.0.1";
public int ConnectPort = 7777;
// How many channels are expected
public int ExpectedChannels = 2;
// Native poll waiting time
public int PollTime = 1;
// Maximum Packet Size
public int MaximumPacketSize = 33554432;
// General Verbosity by default.
public int Verbosity = 1;
// Queues
public ConcurrentQueue<IgnoranceIncomingPacket> Incoming = new ConcurrentQueue<IgnoranceIncomingPacket>();
public ConcurrentQueue<IgnoranceOutgoingPacket> Outgoing = new ConcurrentQueue<IgnoranceOutgoingPacket>();
public ConcurrentQueue<IgnoranceCommandPacket> Commands = new ConcurrentQueue<IgnoranceCommandPacket>();
public ConcurrentQueue<IgnoranceConnectionEvent> ConnectionEvents = new ConcurrentQueue<IgnoranceConnectionEvent>();
public ConcurrentQueue<IgnoranceClientStats> StatusUpdates = new ConcurrentQueue<IgnoranceClientStats>();
public bool IsAlive => WorkerThread != null && WorkerThread.IsAlive;
private volatile bool CeaseOperation = false;
private Thread WorkerThread;
public void Start()
{
Debug.Log("IgnoranceClient.Start()");
if (WorkerThread != null && WorkerThread.IsAlive)
{
// Cannot do that.
Debug.LogError("A worker thread is already running. Cannot start another.");
return;
}
CeaseOperation = false;
ThreadParamInfo threadParams = new ThreadParamInfo()
{
Address = ConnectAddress,
Port = ConnectPort,
Channels = ExpectedChannels,
PollTime = PollTime,
PacketSizeLimit = MaximumPacketSize,
Verbosity = Verbosity
};
// Drain queues.
if (Incoming != null) while (Incoming.TryDequeue(out _)) ;
if (Outgoing != null) while (Outgoing.TryDequeue(out _)) ;
if (Commands != null) while (Commands.TryDequeue(out _)) ;
if (ConnectionEvents != null) while (ConnectionEvents.TryDequeue(out _)) ;
if (StatusUpdates != null) while (StatusUpdates.TryDequeue(out _)) ;
WorkerThread = new Thread(ThreadWorker);
WorkerThread.Start(threadParams);
Debug.Log("Client has dispatched worker thread.");
}
public void Stop()
{
Debug.Log("Telling client thread to stop, this may take a while depending on network load");
CeaseOperation = true;
}
// This runs in a seperate thread, be careful accessing anything outside of it's thread
// or you may get an AccessViolation/crash.
private void ThreadWorker(Object parameters)
{
if (Verbosity > 0)
Debug.Log("Ignorance Client: Initializing. Please stand by...");
ThreadParamInfo setupInfo;
Address clientAddress = new Address();
Peer clientPeer;
Host clientENetHost;
Event clientENetEvent;
IgnoranceClientStats icsu = default;
// Grab the setup information.
if (parameters.GetType() == typeof(ThreadParamInfo))
{
setupInfo = (ThreadParamInfo)parameters;
}
else
{
Debug.LogError("Ignorance Client: Startup failure: Invalid thread parameters. Aborting.");
return;
}
// Attempt to initialize ENet inside the thread.
if (Library.Initialize())
{
Debug.Log("Ignorance Client: ENet initialized.");
}
else
{
Debug.LogError("Ignorance Client: Failed to initialize ENet. This threads' fucked.");
return;
}
// Attempt to connect to our target.
clientAddress.SetHost(setupInfo.Address);
clientAddress.Port = (ushort)setupInfo.Port;
using (clientENetHost = new Host())
{
// TODO: Maybe try catch this
clientENetHost.Create();
clientPeer = clientENetHost.Connect(clientAddress, setupInfo.Channels);
while (!CeaseOperation)
{
bool pollComplete = false;
// Step 0: Handle commands.
while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
{
switch (commandPacket.Type)
{
default:
break;
case IgnoranceCommandType.ClientWantsToStop:
CeaseOperation = true;
break;
case IgnoranceCommandType.ClientRequestsStatusUpdate:
// Respond with statistics so far.
if (!clientPeer.IsSet)
break;
icsu.RTT = clientPeer.RoundTripTime;
icsu.BytesReceived = clientPeer.BytesReceived;
icsu.BytesSent = clientPeer.BytesSent;
icsu.PacketsReceived = clientENetHost.PacketsReceived;
icsu.PacketsSent = clientPeer.PacketsSent;
icsu.PacketsLost = clientPeer.PacketsLost;
StatusUpdates.Enqueue(icsu);
break;
}
}
// Step 1: Send out data.
// ---> Sending to Server
while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
{
// TODO: Revise this, could we tell the Peer to disconnect right here?
// Stop early if we get a client stop packet.
// if (outgoingPacket.Type == IgnorancePacketType.ClientWantsToStop) break;
int ret = clientPeer.Send(outgoingPacket.Channel, ref outgoingPacket.Payload);
if (ret < 0 && setupInfo.Verbosity > 0)
Debug.LogWarning($"Ignorance Client: ENet error code {ret} while sending packet to Peer {outgoingPacket.NativePeerId}.");
}
// Step 2:
// <----- Receive Data packets
// This loops until polling is completed. It may take a while, if it's
// a slow networking day.
while (!pollComplete)
{
Packet incomingPacket;
Peer incomingPeer;
int incomingPacketLength;
// Any events worth checking out?
if (clientENetHost.CheckEvents(out clientENetEvent) <= 0)
{
// If service time is met, break out of it.
if (clientENetHost.Service(setupInfo.PollTime, out clientENetEvent) <= 0) break;
// Poll is done.
pollComplete = true;
}
// Setup the packet references.
incomingPeer = clientENetEvent.Peer;
// Now, let's handle those events.
switch (clientENetEvent.Type)
{
case EventType.None:
default:
break;
case EventType.Connect:
ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
{
NativePeerId = incomingPeer.ID,
IP = incomingPeer.IP,
Port = incomingPeer.Port
});
break;
case EventType.Disconnect:
case EventType.Timeout:
ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
{
WasDisconnect = true
});
break;
case EventType.Receive:
// Receive event type usually includes a packet; so cache its reference.
incomingPacket = clientENetEvent.Packet;
if (!incomingPacket.IsSet)
{
if (setupInfo.Verbosity > 0)
Debug.LogWarning($"Ignorance Client: A receive event did not supply us with a packet to work with. This should never happen.");
break;
}
incomingPacketLength = incomingPacket.Length;
// Never consume more than we can have capacity for.
if (incomingPacketLength > setupInfo.PacketSizeLimit)
{
if (setupInfo.Verbosity > 0)
Debug.LogWarning($"Ignorance Client: Incoming packet is too big. My limit is {setupInfo.PacketSizeLimit} byte(s) whilest this packet is {incomingPacketLength} bytes.");
incomingPacket.Dispose();
break;
}
IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
{
Channel = clientENetEvent.ChannelID,
NativePeerId = incomingPeer.ID,
Payload = incomingPacket
};
Incoming.Enqueue(incomingQueuePacket);
break;
}
}
}
Debug.Log("Ignorance Server: Shutdown commencing, disconnecting and flushing connection.");
// Flush the client and disconnect.
clientPeer.Disconnect(0);
clientENetHost.Flush();
// Fix for client stuck in limbo, since the disconnection event may not be fired until next loop.
ConnectionEvents.Enqueue(new IgnoranceConnectionEvent()
{
WasDisconnect = true
});
}
// Deinitialize
Library.Deinitialize();
if (setupInfo.Verbosity > 0)
Debug.Log("Ignorance Client: Shutdown complete.");
}
private struct ThreadParamInfo
{
public int Channels;
public int PollTime;
public int Port;
public int PacketSizeLimit;
public int Verbosity;
public string Address;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b7b9e2c091c3d42439840a02fe700252
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,328 @@
// Ignorance 1.4.x
// Ignorance. It really kicks the Unity LLAPIs ass.
// https://github.com/SoftwareGuy/Ignorance
// -----------------
// Copyright (c) 2019 - 2020 Matt Coburn (SoftwareGuy/Coburn64)
// Ignorance Transport is licensed under the MIT license. Refer
// to the LICENSE file for more information.
using ENet;
// using NetStack.Buffers;
using System.Collections.Concurrent;
using System.Threading;
using UnityEngine;
using Event = ENet.Event; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using EventType = ENet.EventType; // fixes CS0104 ambigous reference between the same thing in UnityEngine
using Object = System.Object; // fixes CS0104 ambigous reference between the same thing in UnityEngine
namespace IgnoranceTransport
{
public class IgnoranceServer
{
// Server Properties
// - Bind Settings
public string BindAddress = "127.0.0.1";
public int BindPort = 7777;
// - Maximum allowed channels, peers, etc.
public int MaximumChannels = 2;
public int MaximumPeers = 100;
public int MaximumPacketSize = 33554432; // ENet.cs: uint maxPacketSize = 32 * 1024 * 1024 = 33554432
// - Native poll waiting time
public int PollTime = 1;
public int Verbosity = 1;
public bool IsAlive => WorkerThread != null && WorkerThread.IsAlive;
private volatile bool CeaseOperation = false;
// Queues
public ConcurrentQueue<IgnoranceIncomingPacket> Incoming = new ConcurrentQueue<IgnoranceIncomingPacket>();
public ConcurrentQueue<IgnoranceOutgoingPacket> Outgoing = new ConcurrentQueue<IgnoranceOutgoingPacket>();
public ConcurrentQueue<IgnoranceCommandPacket> Commands = new ConcurrentQueue<IgnoranceCommandPacket>();
public ConcurrentQueue<IgnoranceConnectionEvent> ConnectionEvents = new ConcurrentQueue<IgnoranceConnectionEvent>();
public ConcurrentQueue<IgnoranceConnectionEvent> DisconnectionEvents = new ConcurrentQueue<IgnoranceConnectionEvent>();
// Thread
private Thread WorkerThread;
public void Start()
{
if (WorkerThread != null && WorkerThread.IsAlive)
{
// Cannot do that.
Debug.LogError("A worker thread is already running. Cannot start another.");
return;
}
CeaseOperation = false;
ThreadParamInfo threadParams = new ThreadParamInfo()
{
Address = BindAddress,
Port = BindPort,
Peers = MaximumPeers,
Channels = MaximumChannels,
PollTime = PollTime,
PacketSizeLimit = MaximumPacketSize,
Verbosity = Verbosity
};
// Drain queues.
if (Incoming != null) while (Incoming.TryDequeue(out _)) ;
if (Outgoing != null) while (Outgoing.TryDequeue(out _)) ;
if (Commands != null) while (Commands.TryDequeue(out _)) ;
if (ConnectionEvents != null) while (ConnectionEvents.TryDequeue(out _)) ;
if (DisconnectionEvents != null) while (DisconnectionEvents.TryDequeue(out _)) ;
WorkerThread = new Thread(ThreadWorker);
WorkerThread.Start(threadParams);
// Announce
if (Verbosity > 0)
Debug.Log("Server has dispatched worker thread.");
}
public void Stop()
{
if (Verbosity > 0)
Debug.Log("Telling server thread to stop, this may take a while depending on network load");
CeaseOperation = true;
}
private void ThreadWorker(Object parameters)
{
if (Verbosity > 0)
Debug.Log("Ignorance Server: Initializing. Please stand by...");
// Thread cache items
ThreadParamInfo setupInfo;
Address serverAddress = new Address();
Host serverENetHost;
Event serverENetEvent;
Peer[] serverPeerArray;
// Grab the setup information.
if (parameters.GetType() == typeof(ThreadParamInfo))
{
setupInfo = (ThreadParamInfo)parameters;
}
else
{
Debug.LogError("Ignorance Server: Startup failure: Invalid thread parameters. Aborting.");
return;
}
// Attempt to initialize ENet inside the thread.
if (Library.Initialize())
{
Debug.Log("Ignorance Server: ENet initialized.");
}
else
{
Debug.LogError("Ignorance Server: Failed to initialize ENet. This threads' fucked.");
return;
}
// Configure the server address.
serverAddress.SetHost(setupInfo.Address);
serverAddress.Port = (ushort)setupInfo.Port;
serverPeerArray = new Peer[setupInfo.Peers];
using (serverENetHost = new Host())
{
// Create the server object.
serverENetHost.Create(serverAddress, setupInfo.Peers, setupInfo.Channels);
// Loop until we're told to cease operations.
while (!CeaseOperation)
{
// Intermission: Command Handling
while (Commands.TryDequeue(out IgnoranceCommandPacket commandPacket))
{
switch (commandPacket.Type)
{
default:
break;
// Boot a Peer off the Server.
case IgnoranceCommandType.ServerKickPeer:
uint targetPeer = commandPacket.PeerId;
if (!serverPeerArray[targetPeer].IsSet) continue;
if (setupInfo.Verbosity > 0)
Debug.Log($"Ignorance Server: Booting Peer {targetPeer} off this server instance.");
IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent()
{
WasDisconnect = true,
NativePeerId = targetPeer
};
DisconnectionEvents.Enqueue(iced);
// Disconnect and reset the peer array's entry for that peer.
serverPeerArray[targetPeer].DisconnectNow(0);
serverPeerArray[targetPeer] = default;
break;
}
}
// Step One:
// ---> Sending to peers
while (Outgoing.TryDequeue(out IgnoranceOutgoingPacket outgoingPacket))
{
// Only create a packet if the server knows the peer.
if (serverPeerArray[outgoingPacket.NativePeerId].IsSet)
{
int ret = serverPeerArray[outgoingPacket.NativePeerId].Send(outgoingPacket.Channel, ref outgoingPacket.Payload);
if (ret < 0 && setupInfo.Verbosity > 0)
Debug.LogWarning($"Ignorance Server: ENet error code {ret} while sending packet to Peer {outgoingPacket.NativePeerId}.");
}
else
{
// A peer might have disconnected, this is OK - just log the packet if set to paranoid.
if (setupInfo.Verbosity > 1)
Debug.LogWarning("Ignorance Server: Can't send packet, a native peer object is not set. This may be normal if the Peer has disconnected before this send cycle.");
}
}
// Step 2
// <--- Receiving from peers
bool pollComplete = false;
while (!pollComplete)
{
Packet incomingPacket;
Peer incomingPeer;
int incomingPacketLength;
// Any events happening?
if (serverENetHost.CheckEvents(out serverENetEvent) <= 0)
{
// If service time is met, break out of it.
if (serverENetHost.Service(setupInfo.PollTime, out serverENetEvent) <= 0) break;
pollComplete = true;
}
// Setup the packet references.
incomingPeer = serverENetEvent.Peer;
switch (serverENetEvent.Type)
{
// Idle.
case EventType.None:
default:
break;
// Connection Event.
case EventType.Connect:
if (setupInfo.Verbosity > 1)
Debug.Log("Ignorance Server: Here comes a new Peer connection.");
IgnoranceConnectionEvent ice = new IgnoranceConnectionEvent()
{
NativePeerId = incomingPeer.ID,
IP = incomingPeer.IP,
Port = incomingPeer.Port
};
ConnectionEvents.Enqueue(ice);
// Assign a reference to the Peer.
serverPeerArray[incomingPeer.ID] = incomingPeer;
break;
// Disconnect/Timeout. Mirror doesn't care if it's either, so we lump them together.
case EventType.Disconnect:
case EventType.Timeout:
if (!serverPeerArray[incomingPeer.ID].IsSet) break;
if (setupInfo.Verbosity > 1)
Debug.Log("Ignorance Server: Peer disconnection.");
IgnoranceConnectionEvent iced = new IgnoranceConnectionEvent()
{
WasDisconnect = true,
NativePeerId = incomingPeer.ID
};
DisconnectionEvents.Enqueue(iced);
// Reset the peer array's entry for that peer.
serverPeerArray[incomingPeer.ID] = default;
break;
case EventType.Receive:
// Receive event type usually includes a packet; so cache its reference.
incomingPacket = serverENetEvent.Packet;
if (!incomingPacket.IsSet)
{
if (setupInfo.Verbosity > 0)
Debug.LogWarning($"Ignorance Server: A receive event did not supply us with a packet to work with. This should never happen.");
break;
}
incomingPacketLength = incomingPacket.Length;
// Firstly check if the packet is too big. If it is, do not process it - drop it.
if (incomingPacketLength > setupInfo.PacketSizeLimit)
{
if (setupInfo.Verbosity > 0)
Debug.LogWarning($"Ignorance Server: Incoming packet is too big. My limit is {setupInfo.PacketSizeLimit} byte(s) whilest this packet is {incomingPacketLength} bytes.");
incomingPacket.Dispose();
break;
}
IgnoranceIncomingPacket incomingQueuePacket = new IgnoranceIncomingPacket
{
Channel = serverENetEvent.ChannelID,
NativePeerId = incomingPeer.ID,
Payload = incomingPacket,
};
// Enqueue.
Incoming.Enqueue(incomingQueuePacket);
break;
}
}
}
if (Verbosity > 0)
Debug.Log("Ignorance Server: Shutdown commencing, flushing connections.");
// Cleanup and flush everything.
serverENetHost.Flush();
// Kick everyone.
for (int i = 0; i < serverPeerArray.Length; i++)
{
if (!serverPeerArray[i].IsSet) continue;
serverPeerArray[i].DisconnectNow(0);
}
}
// Flush again to ensure ENet gets those Disconnection stuff out.
// May not be needed; better to err on side of caution
if (setupInfo.Verbosity > 0)
Debug.Log("Ignorance Server: Shutdown complete.");
Library.Deinitialize();
}
private struct ThreadParamInfo
{
public int Channels;
public int Peers;
public int PollTime;
public int Port;
public int PacketSizeLimit;
public int Verbosity;
public string Address;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1069f42b88a4adb4ab1990cec4949343
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 12f903db684732e45b130ad56f7c86c1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 12a7875e95f5ebb4a9b58390441dd933
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0995e08af14888348b42ecaa6eb21544
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,83 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
namespace IgnoranceTransport
{
/// <summary>
/// Adds the given define symbols to PlayerSettings define symbols.
/// Just add your own define symbols to the Symbols property at the below.
/// </summary>
[InitializeOnLoad]
public class AddIgnoranceDefine : Editor
{
private static string existingDefines = string.Empty;
/// <summary>
/// Symbols that will be added to the editor
/// </summary>
public static readonly string[] Symbols = new string[] {
"IGNORANCE", // Ignorance exists
"IGNORANCE_1", // Major version
"IGNORANCE_1_4" // Major and minor version
};
/// <summary>
/// Do not remove these symbols
/// </summary>
public static readonly string[] DoNotRemoveTheseSymbols = new string[]
{
"IGNORANCE_NO_UPNP",
"IGNORANCE_MIRROR_POLLING"
};
/// <summary>
/// Add define symbols as soon as Unity gets done compiling.
/// </summary>
static AddIgnoranceDefine()
{
// Get the current scripting defines
string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
if (existingDefines == definesString)
{
// 1.2.6: There is no need to apply the changes, return.
return;
}
// Convert the string to a list
List<string> allDefines = definesString.Split(';').ToList();
// Remove any old version defines from previous installs
allDefines.RemoveAll(IsSafeToRemove);
// x => x.StartsWith("IGNORANCE") && !DoesSymbolExistInBlacklist(x));
// Add any symbols that weren't already in the list
allDefines.AddRange(Symbols.Except(allDefines));
string newDefines = string.Join(";", allDefines.ToArray());
PlayerSettings.SetScriptingDefineSymbolsForGroup(
EditorUserBuildSettings.selectedBuildTargetGroup,
newDefines
);
existingDefines = newDefines;
}
// 1.2.4: Workaround to stop things from eating custom IGNORANCE_ symbols
static bool DoesSymbolExistInBlacklist(string symbol)
{
foreach(string s in DoNotRemoveTheseSymbols)
{
if (s == symbol.Trim()) return true;
}
return false;
}
static bool IsSafeToRemove (string input)
{
if (input.StartsWith("IGNORANCE") && !DoesSymbolExistInBlacklist(input)) return true;
return false;
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed8acbde141f2d8469baf2142712de9e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,44 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
namespace IgnoranceTransport
{
public class IgnoranceToolbox
{
#pragma warning disable IDE0051
[MenuItem("Ignorance/Mirror/Switch Update Method")]
public static void SwitchIgnoranceUpdateMethod ()
{
}
[MenuItem("Ignorance/Debug/Reveal ENet Native Library Name")]
public static void RevealEnetLibraryName()
{
EditorUtility.DisplayDialog("Enet Library Name", $"Use this for debugging.\nYour platform expects the native Enet library to be called: {ENet.Native.nativeLibraryName}", "Got it");
}
[MenuItem("Ignorance/RTFM/Github Repository")]
private static void LaunchGithubRepo()
{
UnityEngine.Application.OpenURL("https://github.com/SoftwareGuy/Ignorance");
}
[MenuItem("Ignorance/RTFM/Github Issue Tracker")]
private static void LaunchGithubIssueTracker()
{
UnityEngine.Application.OpenURL("https://github.com/SoftwareGuy/Ignorance/issues");
}
[MenuItem("Ignorance/RTFM/ENet-CSharp Fork")]
private static void LaunchENetCSharpForkRepo()
{
UnityEngine.Application.OpenURL("https://github.com/SoftwareGuy/ENet-CSharp");
}
#pragma warning restore
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1fdecc996313d614ca16214d4e2b9162
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,746 @@
// Ignorance 1.4.x
// Ignorance. It really kicks the Unity LLAPIs ass.
// https://github.com/SoftwareGuy/Ignorance
// -----------------
// Copyright (c) 2019 - 2020 Matt Coburn (SoftwareGuy/Coburn64)
// Ignorance Transport is licensed under the MIT license. Refer
// to the LICENSE file for more information.
// -----------------
// Ignorance Experimental (New) Version
// -----------------
using ENet;
using Mirror;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace IgnoranceTransport
{
[DisallowMultipleComponent]
public class Ignorance : Transport
{
#region Inspector options
public int port = 7777;
[Header("Debug & Logging Configuration")]
[Tooltip("How verbose do you want Ignorance to be?")]
public IgnoranceLogType LogType = IgnoranceLogType.Standard;
[Tooltip("Uses OnGUI to present you with statistics for Server and Client backend instances.")]
public bool DebugDisplay = false;
[Header("Server Configuration")]
[Tooltip("Should the server bind to all interfaces?")]
public bool serverBindsAll = true;
[Tooltip("This is only used if Server Binds All is unticked.")]
public string serverBindAddress = string.Empty;
[Tooltip("This tells ENet how many Peer slots to create. Helps performance, avoids looping over huge native arrays. Recommended: Max Mirror players, rounded to nearest 10. (Example: 16 -> 20).")]
public int serverMaxPeerCapacity = 50;
[Tooltip("How long ENet waits in native world. The higher this value, the more CPU usage. Lower values may/may not impact performance at high packet load.")]
public int serverMaxNativeWaitTime = 1;
[Header("Client Configuration")]
[Tooltip("How long ENet waits in native world. The higher this value, the more CPU usage used. This is for the client, unlike the one above. Higher value probably trades CPU for more responsive networking.")]
public int clientMaxNativeWaitTime = 3;
[Tooltip("Interval between asking ENet for client status updates. Set to -1 to disable.")]
public int clientStatusUpdateInterval = -1;
[Header("Channel Configuration")]
[Tooltip("You must define your channels in the array shown here, otherwise ENet will not know what channel delivery type to use.")]
public IgnoranceChannelTypes[] Channels;
[Header("Low-level Tweaking")]
[Tooltip("Used internally to keep allocations to a minimum. This is how much memory will be consumed by the packet buffer on startup, and then reused.")]
public int PacketBufferCapacity = 4096;
[Tooltip("For UDP based protocols, it's best to keep your data under the safe MTU of 1200 bytes. You can increase this, however beware this may open you up to allocation attacks.")]
public int MaxAllowedPacketSize = 33554432;
#endregion
#region Public Statistics
public IgnoranceClientStats ClientStatistics;
#endregion
#if MIRROR_26_0_OR_NEWER
public override bool Available()
{
// Ignorance is not available for Unity WebGL, the PS4 (no dev kit to confirm) or Switch (port exists but I have no access to said code).
// Ignorance is available for most other operating systems.
#if (UNITY_WEBGL || UNITY_PS4 || UNITY_SWITCH)
return false;
#else
return true;
#endif
}
public void Awake()
{
if (LogType != IgnoranceLogType.Nothing)
Debug.Log($"Thanks for using Ignorance {IgnoranceInternals.Version}. Keep up to date, report bugs and support the developer at https://github.com/SoftwareGuy/Ignorance!");
}
public override string ToString()
{
return $"Ignorance v{IgnoranceInternals.Version}";
}
public override void ClientConnect(string address)
{
ClientState = ConnectionState.Connecting;
cachedConnectionAddress = address;
// Initialize.
InitializeClientBackend();
// Get going.
ignoreDataPackets = false;
// Start!
Client.Start();
}
public override void ClientConnect(Uri uri)
{
if (uri.Scheme != IgnoranceInternals.Scheme)
throw new ArgumentException($"You used an invalid URI: {uri}. Please use {IgnoranceInternals.Scheme}://host:port instead", nameof(uri));
if (!uri.IsDefaultPort)
// Set the communication port to the one specified.
port = uri.Port;
// Pass onwards to the proper handler.
ClientConnect(uri.Host);
}
public override bool ClientConnected() => ClientState == ConnectionState.Connected;
public override void ClientDisconnect()
{
if (Client != null)
Client.Stop();
// TODO: Figure this one out to see if it's related to a race condition.
// Maybe experiment with a while loop to pause main thread when disconnecting,
// since client might not stop on a dime.
// while(Client.IsAlive) ;
// v1.4.0b1: Probably fixed in IgnoranceClient.cs; need further testing.
// ignoreDataPackets = true;
ClientState = ConnectionState.Disconnected;
}
#if !MIRROR_37_0_OR_NEWER
public override void ClientSend(int channelId, ArraySegment<byte> segment)
#else
// v1.4.0b6: Mirror rearranged the ClientSend params, so we need to apply a fix for that or
// we end up using the obsoleted version. The obsolete version isn't a fatal error, but
// it's best to stick with the new structures.
public override void ClientSend(ArraySegment<byte> segment, int channelId)
#endif
{
if (Client == null)
{
Debug.LogError("Client object is null, this shouldn't really happen but it did...");
return;
}
if (channelId < 0 || channelId > Channels.Length)
{
Debug.LogError("Channel ID is out of bounds.");
return;
}
// Create our struct...
Packet clientOutgoingPacket = default;
int byteCount = segment.Count;
int byteOffset = segment.Offset;
// Set our desired flags...
PacketFlags desiredFlags = (PacketFlags)Channels[channelId];
// Warn if over recommended MTU...
bool flagsSet = (desiredFlags & ReliableOrUnreliableFragmented) > 0;
if (LogType != IgnoranceLogType.Nothing && byteCount > 1200 && !flagsSet)
Debug.LogWarning($"Warning: Client trying to send a Unreliable packet bigger than the recommended ENet 1200 byte MTU ({byteCount} > 1200). ENet will force Reliable Fragmented delivery.");
// Create the packet.
clientOutgoingPacket.Create(segment.Array, byteOffset, byteCount + byteOffset, desiredFlags);
// byteCount
// Enqueue the packet.
IgnoranceOutgoingPacket dispatchPacket = new IgnoranceOutgoingPacket
{
Channel = (byte)channelId,
Payload = clientOutgoingPacket
};
// Pass the packet onto the thread for dispatch.
Client.Outgoing.Enqueue(dispatchPacket);
}
public override bool ServerActive()
{
// Very simple check.
return Server != null && Server.IsAlive;
}
#if !MIRROR_37_0_OR_NEWER
// Workaround for legacy Mirror versions.
public override bool ServerDisconnect(int connectionId) => ServerDisconnectLegacy(connectionId);
#else
public override void ServerDisconnect(int connectionId)
{
if (Server == null)
{
Debug.LogError("Cannot enqueue kick packet; our Server object is null. Something has gone wrong.");
// Return here because otherwise we will get a NRE when trying to enqueue the kick packet.
return;
}
IgnoranceCommandPacket kickPacket = new IgnoranceCommandPacket
{
Type = IgnoranceCommandType.ServerKickPeer,
PeerId = (uint)connectionId - 1 // ENet's native peer ID will be ConnID - 1
};
// Pass the packet onto the thread for dispatch.
Server.Commands.Enqueue(kickPacket);
}
#endif
public override string ServerGetClientAddress(int connectionId)
{
if (ConnectionLookupDict.TryGetValue(connectionId, out PeerConnectionData details))
return $"{details.IP}:{details.Port}";
return "(unavailable)";
}
#if !MIRROR_37_0_OR_NEWER
public override void ServerSend(int connectionId, int channelId, ArraySegment<byte> segment)
#else
// v1.4.0b6: Mirror rearranged the ServerSend params, so we need to apply a fix for that or
// we end up using the obsoleted version. The obsolete version isn't a fatal error, but
// it's best to stick with the new structures.
public override void ServerSend(int connectionId, ArraySegment<byte> segment, int channelId)
#endif
{
// Debug.Log($"ServerSend({connectionId}, {channelId}, <{segment.Count} byte segment>)");
if (Server == null)
{
Debug.LogError("Cannot enqueue data packet; our Server object is null. Something has gone wrong.");
return;
}
if (channelId < 0 || channelId > Channels.Length)
{
Debug.LogError("Channel ID is out of bounds.");
return;
}
// Packet Struct
Packet serverOutgoingPacket = default;
int byteCount = segment.Count;
int byteOffset = segment.Offset;
PacketFlags desiredFlags = (PacketFlags)Channels[channelId];
// Warn if over recommended MTU
bool flagsSet = (desiredFlags & ReliableOrUnreliableFragmented) > 0;
if (LogType != IgnoranceLogType.Nothing && byteCount > 1200 && !flagsSet)
Debug.LogWarning($"Warning: Server trying to send a Unreliable packet bigger than the recommended ENet 1200 byte MTU ({byteCount} > 1200). ENet will force Reliable Fragmented delivery.");
// Create the packet.
serverOutgoingPacket.Create(segment.Array, byteOffset, byteCount + byteOffset, (PacketFlags)Channels[channelId]);
// Enqueue the packet.
IgnoranceOutgoingPacket dispatchPacket = new IgnoranceOutgoingPacket
{
Channel = (byte)channelId,
NativePeerId = (uint)connectionId - 1, // ENet's native peer ID will be ConnID - 1
Payload = serverOutgoingPacket
};
Server.Outgoing.Enqueue(dispatchPacket);
}
public override void ServerStart()
{
if (LogType != IgnoranceLogType.Nothing)
Debug.Log("Ignorance Server Instance starting up...");
InitializeServerBackend();
Server.Start();
}
public override void ServerStop()
{
if (Server != null)
{
if (LogType != IgnoranceLogType.Nothing)
Debug.Log("Ignorance Server Instance shutting down...");
Server.Stop();
}
ConnectionLookupDict.Clear();
}
public override Uri ServerUri()
{
UriBuilder builder = new UriBuilder
{
Scheme = IgnoranceInternals.Scheme,
Host = serverBindAddress,
Port = port
};
return builder.Uri;
}
public override void Shutdown()
{
// TODO: Nothing needed here?
}
// Check to ensure channels 0 and 1 mimic LLAPI. Override this at your own risk.
private void OnValidate()
{
if (Channels != null && Channels.Length >= 2)
{
// Check to make sure that Channel 0 and 1 are correct.
if (Channels[0] != IgnoranceChannelTypes.Reliable)
{
Debug.LogWarning("Please do not modify Ignorance Channel 0. The channel will be reset to Reliable delivery. If you need a channel with a different delivery, define and use it instead.");
Channels[0] = IgnoranceChannelTypes.Reliable;
}
if (Channels[1] != IgnoranceChannelTypes.Unreliable)
{
Debug.LogWarning("Please do not modify Ignorance Channel 1. The channel will be reset to Unreliable delivery. If you need a channel with a different delivery, define and use it instead.");
Channels[1] = IgnoranceChannelTypes.Unreliable;
}
}
else
{
Debug.LogWarning("Invalid Channels setting, fixing. If you've just added Ignorance to your NetworkManager GameObject, seeing this message is normal.");
Channels = new IgnoranceChannelTypes[2]
{
IgnoranceChannelTypes.Reliable,
IgnoranceChannelTypes.Unreliable
};
}
// ENet only supports a maximum of 32MB packet size.
if (MaxAllowedPacketSize > 33554432)
MaxAllowedPacketSize = 33554432;
}
private void InitializeServerBackend()
{
if (Server == null)
{
Debug.LogWarning("IgnoranceServer reference for Server mode was null. This shouldn't happen, but to be safe we'll reinitialize it.");
Server = new IgnoranceServer();
}
// Set up the new IgnoranceServer reference.
if (serverBindsAll)
// MacOS is special. It's also a massive thorn in my backside.
Server.BindAddress = IgnoranceInternals.BindAllMacs;
else
// Use the supplied bind address.
Server.BindAddress = serverBindAddress;
// Sets port, maximum peers, max channels, the server poll time, maximum packet size and verbosity.
Server.BindPort = port;
Server.MaximumPeers = serverMaxPeerCapacity;
Server.MaximumChannels = Channels.Length;
Server.PollTime = serverMaxNativeWaitTime;
Server.MaximumPacketSize = MaxAllowedPacketSize;
Server.Verbosity = (int)LogType;
// Initializes the packet buffer.
// Allocates once, that's it.
if (InternalPacketBuffer == null)
InternalPacketBuffer = new byte[PacketBufferCapacity];
}
private void InitializeClientBackend()
{
if (Client == null)
{
Debug.LogWarning("Ignorance: IgnoranceClient reference for Client mode was null. This shouldn't happen, but to be safe we'll reinitialize it.");
Client = new IgnoranceClient();
}
// Sets address, port, channels to expect, verbosity, the server poll time and maximum packet size.
Client.ConnectAddress = cachedConnectionAddress;
Client.ConnectPort = port;
Client.ExpectedChannels = Channels.Length;
Client.PollTime = clientMaxNativeWaitTime;
Client.MaximumPacketSize = MaxAllowedPacketSize;
Client.Verbosity = (int)LogType;
// Initializes the packet buffer.
// Allocates once, that's it.
if (InternalPacketBuffer == null)
InternalPacketBuffer = new byte[PacketBufferCapacity];
}
private void ProcessServerPackets()
{
IgnoranceIncomingPacket incomingPacket;
IgnoranceConnectionEvent connectionEvent;
int adjustedConnectionId;
Packet payload;
// Incoming connection events.
while (Server.ConnectionEvents.TryDequeue(out connectionEvent))
{
adjustedConnectionId = (int)connectionEvent.NativePeerId + 1;
if (LogType == IgnoranceLogType.Verbose)
Debug.Log($"Processing a server connection event from ENet native peer {connectionEvent.NativePeerId}. This peer would be Mirror ConnID {adjustedConnectionId}.");
// TODO: Investigate ArgumentException: An item with the same key has already been added. Key: <id>
ConnectionLookupDict.Add(adjustedConnectionId, new PeerConnectionData
{
NativePeerId = connectionEvent.NativePeerId,
IP = connectionEvent.IP,
Port = connectionEvent.Port
});
OnServerConnected?.Invoke(adjustedConnectionId);
}
// Handle incoming data packets.
// Console.WriteLine($"Server Incoming Queue is {Server.Incoming.Count}");
while (Server.Incoming.TryDequeue(out incomingPacket))
{
adjustedConnectionId = (int)incomingPacket.NativePeerId + 1;
payload = incomingPacket.Payload;
int length = payload.Length;
ArraySegment<byte> dataSegment;
// Copy to working buffer and dispose of it.
if (length > InternalPacketBuffer.Length)
{
byte[] oneFreshNTastyGcAlloc = new byte[length];
payload.CopyTo(oneFreshNTastyGcAlloc);
dataSegment = new ArraySegment<byte>(oneFreshNTastyGcAlloc, 0, length);
}
else
{
payload.CopyTo(InternalPacketBuffer);
dataSegment = new ArraySegment<byte>(InternalPacketBuffer, 0, length);
}
payload.Dispose();
OnServerDataReceived?.Invoke(adjustedConnectionId, dataSegment, incomingPacket.Channel);
// Some messages can disable the transport
// If the transport was disabled by any of the messages, we have to break out of the loop and wait until we've been re-enabled.
if (!enabled)
break;
}
// Disconnection events.
while (Server.DisconnectionEvents.TryDequeue(out IgnoranceConnectionEvent disconnectionEvent))
{
adjustedConnectionId = (int)disconnectionEvent.NativePeerId + 1;
if (LogType == IgnoranceLogType.Verbose)
Debug.Log($"ProcessServerPackets fired; handling disconnection event from native peer {disconnectionEvent.NativePeerId}.");
ConnectionLookupDict.Remove(adjustedConnectionId);
// Invoke Mirror handler.
OnServerDisconnected?.Invoke(adjustedConnectionId);
}
}
private void ProcessClientPackets()
{
IgnoranceIncomingPacket incomingPacket;
IgnoranceCommandPacket commandPacket;
IgnoranceClientStats clientStats;
Packet payload;
IgnoranceConnectionEvent connectionEvent;
// Handle connection events.
while (Client.ConnectionEvents.TryDequeue(out connectionEvent))
{
if (LogType == IgnoranceLogType.Verbose)
Debug.Log($"ProcessClientConnectionEvents fired: processing a client ConnectionEvents queue item.");
if (connectionEvent.WasDisconnect)
{
// Disconnected from server.
ClientState = ConnectionState.Disconnected;
if (LogType != IgnoranceLogType.Nothing)
Debug.Log($"Ignorance Client has been disconnected from server.");
ignoreDataPackets = true;
OnClientDisconnected?.Invoke();
}
else
{
// Connected to server.
ClientState = ConnectionState.Connected;
if (LogType != IgnoranceLogType.Nothing)
Debug.Log($"Ignorance Client successfully connected to server at address {connectionEvent.IP}:{connectionEvent.Port}");
ignoreDataPackets = false;
OnClientConnected?.Invoke();
}
}
// Now handle the incoming messages.
while (Client.Incoming.TryDequeue(out incomingPacket))
{
// Temporary fix: if ENet thread is too fast for Mirror, then ignore the packet.
// This is seen sometimes if you stop the client and there's still stuff in the queue.
if (ignoreDataPackets)
{
if (LogType == IgnoranceLogType.Verbose)
Debug.Log("ProcessClientPackets cycle skipped; ignoring data packet");
break;
}
// Otherwise client recieved data, advise Mirror.
// print($"Byte array: {incomingPacket.RentedByteArray.Length}. Packet Length: {incomingPacket.Length}");
payload = incomingPacket.Payload;
int length = payload.Length;
ArraySegment<byte> dataSegment;
// Copy to working buffer and dispose of it.
if (length > InternalPacketBuffer.Length)
{
// Unity's favourite: A fresh 'n' tasty GC Allocation!
byte[] oneFreshNTastyGcAlloc = new byte[length];
payload.CopyTo(oneFreshNTastyGcAlloc);
dataSegment = new ArraySegment<byte>(oneFreshNTastyGcAlloc, 0, length);
}
else
{
payload.CopyTo(InternalPacketBuffer);
dataSegment = new ArraySegment<byte>(InternalPacketBuffer, 0, length);
}
payload.Dispose();
OnClientDataReceived?.Invoke(dataSegment, incomingPacket.Channel);
// Some messages can disable the transport
// If the transport was disabled by any of the messages, we have to break out of the loop and wait until we've been re-enabled.
if (!enabled)
break;
}
// Step 3: Handle other commands.
while (Client.Commands.TryDequeue(out commandPacket))
{
switch (commandPacket.Type)
{
// ...
default:
break;
}
}
// Step 4: Handle status updates.
if (Client.StatusUpdates.TryDequeue(out clientStats))
{
ClientStatistics = clientStats;
}
}
#region Main Thread Processing and Polling
// Ignorance 1.4.0b5: To use Mirror's polling or not use Mirror's polling, that is up to the developer to decide
#if !IGNORANCE_MIRROR_POLLING
// IMPORTANT: Set Ignorance' execution order before everything else. Yes, that's -32000 !!
// This ensures it has priority over other things.
// FixedUpdate can be called many times per frame.
// Once we've handled stuff, we set a flag so that we don't poll again for this frame.
private bool fixedUpdateCompletedWork;
public void FixedUpdate()
{
if (!enabled) return;
if (fixedUpdateCompletedWork) return;
ProcessAndExecuteAllPackets();
// Flip the bool to signal we've done our work.
fixedUpdateCompletedWork = true;
}
// Normally, Mirror blocks Update() due to poor design decisions...
// But thanks to Vincenzo, we've found a way to bypass that block.
// Update is called once per frame. We don't have to worry about this shit now.
public new void Update()
{
if (!enabled) return;
// Process what FixedUpdate missed, only if the boolean is not set.
if (!fixedUpdateCompletedWork)
ProcessAndExecuteAllPackets();
// Flip back the bool, so it can be reset.
fixedUpdateCompletedWork = false;
}
// Processes and Executes All Packets.
private void ProcessAndExecuteAllPackets()
{
// Process Server Events...
if (Server.IsAlive)
ProcessServerPackets();
// Process Client Events...
if (Client.IsAlive)
{
ProcessClientPackets();
if (ClientState == ConnectionState.Connected && clientStatusUpdateInterval > -1)
{
statusUpdateTimer += Time.deltaTime;
if (statusUpdateTimer >= clientStatusUpdateInterval)
{
Client.Commands.Enqueue(new IgnoranceCommandPacket { Type = IgnoranceCommandType.ClientRequestsStatusUpdate });
statusUpdateTimer = 0f;
}
}
}
}
#else
// This section will be compiled in instead if you enable IGNORANCE_MIRROR_POLLING.
public override void ServerEarlyUpdate() {
// This is used by Mirror to consume the incoming server packets.
if (!enabled) return;
// Process Server Events...
if (Server.IsAlive)
ProcessServerPackets();
}
public override void ClientEarlyUpdate() {
// This is used by Mirror to consume the incoming client packets.
if(!enabled) return;
if(Client.IsAlive)
{
ProcessClientPackets();
if (ClientState == ConnectionState.Connected && clientStatusUpdateInterval > -1)
{
statusUpdateTimer += Time.deltaTime;
if (statusUpdateTimer >= clientStatusUpdateInterval)
{
Client.Commands.Enqueue(new IgnoranceCommandPacket { Type = IgnoranceCommandType.ClientRequestsStatusUpdate });
statusUpdateTimer = 0f;
}
}
}
}
/*
public override void ClientLateUpdate() {
// This is used by Mirror to send out the outgoing client packets.
if (!enabled) return;
}
public override void ServerLateUpdate() {
// This is used by Mirror to send out the outgoing server packets.
if (!enabled) return;
}
*/
#endif
#endregion
#region Debug
private void OnGUI()
{
if (DebugDisplay)
GUI.Box(new Rect(
new Vector2(32, Screen.height - 240), new Vector2(200, 160)),
"-- CLIENT --\n" +
$"State: {ClientState}\n" +
$"Incoming Queue: {Client.Incoming.Count}\n" +
$"Outgoing Queue: {Client.Outgoing.Count}\n\n" +
"-- SERVER --\n" +
$"Incoming Queue: {Server.Incoming.Count}\n" +
$"Outgoing Queue: {Server.Outgoing.Count}\n" +
$"ConnEvent Queue: {Server.ConnectionEvents.Count}"
);
}
#endregion
public override int GetMaxPacketSize(int channelId = 0) => MaxAllowedPacketSize;
// UDP Recommended Max MTU = 1200.
public override int GetMaxBatchSize(int channelId) {
bool isFragmentedAlready = ((PacketFlags)Channels[channelId] & ReliableOrUnreliableFragmented) > 0;
return isFragmentedAlready ? MaxAllowedPacketSize : 1200;
}
#region Internals
private bool ignoreDataPackets;
private string cachedConnectionAddress = string.Empty;
private IgnoranceServer Server = new IgnoranceServer();
private IgnoranceClient Client = new IgnoranceClient();
private Dictionary<int, PeerConnectionData> ConnectionLookupDict = new Dictionary<int, PeerConnectionData>();
private enum ConnectionState { Connecting, Connected, Disconnecting, Disconnected }
private ConnectionState ClientState = ConnectionState.Disconnected;
private byte[] InternalPacketBuffer;
private const PacketFlags ReliableOrUnreliableFragmented = PacketFlags.Reliable | PacketFlags.UnreliableFragmented;
private float statusUpdateTimer = 0f;
#endregion
#region Legacy Overrides
#if !MIRROR_37_0_OR_NEWER
public bool ServerDisconnectLegacy(int connectionId)
{
if (Server == null)
{
Debug.LogError("Cannot enqueue kick packet; our Server object is null. Something has gone wrong.");
// Return here because otherwise we will get a NRE when trying to enqueue the kick packet.
return false;
}
IgnoranceCommandPacket kickPacket = new IgnoranceCommandPacket
{
Type = IgnoranceCommandType.ServerKickPeer,
PeerId = (uint)connectionId - 1 // ENet's native peer ID will be ConnID - 1
};
// Pass the packet onto the thread for dispatch.
Server.Commands.Enqueue(kickPacket);
return true;
}
#endif
#endregion
#endif
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 872fa23ef6e77334ca452ce16f6cd091
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -32000
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,94 @@
using System;
using ENet;
namespace IgnoranceTransport
{
// Snipped from the transport files, as this will help
// me keep things up to date.
[Serializable]
public enum IgnoranceChannelTypes
{
Reliable = PacketFlags.Reliable, // TCP Emulation.
ReliableUnsequenced = PacketFlags.Reliable | PacketFlags.Unsequenced, // TCP Emulation, but no sequencing.
Unreliable = PacketFlags.Unsequenced, // Pure UDP.
UnreliableFragmented = PacketFlags.UnreliableFragmented, // Pure UDP, but fragmented.
UnreliableSequenced = PacketFlags.None, // Pure UDP, but sequenced.
Unthrottled = PacketFlags.Unthrottled, // Apparently ENet's version of Taco Bell.
}
public class IgnoranceInternals
{
public const string Version = "1.4.0b6";
public const string Scheme = "enet";
public const string BindAllIPv4 = "0.0.0.0";
public const string BindAllMacs = "::0";
}
public enum IgnoranceLogType
{
Nothing,
Standard,
Verbose
}
// Struct optimized for cache efficiency. (Thanks Vincenzo!)
public struct IgnoranceIncomingPacket
{
public byte Channel;
public uint NativePeerId;
public Packet Payload;
}
// Struct optimized for cache efficiency. (Thanks Vincenzo!)
public struct IgnoranceOutgoingPacket
{
public byte Channel;
public uint NativePeerId;
public Packet Payload;
}
// Struct optimized for cache efficiency. (Thanks Vincenzo!)
public struct IgnoranceConnectionEvent
{
public bool WasDisconnect;
public ushort Port;
public uint NativePeerId;
public string IP;
}
public struct IgnoranceCommandPacket
{
public IgnoranceCommandType Type;
public uint PeerId;
}
public struct IgnoranceClientStats
{
// Stats only - may not always be used!
public uint RTT;
public ulong BytesReceived;
public ulong BytesSent;
public ulong PacketsReceived;
public ulong PacketsSent;
public ulong PacketsLost;
}
public enum IgnoranceCommandType
{
// Client
ClientWantsToStop,
ClientRequestsStatusUpdate,
// ENet internal
ResponseToClientStatusRequest,
// Server
ServerKickPeer
}
// TODO: Optimize struct for Cache performance.
public struct PeerConnectionData
{
public ushort Port;
public uint NativePeerId;
public string IP;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b2d1f7f7d9d3d64297755419f6ab925
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e8bd04b9965420e40ac911fbf4294e1c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c90c88052305a054d87177362f63dea8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e4a42b5855436864693138f74335c094
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,111 @@
fileFormatVersion: 2
guid: 4b3abd2268dea254da11190b00d16051
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: ARM64
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: LinuxUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
WebGL: WebGL
second:
enabled: 0
settings: {}
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bfbaf4fbcf8987e4585ca666e28f4871
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: e3ce4b8600e09d74ead46137ba184d01
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: LinuxUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b3486c84aaebff4489e2e11f5bd3030f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,80 @@
fileFormatVersion: 2
guid: ba78b07719f786c4cae4c52b9528903f
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 0
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 1
settings:
CPU: x86
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8e3ca9b41c9f4064581a6b56ae549a9c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,97 @@
fileFormatVersion: 2
guid: f2bd341c8082ddd47b4b5cc9bfdf2332
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux: 1
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXUniversal: 1
Exclude WebGL: 1
Exclude Win: 0
Exclude Win64: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: x86_64
DefaultValueInitialized: true
OS: Linux
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
- first:
Standalone: LinuxUniversal
second:
enabled: 1
settings:
CPU: x86_64
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8837cb1a7320b8b4f824a02e23f4a545
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
This is a Windows x64 build of ENet-CSharp.
If you require a version of ENet for 32 Bit computer systems (ie. Windows 7/8/10 32Bit) then please get in touch, or you can install the requirements yourself and compile it using ENet-CSharp's MSBuild-based build system. Get in touch if you want me to compile them for you, but keep in mind that I do not support them when reporting bugs.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 09ee288deb259474c819a5e3daf54b80
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,111 @@
fileFormatVersion: 2
guid: cc98033c6bc234a419ccd053e7173781
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
'': Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 0
Exclude Linux: 0
Exclude Linux64: 0
Exclude LinuxUniversal: 0
Exclude OSXUniversal: 0
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 0
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: None
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 1
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: x86_64
- first:
Standalone: LinuxUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
WebGL: WebGL
second:
enabled: 0
settings: {}
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7edc275f3670f4251b90301cbb9f7413
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,80 @@
fileFormatVersion: 2
guid: 1485de7d76884a64bac00df01454081e
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: ARM64
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,80 @@
fileFormatVersion: 2
guid: fa239cb4c47fc9447816815f80667fea
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: ARMv7
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show more