From 5f0c7ceb52e8059c3a76e24da04a6636a2f02c7f Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 14 Jun 2020 17:33:32 +0100 Subject: [PATCH 01/57] moving spawn functions next to each other (#2002) --- Assets/Mirror/Runtime/NetworkServer.cs | 52 +++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Assets/Mirror/Runtime/NetworkServer.cs b/Assets/Mirror/Runtime/NetworkServer.cs index 19706f26..d52d1436 100644 --- a/Assets/Mirror/Runtime/NetworkServer.cs +++ b/Assets/Mirror/Runtime/NetworkServer.cs @@ -1133,32 +1133,6 @@ public static void Spawn(GameObject obj, NetworkConnection ownerConnection = nul } } - static bool CheckForPrefab(GameObject obj) - { -#if UNITY_EDITOR -#if UNITY_2018_3_OR_NEWER - return UnityEditor.PrefabUtility.IsPartOfPrefabAsset(obj); -#elif UNITY_2018_2_OR_NEWER - return (UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null); -#else - return (UnityEditor.PrefabUtility.GetPrefabParent(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null); -#endif -#else - return false; -#endif - } - - static bool VerifyCanSpawn(GameObject obj) - { - if (CheckForPrefab(obj)) - { - logger.LogFormat(LogType.Error, "GameObject {0} is a prefab, it can't be spawned. This will cause errors in builds.", obj.name); - return false; - } - - return true; - } - /// /// This spawns an object like NetworkServer.Spawn() but also assigns Client Authority to the specified client. /// This is the same as calling NetworkIdentity.AssignClientAuthority on the spawned object. @@ -1202,6 +1176,32 @@ public static void Spawn(GameObject obj, Guid assetId, NetworkConnection ownerCo } } + static bool CheckForPrefab(GameObject obj) + { +#if UNITY_EDITOR +#if UNITY_2018_3_OR_NEWER + return UnityEditor.PrefabUtility.IsPartOfPrefabAsset(obj); +#elif UNITY_2018_2_OR_NEWER + return (UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null); +#else + return (UnityEditor.PrefabUtility.GetPrefabParent(obj) == null) && (UnityEditor.PrefabUtility.GetPrefabObject(obj) != null); +#endif +#else + return false; +#endif + } + + static bool VerifyCanSpawn(GameObject obj) + { + if (CheckForPrefab(obj)) + { + logger.LogFormat(LogType.Error, "GameObject {0} is a prefab, it can't be spawned. This will cause errors in builds.", obj.name); + return false; + } + + return true; + } + static void DestroyObject(NetworkIdentity identity, bool destroyServerObject) { if (logger.LogEnabled()) logger.Log("DestroyObject instance:" + identity.netId); From 268d93f471ae5aa4dc840c1fb98a625f1b2ec70f Mon Sep 17 00:00:00 2001 From: James Frowen Date: Mon, 15 Jun 2020 13:52:36 +0100 Subject: [PATCH 02/57] Update Attributes.md (#1996) --- doc/Guides/Attributes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/Guides/Attributes.md b/doc/Guides/Attributes.md index aa34bc0e..c8d8a588 100644 --- a/doc/Guides/Attributes.md +++ b/doc/Guides/Attributes.md @@ -3,6 +3,9 @@ Networking attributes are added to member functions of NetworkBehaviour scripts, to make them run on either the client or server. These attributes can be used for Unity game loop methods like Start or Update, as well as other implemented methods. + +> **NOTE**: when using abstract or virtual methods the Attributes need to be applied to the override methods too. + - **NetworkSettings** This attribute has been deprecated because `channels` were moved to transports (where applicable) and `interval` was moved to an inspector property - **Server** From 46239783f313159ac47e192499aa8e7fcc5df0ec Mon Sep 17 00:00:00 2001 From: James Frowen Date: Mon, 15 Jun 2020 13:54:35 +0100 Subject: [PATCH 03/57] feat: adding log handler that sets console color (#2001) * adding log handler that sets console color * fixing stack trace log * removing empty cases * removing string.Format --- .../Runtime/Logging/ConsoleColorLogHandler.cs | 44 ++++++++++++++++++ .../Logging/ConsoleColorLogHandler.cs.meta | 11 +++++ .../Runtime/Logging/NetworkHeadlessLogger.cs | 23 +++++++++ .../Logging/NetworkHeadlessLogger.cs.meta | 11 +++++ doc/Components/NetworkHeadlessLogger.md | 9 ++++ doc/Components/NetworkHeadlessLogger.png | Bin 0 -> 6692 bytes doc/Components/index.md | 2 + 7 files changed, 100 insertions(+) create mode 100644 Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs create mode 100644 Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs.meta create mode 100644 Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs create mode 100644 Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs.meta create mode 100644 doc/Components/NetworkHeadlessLogger.md create mode 100644 doc/Components/NetworkHeadlessLogger.png diff --git a/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs new file mode 100644 index 00000000..b526ecc3 --- /dev/null +++ b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs @@ -0,0 +1,44 @@ +using System; +using UnityEngine; + +namespace Mirror.Logging +{ + public class ConsoleColorLogHandler : ILogHandler + { + readonly bool showExceptionStackTrace; + + public ConsoleColorLogHandler(bool showExceptionStackTrace) + { + this.showExceptionStackTrace = showExceptionStackTrace; + } + + public void LogException(Exception exception, UnityEngine.Object context) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Exception: {0}", exception.Message); + if (showExceptionStackTrace) + { + Console.WriteLine(" {0}", exception.StackTrace); + } + Console.ResetColor(); + } + + public void LogFormat(LogType logType, UnityEngine.Object context, string format, params object[] args) + { + switch (logType) + { + case LogType.Exception: + case LogType.Error: + case LogType.Assert: + Console.ForegroundColor = ConsoleColor.Red; + break; + case LogType.Warning: + Console.ForegroundColor = ConsoleColor.Yellow; + break; + } + + Console.WriteLine(format, args); + Console.ResetColor(); + } + } +} diff --git a/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs.meta b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs.meta new file mode 100644 index 00000000..329c6eba --- /dev/null +++ b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a9618569c20a504aa86feb5913c70e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs b/Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs new file mode 100644 index 00000000..d41bc2e0 --- /dev/null +++ b/Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace Mirror.Logging +{ + /// + /// Used to replace log hanlder with Console Color LogHandler + /// + [DisallowMultipleComponent] + [AddComponentMenu("Network/NetworkHeadlessLogger")] + [HelpURL("https://mirror-networking.com/docs/Components/NetworkHeadlessLogger.html")] + public class NetworkHeadlessLogger : MonoBehaviour + { + [SerializeField] bool showExceptionStackTrace = false; + + void Awake() + { + if (NetworkManager.isHeadless) + { + LogFactory.ReplaceLogHandler(new ConsoleColorLogHandler(showExceptionStackTrace)); + } + } + } +} diff --git a/Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs.meta b/Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs.meta new file mode 100644 index 00000000..221a61b8 --- /dev/null +++ b/Assets/Mirror/Runtime/Logging/NetworkHeadlessLogger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7627623f2b9fad4484082517cd73e67 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/doc/Components/NetworkHeadlessLogger.md b/doc/Components/NetworkHeadlessLogger.md new file mode 100644 index 00000000..0a61dc2b --- /dev/null +++ b/doc/Components/NetworkHeadlessLogger.md @@ -0,0 +1,9 @@ +# Network Headless Logger + +Network Headless Logger replaces the the default log handler with one that set `Console.ForegroundColor`. + +Only replaces the handler when running in headless mode. + +![Inspector](NetworkHeadlessLogger.png) + +`showExceptionStackTrace` will log the stack trace of any exceptions sent to the handler. \ No newline at end of file diff --git a/doc/Components/NetworkHeadlessLogger.png b/doc/Components/NetworkHeadlessLogger.png new file mode 100644 index 0000000000000000000000000000000000000000..53bd4d0a3e2ab5ef3c9441447c959698bea8a89f GIT binary patch literal 6692 zcmX|mbzGC(ANCT)Ml%$Yl!r&U5u_R22nYyLA|N0&QY1zrQc5Ti(x7xmcMC`(U6PVh zKw`vu`@FyR{p_>tKIe~nJKuAi?-lneU2PRI+EwD>yJFaaDcf4g!&P{(XacT?(IqK=k!$it+|N z=6mTRY1$7@dq2)}53<;B65i%TV$gX87}ex07f!`Tl^Yh7ipjeg6RnsJ)sHIk5P8q! zS-CX0gu*^p-P=gNyuQjf$#C2BJ!n3VJRI^#+1zoTe>q(5eo%kXaw0Ww|3nJ>;K74O zy>ZM1eSNA?v9bTkQ^MpaOP%}Q@$1YW+d3&^HPzJAOx~~{f>{to+$$?9=)w{da2>20 zNlAhGJMGiAHEPXS=;3ru=;B1iaVX2nx1$-*>Ot*_tnEPt|A!rB7>^DlB#f4us z45sS{`;GU{gnJ~+Nj(49)i^KopSVmEJ}`;B7JAZ!DBY=XnyY4z=kR-)o3H2kMi=|f zUHvLstxx@0UpSkd+Dmxyg|*E4zrVq2s>82sp?*#1pYzzCzi$XBKD{^`UdWez`KNsS zfP`}2BH)Z2br}RDcBt>#=~GCVLbmNMG}^EB#N?B#+mbGBj(m^2agPJzos7zzWHcL? zSt_t+?-J{qB4w1A*mG;9GB66ZbT{hd&RT3)cBmUV+#DXCuXq2X`sR*^?I0cRI}Sm? zH@3qWTImv=*~CmfxNx%D$^*%~4$SB2Kb#&lC>9bqVwQWi8{Fs6fpRWN02 zEFC+@InTYI8+9%_7Ek2us4X^Cte#Xfk!w;ruPx}tHz13<7PI^Mmfd-LEKj4}37bw?LZ_iEy>>U(1=NNxpca&XyV~0dI9oS=ybejXOWyQHdaD z9K*ueucyncpeVxk64UW7Q|3kM)Xf*a2dbSHByNd3qvW3TKR?QHX}vV${>Eq#cqv-Y zfBdcZB=(X-?tjwWb`amQ;;jT`;*WRq#2MJFuu_L7C;1|a!y)yIWt;LrIlj?jB zcA^j=yKf)z*4N03b__CiuLuX5M_n{JBPUCNWl5CXy}gH`wGNX}=O+hc>mRJWWjJhn z_&5}{7n>UmpO|fsd7a4KyO*5ta{s#Qo4TUxX$@ljYX6hfdV4QT`3j~Gv9xOKh9G1Nv zAbetw7t-&gs(GG67I3_las6Qxrg zrR-u=2=-H70|t0&>$DzzHps%R_dn>4qW$E1ygj@44w6-RbN89B0D_rh2e}%69N3;L zev}X#67q%j=CpDP`{{eRcP-*6YSyi)c`DoyZx5MlXx1k3e}@=Z_$QUNUip5w@BZ(% z_ktl~V|-qcxG9Ukbi-m}`PJUIg0sWT@%9j6``K#y$N9C1iR&JOz1pg&)!Lpq+*4gQ5+}Qzsc{JTB!XfvV z>`TYC1Z|N~Sw636jVt5z=_*BwMHEnGH)g%17XO)J$B2cq%o!$eSKLXb^!aiKMK$$~ zkV|>v_2I_18~_Uy?-0Xnr+U*#FR?m7Glvg3f=uhNHs)L`c<}aOi~q|HGX4_W>_`sg zovAWAIC}Wof`6rCEhLJEhin3VLRLq(iFpOSG9IiKl6r6R0T{s1z3!WMG-NOSJfVMd3#oFD~ zg{Llbw4bXf*(*qI+xOc}NUX5#t)xY<=9P0D5;YQ9y${UIKbR$$)fcofR&5rw0VJ+r zF`TQGFuiAyqfGYaaoa-d%WU0@5EZ5u{}3|hD}Y*(X;#^O^I1sX6F$EE?hF&!p>FAl zU}rDTjp~#qFAz;leye=l{qLB!EMvj31*1nx6-nZjpDe@8p-qSAIRJOv8BjWNkaFeB zOQ2>Ika%|_9j7WXQC?g6a8USYLSM&CZ?7m10?IsIJ(R)aRYEQpeL$HoIpf>6#YFE= zCudV<&~e%;b%v9@IGeHiIQmU&Y0#Qw`A=`fEivao8(+L-u@r+%f1;p&dAY>sUcAw6 zDGi3%#+9w}vuL)|-3*R9Kq*FSSMKR(Y1xq7{9e%UnMdsXLZHoP>i;THw24Z@2JxY! zeR@Y|LxSWEnhwb~f6|hA1{7J(rJKh2_GFNXKY5o=qtkc|TXBHWT%}35&2ug%Z0*ie zdHh+T>(|uE4)=7~ZK3D%|W>l-!TzUgbGB`=vxjV6j_1U(BZFXt|@_OXFk3%_8lu9ba=Y>p6B`gSzk|+-e&_& zFQ*RQshs)sx(Z5h*PqtaUm!PRaRU}Xw@FxzvOp~Ircm|!Am1YW*VI+vgNO_gk3*FWwN&AEsQLOy;W5m}AuX_oVf5b92ivsH2mt=)l3t zj+k_a#OxW9_*;Iw*m=R#t9x@DNcgpi0P*7fJ4>x1tglW#v>bgj(>ceQcidKjT)y5Wu( zwpTrsTB-M*3tGj~-U>YG#8?xK#&xQAmD5n_5m=?wx?vdtkCLJyzJ{8mM`HVMbflx3 z6ues+NM9!zD>%F_F&YsqV{@UKMT^-2AD^5C>7>-% z10-2Y85PtV_b`RZ)10j^V&Ss4xx3ip^xJA}lw(hoeu(&9|6b|ng1Z~>`Tk1&&UA&f z*9pq!p!wvKW)2WEVM}Ds4z`Mn%-~xRZNi;ZayP-so7@L6GxafN4!0AqD-wbM>tQ#| z`(z>-mt@<-<3%06yT1Ey3&xEIdv#4Op1@^Pq}3ZJtLk}6)ZK)O9*t&5+)IHzdIa{6 z`6KehSueKc0^Y*&x4!u?@cZ}2QKH3OO$o-mbsVCLJ;l5*@mdMlp3BS_2!8u# zb0%F?xEHY#@1kSVfy_swxC~!La7Qum344ad(-n%YbdJa5meLApK38X(kLuf}QPN)P zFW|up7&LM{f;r&*s(#x=k3PE+#eDiggXiimS!VyEH!9W`-~_F%eGD8GTiVZKB+lXN zo>2~k(R!N9TA|TcGB|OBu5kro(^sH7O+wqVKUcpyN(}$*UPiDEZqzQ0|GfZW+H}O3 zbC{*rueq1WNz2z)f?_S=0dywSr5zXTpXzInr+A8b2W@&>o{`1cIUs~xQ*BrYzg?|I zz*+>kF^!zA_ySYg(`E}&r9QJ9pjXG*3;84Z%}gX@9>MibAE^eJJivTc3- zeoW~WNSsA1Sl68n6)c-0Q`KHuqf3OJ#Hm}U0;cRKX-=TZ#AcHw;rHjfgpaae{V%a@@TKTVds#7 ze68Qt?CxNrQb^R(ch`>*V@e$31?NBxC=bMV;jJda1s1z1|KlLRrA=_P^V~ zkGrVnyiPU2r+`)yM^I#wTXn>zIyZ1mA#p5^)!LwxXa;r3Slf}e%z9hR{^Tad3e+Vt zsj5qt$%Caei4zkHRbgNcHU=3#<2h=Wd>oH|AY{n8DDXhTn#@#LBq>se;_PPn{_};5}J=I-aCjdHT^Yiu0A4X)Tcs{{B|pU?JZ6 z`EEYkqRFSi@QH=3p-ZD33&M~k05O~Jqx<#Yy<|YR(aPw91kAWLNF#QbDvYQKw3>JDs-xwG-Mz1>kbik1F8}YRy@}WilOY+=be)5ww! zn?@|JW-v&E^BmNPl`#2s@0q7x@n5Mu9F%E-tnw2s-hbDU!D~|8w=z?~Rn^FEJ1j@J z8~OV6z>OOpa$*@XgN2d7(*G z+#YjV%=Tr=JUEDml`QX8dkAF{$=vzbIn^E&SP9QGSz;MhOLl5Vg-n&LC~vtU}HsmU;f!$!Ev20+t{Aj8ZYqE zGN5d9e;gSn%}DEe11ppQw~EsG>(X~k-@77;0RRm`$Rb!{h@fD~qgiQOkqCdA(gt5o zBgUo$0frTQW}LFnsB;*JCxp4u|cs8E+x#XtZwKxLRqU4D6fJg&|M zM}k68i3kQ16Br@UOw1z2G9f7QBGkM6cJVg3x9`ufyiZPZHSc^bMreP0?XxRdU3K5s zo-A@-x*J;D!6Pe{nPIyZ|1d>t*nqN0zMhaojmz7e8jC;6gsotM!x{VSzx1(8;o34^fBa>@AEcX= zGL*ZwOEma94BzUDmsDX|yn7_Ovvl)f|KZkC5FCUIt$fb?@N-vSkr8M)MPZ6zQ42Wm zz0xQ13g146uDY+DOLc$Vrz^m@cdilxgn$ipH-H)vjVELc%W(*Inf z@k+oD#NSx(e5oa!7%x|3KVMgotg&k^w~Ou4y%{lEz$w>dNRQUIK7BiL!AbzUbn9So_C#LFQIbKil zrC6IW>j&bEpQ9?w>o`FWO>12Tq;Z3QTE@#gk~-$b%$X?F0_@B2%ufPA`JnS(&G&6l zFbG)dgUG9bpUn(%mh|K6Z9a<^l-XV<%`9bRfvqt=9iYj9G24^(b;Uh+;3U~%lSFx+y!&TV(QOKQq-s?;W^+GgNJN%eA2`D8&6ZD7Me55Z}^W!6=k zWljIS)h){}Yl*uCq}6%AqGf*w!$EH4RCwYy{ggjZf)#c{X`hlBjBB3Ldu~s>+U!w& z{2YF+A3?#aU1IX(N1jXv^Pezy7$Ugb)!N$nMI#_nXPFiS11@|_S_7oZRFsrPHTavm zc0g1Ow%vOrPrme>+lVJ^J1qL#M?L)(eVPE%|q^{lDNr3 z4pjjiZ}q4Un$T90hVN!ba5AuASCPYL+|?yve7QYj1|CyriXeNQ>+|ae&$MzJlNRbG z-vsv6#<$d7!`%;}j)l$(4I+V8ekGyexvaPR>b?jbbNzUwK+j=XQ(P1AGI2y0DT^?j zpa}K_{JjW}2$qD_X-7Ils@ja_YptH+;HVpT!F$iAf-jZ!tVsas-3z_hw zFR^4ZoFX0EPogR!I2%ULavQob|C#ut@6Ir{drmv8{A{DCOHgHc3k)S1`7dWY*s(s5 zLL%SIS+IM+3vGt@{zF(7(DFJcI)p;uQ33YG&nU}%%PF2DvPJXrSa!Gg6ACrn@flP< zd*HiU(fbU@a!g3vn7Km9JM1t%2eV&Z6LTkX>MPH6N~>?thcPE25amD`Td^D+9X+8Q z>9srE?%CDn#1Qy&mX2T*%+wZr5VD6BqnnL`nEWS1d_aG8XF9(dK?=Ci{ z#xhCw_rK@=s^u@`&vX`JzPytJ`e*7CG^IxgYiItI0s+0gg@HgIe7?q6KsNVXz2uWc zt4w3iXl-2k^J&92XgPLWy#~hmPpX)UHV^~V9E08m?T4~!B#$_jH7mO`{UYk_?zU%F z1o#@rJMOtDkURSJCvv7Om0Kyu*gbi2=VWpih^r21%b#RrHUVPMk5mbux}W%!&RIk4 z;?kMhyZen5EdvSAn0k0rC-eTD=$KRoogF{s27L0jVizE0$s`gZ~fuXr%7| literal 0 HcmV?d00001 diff --git a/doc/Components/index.md b/doc/Components/index.md index 3812148f..beff4872 100644 --- a/doc/Components/index.md +++ b/doc/Components/index.md @@ -14,6 +14,8 @@ These core components are included in Mirror: The Network Identity component is at the heart of the Mirror networking high-level API. It controls a game object’s unique identity on the network, and it uses that identity to make the networking system aware of the game object. It offers two different options for configuration and they are mutually exclusive, which means either one of the options or none can be checked. - [Network Log Settings](NetworkLogSettings.md) The Network Log Settings component allows you to configure logging levels and load the settings in a build. +- [Network Headless Logger](NetworkHeadlessLogger.md) + Network Headless Logger adds color to log when running in headless mode - [Network Manager](NetworkManager.md) The Network Manager is a component for managing the networking aspects of a multiplayer game. - [Network Manager HUD](NetworkManagerHUD.md) From b41fca2d28c730ce1058bd1a48c923ba57842c88 Mon Sep 17 00:00:00 2001 From: Chris Langsenkamp Date: Tue, 16 Jun 2020 08:29:59 -0400 Subject: [PATCH 04/57] Changed to inline token injection --- Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs index b526ecc3..769fbf73 100644 --- a/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs +++ b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs @@ -15,10 +15,10 @@ public ConsoleColorLogHandler(bool showExceptionStackTrace) public void LogException(Exception exception, UnityEngine.Object context) { Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("Exception: {0}", exception.Message); + Console.WriteLine($"Exception: {exception.Message}"); if (showExceptionStackTrace) { - Console.WriteLine(" {0}", exception.StackTrace); + Console.WriteLine($" {exception.StackTrace}"); } Console.ResetColor(); } From 76d49c1e99c1229be2c1e6f81af25af5c17dcc83 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Tue, 16 Jun 2020 16:16:58 +0100 Subject: [PATCH 05/57] faster write line (#2009) --- Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs index 769fbf73..a1b7d22c 100644 --- a/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs +++ b/Assets/Mirror/Runtime/Logging/ConsoleColorLogHandler.cs @@ -37,7 +37,7 @@ public void LogFormat(LogType logType, UnityEngine.Object context, string format break; } - Console.WriteLine(format, args); + Console.WriteLine(string.Format(format, args)); Console.ResetColor(); } } From 8c1ed40c40aad9c9888c3c1c97a9fb83e2778921 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Tue, 16 Jun 2020 17:21:57 +0100 Subject: [PATCH 06/57] adding check before telling clients (#2010) * adding check before telling clients * Update Assets/Mirror/Runtime/NetworkManager.cs Co-authored-by: MrGadget --- Assets/Mirror/Runtime/NetworkManager.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Assets/Mirror/Runtime/NetworkManager.cs b/Assets/Mirror/Runtime/NetworkManager.cs index 01c31aef..d8a3ad22 100644 --- a/Assets/Mirror/Runtime/NetworkManager.cs +++ b/Assets/Mirror/Runtime/NetworkManager.cs @@ -824,8 +824,13 @@ public virtual void ServerChangeScene(string newSceneName) loadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName); - // notify all clients about the new scene - NetworkServer.SendToAll(new SceneMessage { sceneName = newSceneName }); + // ServerChangeScene can be called when stopping the server + // when this happens the server is not active so does not need to tell clients about the change + if (NetworkServer.active) + { + // notify all clients about the new scene + NetworkServer.SendToAll(new SceneMessage { sceneName = newSceneName }); + } startPositionIndex = 0; startPositions.Clear(); From 37338706f9ce36d3f93e92e83a42599e677a4f9c Mon Sep 17 00:00:00 2001 From: Chris Langsenkamp Date: Wed, 17 Jun 2020 17:35:32 -0400 Subject: [PATCH 07/57] Remove redundant .transform --- Assets/Mirror/Components/Experimental/NetworkTransformBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs b/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs index a05421b3..10107c73 100644 --- a/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs +++ b/Assets/Mirror/Components/Experimental/NetworkTransformBase.cs @@ -1,4 +1,4 @@ -// vis2k: +// vis2k: // base class for NetworkTransform and NetworkTransformChild. // New method is simple and stupid. No more 1500 lines of code. // @@ -134,7 +134,7 @@ void FixedUpdate() // serialize // local position/rotation for VR support // send to server - CmdClientToServerSync(targetTransform.transform.localPosition, targetTransform.transform.localRotation, targetTransform.transform.localScale); + CmdClientToServerSync(targetTransform.localPosition, targetTransform.localRotation, targetTransform.localScale); } } } From e84754d3e888a80377d59b7db6f0198edbe7945e Mon Sep 17 00:00:00 2001 From: Chris Langsenkamp Date: Wed, 17 Jun 2020 22:40:17 -0400 Subject: [PATCH 08/57] doc: Updated Profiler page --- doc/Guides/Profiler.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/Guides/Profiler.md b/doc/Guides/Profiler.md index 2c2666a2..7bd23f8a 100644 --- a/doc/Guides/Profiler.md +++ b/doc/Guides/Profiler.md @@ -1,16 +1,16 @@ # Mirror Network Profiler -The [mirror profiler](https://mirror-networking.com/download/mirror-profiler/) is part of the Mirror Pro suit. +The Mirror Profiler is part of the Mirror Pro suit. As of this writing it is accessible to our Github Supporters. ![Network Profiler](Profiler.png) ## Installation -1. Make sure you have the latest version of Mirror +1. Make sure you have the latest version of Mirror. 2. Become a [Github Supporter](https://github.com/sponsors/vis2k) if you haven't. -3. [Download](https://mirror-networking.com/download/mirror-profiler/) the profiler -4. Install the unity package in your project +3. Download the profiler. +4. Install the unity package in your project. ## Usage From b41996b0742c9b9e429221aee64099f58dcfab07 Mon Sep 17 00:00:00 2001 From: Chris Langsenkamp Date: Wed, 17 Jun 2020 22:42:21 -0400 Subject: [PATCH 09/57] doc: Updated Profiler Guide --- doc/Guides/Profiler.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Guides/Profiler.md b/doc/Guides/Profiler.md index 7bd23f8a..fe28c707 100644 --- a/doc/Guides/Profiler.md +++ b/doc/Guides/Profiler.md @@ -1,14 +1,14 @@ # Mirror Network Profiler The Mirror Profiler is part of the Mirror Pro suit. -As of this writing it is accessible to our Github Supporters. +As of this writing it is accessible to our GitHub Supporters. ![Network Profiler](Profiler.png) ## Installation 1. Make sure you have the latest version of Mirror. -2. Become a [Github Supporter](https://github.com/sponsors/vis2k) if you haven't. +2. Become a [GitHub Sponsor](https://github.com/sponsors/vis2k) if you haven't. 3. Download the profiler. 4. Install the unity package in your project. From f2e38929df9c0c574b91b2d600e7773374baaf8f Mon Sep 17 00:00:00 2001 From: Chris Langsenkamp Date: Wed, 17 Jun 2020 22:43:51 -0400 Subject: [PATCH 10/57] doc: Updated Profiler Guide --- doc/Guides/Profiler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Guides/Profiler.md b/doc/Guides/Profiler.md index fe28c707..81593078 100644 --- a/doc/Guides/Profiler.md +++ b/doc/Guides/Profiler.md @@ -1,7 +1,7 @@ # Mirror Network Profiler The Mirror Profiler is part of the Mirror Pro suit. -As of this writing it is accessible to our GitHub Supporters. +As of this writing it is accessible to our [GitHub Sponsors](https://github.com/sponsors/vis2k). ![Network Profiler](Profiler.png) From c14b82c62191a0b8eeccb835e97f3c8ce0f537ce Mon Sep 17 00:00:00 2001 From: Marco Hoffmann <30300243+Chykary@users.noreply.github.com> Date: Thu, 18 Jun 2020 13:49:16 +0200 Subject: [PATCH 11/57] Updated doc for Fizzy Steam transports (#2016) Co-authored-by: Marco Hoffmann --- doc/Transports/FizzyFacepunch.PNG | Bin 0 -> 59146 bytes doc/Transports/FizzyFacepunch.md | 19 ++++++++++++++++++ doc/Transports/FizzySteamworks.PNG | Bin 0 -> 60081 bytes .../{Fizzy.md => FizzySteamworks.md} | 10 ++++----- doc/Transports/SteamTransport.PNG | Bin 57126 -> 0 bytes doc/Transports/index.md | 4 +++- 6 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 doc/Transports/FizzyFacepunch.PNG create mode 100644 doc/Transports/FizzyFacepunch.md create mode 100644 doc/Transports/FizzySteamworks.PNG rename doc/Transports/{Fizzy.md => FizzySteamworks.md} (60%) delete mode 100644 doc/Transports/SteamTransport.PNG diff --git a/doc/Transports/FizzyFacepunch.PNG b/doc/Transports/FizzyFacepunch.PNG new file mode 100644 index 0000000000000000000000000000000000000000..ae605a60e0996324d21fec45d8e1448d4f52543e GIT binary patch literal 59146 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 Lqf6Bn?W6wzPhAq# literal 0 HcmV?d00001 diff --git a/doc/Transports/FizzyFacepunch.md b/doc/Transports/FizzyFacepunch.md new file mode 100644 index 00000000..d0639e58 --- /dev/null +++ b/doc/Transports/FizzyFacepunch.md @@ -0,0 +1,19 @@ +# FizzyFacepunch Transport + +FizzyFacepunch is a Steam P2P transport for Mirror, it utilizes Steam's P2P service to directly connect or relay your connection to another player. FizzyFacepunch is based on the [Facepunch.Steamworks](https://github.com/Facepunch/Facepunch.Steamworks) wrapper. + +You can get the release **[Here](https://github.com/Chykary/FizzyFacepunch/releases)** or you can clone the repo **[Here](https://github.com/Chykary/FizzyFacepunch)**. + +## Features + +* Multiple Customizable Channels : You can customize the channels in the transport, whether you want just 1 or 5 channels that are unreliable or reliable (best to leave channel 0 as reliable). +* Steam Nat Punching & Relay : The transport will use Steam to do Nat Punching to your destination, and if that doesn't work, steam's relay Server will be used to ensure you can always connect (latency may vary). +* No Code Changes Needed : If you Already use Mirror, you just need to slap this transport in (maybe add your steam App ID in your build), and everything should work the same like any other Mirror Transport. "It Just Works" -Todd Howard + +![The FizzySteamworks Transport component in the Inspector window](FizzyFacepunch.PNG) + +## Credits +* [Chykary](https://github.com/Chykary/FizzyFacepunch) : The author of this Transport. +* [Facepunch](https://github.com/Facepunch) : Creator of Facepunch.Steamworks. +* [vis2k](https://github.com/vis2k) : Creator of Mirror. +* Valve : Steam diff --git a/doc/Transports/FizzySteamworks.PNG b/doc/Transports/FizzySteamworks.PNG new file mode 100644 index 0000000000000000000000000000000000000000..557c0c27ede4edba2a79fbcd61f437b8c9bce3db GIT binary patch literal 60081 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%0D1187pa(J15_(0_x`3Kswl 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 literal 0 HcmV?d00001 diff --git a/doc/Transports/Fizzy.md b/doc/Transports/FizzySteamworks.md similarity index 60% rename from doc/Transports/Fizzy.md rename to doc/Transports/FizzySteamworks.md index d3ff06bf..dbb0c5c6 100644 --- a/doc/Transports/Fizzy.md +++ b/doc/Transports/FizzySteamworks.md @@ -1,8 +1,8 @@ -# FizzySteam Transport +# FizzySteamworks Transport -Fizzy Steam is a Steam P2P transport for Mirror, it utilizes Steam's P2P service to directly connect or relay your connection to another player. Fizzy Steam is based of [Steamworks.Net](https://github.com/rlabrecque/Steamworks.NET) wrapper. +FizzySteamworks is a Steam P2P transport for Mirror, it utilizes Steam's P2P service to directly connect or relay your connection to another player. FizzySteamworks is based on the [Steamworks.Net](https://github.com/rlabrecque/Steamworks.NET) wrapper. -You can get the release **[Here](https://github.com/Chykary/FizzySteamyMirror/releases)** with the latest version of Steamworks.Net included or you can clone the repo **[Here](https://github.com/Chykary/FizzySteamyMirror)**. +You can get the release **[Here](https://github.com/Chykary/FizzySteamworks/releases)** with the latest version of Steamworks.Net included or you can clone the repo **[Here](https://github.com/Chykary/FizzySteamworks)**. ## Features @@ -10,11 +10,11 @@ You can get the release **[Here](https://github.com/Chykary/FizzySteamyMirror/re * Steam Nat Punching & Relay : The transport will use Steam to do Nat Punching to your destination, and if that doesn't work, steam's relay Server will be used to ensure you can always connect (latency may vary). * No Code Changes Needed : If you Already use Mirror, you just need to slap this transport in (maybe add your steam App ID in your build), and everything should work the same like any other Mirror Transport. "It Just Works" -Todd Howard -![The Fizzy Transport component in the Inspector window](SteamTransport.PNG) +![The FizzySteamworks Transport component in the Inspector window](FizzySteamworks.PNG) ## Credits * [Fizz Cube](https://github.com/FizzCube) : Original author for this Transport. -* [Chykary](https://github.com/Chykary/FizzySteamyMirror) : The current maintainer for this Transport. +* [Chykary](https://github.com/Chykary/FizzySteamworks) : The current maintainer for this Transport. * [rlabrecque](https://github.com/rlabrecque) : Creator of Steamworks.Net. * [vis2k](https://github.com/vis2k) : Creator of Mirror. * Valve : Steam diff --git a/doc/Transports/SteamTransport.PNG b/doc/Transports/SteamTransport.PNG deleted file mode 100644 index 2ee8d242944e59dae3555000465f07fd50dbe964..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57126 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

8}?$mS^9dyRfbR7b+##=EcYk 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 diff --git a/doc/Transports/index.md b/doc/Transports/index.md index 551143d4..a3084679 100644 --- a/doc/Transports/index.md +++ b/doc/Transports/index.md @@ -18,4 +18,6 @@ Mirror is a high level Networking Library that can use several different low lev - [UDP - LiteNetLib4Mirror](LiteNetLib4Mirror.md) LiteNetLib4Mirror implements a UDP transport based on LiteNetLib with Network Discovery and uPnP included. -- [Steam - Fizzy](Fizzy.md) A complete rebuild utilising Async (Previously SteamNetNetworkTransport) of a Steam P2P network transport layer. +- [Steam - FizzySteamworks](FizzySteamworks.md) Transport utilising Steam P2P network, building on Steamworks.NET. + +- [Steam - FizzyFacepunch](FizzyFacepunch.md) Transport utilising Steam P2P network, building on Facepunch.Steamworks. \ No newline at end of file From 5032ceb00035679e0b80f59e91131cdfa8e0b1bb Mon Sep 17 00:00:00 2001 From: Chris Langsenkamp Date: Thu, 18 Jun 2020 09:44:13 -0400 Subject: [PATCH 12/57] fix: Clean up roomSlots on clients in NetworkRoomPlayer --- Assets/Mirror/Components/NetworkRoomPlayer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Assets/Mirror/Components/NetworkRoomPlayer.cs b/Assets/Mirror/Components/NetworkRoomPlayer.cs index 40b7573a..5f97060f 100644 --- a/Assets/Mirror/Components/NetworkRoomPlayer.cs +++ b/Assets/Mirror/Components/NetworkRoomPlayer.cs @@ -65,6 +65,15 @@ public void Start() logger.LogError("RoomPlayer could not find a NetworkRoomManager. The RoomPlayer requires a NetworkRoomManager object to function. Make sure that there is one in the scene."); } + public virtual void OnDisable() + { + if (NetworkClient.active && NetworkManager.singleton is NetworkRoomManager room) + { + room.roomSlots.Remove(this); + room.RecalculateRoomPlayerIndices(); + } + } + #endregion #region Commands From 4af72c3a63e72dac6b3bab193dc58bfa3c44a975 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Thu, 18 Jun 2020 23:23:46 +0100 Subject: [PATCH 13/57] fix: calling base method when the first base class did not have the virtual method (#2014) * adding test for error * adding test with multiple overrides * calling methods in base type * adding test for more than 1 override --- Assets/Mirror/Editor/Weaver/Extensions.cs | 26 ++++++++++ .../Weaver/Processors/MethodProcessor.cs | 14 +++++- .../Tests/Editor/CommandOverrideTest.cs | 49 +++++++++++++++++++ .../Tests/Editor/Weaver/.WeaverTests.csproj | 2 + .../Tests/Editor/Weaver/WeaverCommandTests.cs | 12 +++++ .../OverrideVirtualCallBaseCommand.cs | 1 - ...CallsBaseCommandWithMultipleBaseClasses.cs | 27 ++++++++++ ...rideVirtualCallsBaseCommandWithOverride.cs | 34 +++++++++++++ .../OverrideVirtualCommand.cs | 1 - 9 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithMultipleBaseClasses.cs create mode 100644 Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithOverride.cs diff --git a/Assets/Mirror/Editor/Weaver/Extensions.cs b/Assets/Mirror/Editor/Weaver/Extensions.cs index ee190c14..0d211bce 100644 --- a/Assets/Mirror/Editor/Weaver/Extensions.cs +++ b/Assets/Mirror/Editor/Weaver/Extensions.cs @@ -218,6 +218,32 @@ public static List GetMethods(this TypeDefinition td, string m return methods; } + public static MethodDefinition GetMethodInBaseType(this TypeDefinition td, string methodName) + { + TypeDefinition typedef = td; + while (typedef != null) + { + foreach (MethodDefinition md in typedef.Methods) + { + if (md.Name == methodName) + return md; + } + + try + { + TypeReference parent = typedef.BaseType; + typedef = parent?.Resolve(); + } + catch (AssemblyResolutionException) + { + // this can happen for pluins. + break; + } + } + + return null; + } + ///

/// /// diff --git a/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs index a4531b00..f3203e28 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/MethodProcessor.cs @@ -84,7 +84,19 @@ public static void FixRemoteCallToBaseMethod(TypeDefinition type, MethodDefiniti calledMethod.Name == baseRemoteCallName) { TypeDefinition baseType = type.BaseType.Resolve(); - MethodDefinition baseMethod = baseType.GetMethod(callName); + MethodDefinition baseMethod = baseType.GetMethodInBaseType(callName); + + if (baseMethod == null) + { + Weaver.Error($"Could not find base method for {callName}", method); + return; + } + + if (!baseMethod.IsVirtual) + { + Weaver.Error($"Could not find base method that was virutal {callName}", method); + return; + } instruction.Operand = baseMethod; diff --git a/Assets/Mirror/Tests/Editor/CommandOverrideTest.cs b/Assets/Mirror/Tests/Editor/CommandOverrideTest.cs index cedec68b..3bce6b8b 100644 --- a/Assets/Mirror/Tests/Editor/CommandOverrideTest.cs +++ b/Assets/Mirror/Tests/Editor/CommandOverrideTest.cs @@ -42,6 +42,21 @@ public override void CmdSendInt(int someInt) } } + /// + /// test for 2 overrides + /// + class VirtualOverrideCommandWithBase2 : VirtualOverrideCommandWithBase + { + public event Action onOverrideSendInt2; + + [Command] + public override void CmdSendInt(int someInt) + { + base.CmdSendInt(someInt); + onOverrideSendInt2?.Invoke(someInt); + } + } + public class CommandOverrideTest : RemoteTestBase { [Test] @@ -132,5 +147,39 @@ public void OverrideVirtualWithBaseCallsBothVirtualAndBase() Assert.That(virtualCallCount, Is.EqualTo(1)); Assert.That(overrideCallCount, Is.EqualTo(1)); } + + [Test] + public void OverrideVirtualWithBaseCallsAllMethodsThatCallBase() + { + VirtualOverrideCommandWithBase2 hostBehaviour = CreateHostObject(true); + + const int someInt = 20; + + int virtualCallCount = 0; + int overrideCallCount = 0; + int override2CallCount = 0; + hostBehaviour.onVirtualSendInt += incomingInt => + { + virtualCallCount++; + Assert.That(incomingInt, Is.EqualTo(someInt)); + }; + hostBehaviour.onOverrideSendInt += incomingInt => + { + overrideCallCount++; + Assert.That(incomingInt, Is.EqualTo(someInt)); + }; + hostBehaviour.onOverrideSendInt2 += incomingInt => + { + override2CallCount++; + Assert.That(incomingInt, Is.EqualTo(someInt)); + }; + + + hostBehaviour.CmdSendInt(someInt); + ProcessMessages(); + Assert.That(virtualCallCount, Is.EqualTo(1)); + Assert.That(overrideCallCount, Is.EqualTo(1)); + Assert.That(override2CallCount, Is.EqualTo(1)); + } } } diff --git a/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj b/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj index 16da27a9..e207b889 100644 --- a/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj +++ b/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj @@ -100,6 +100,8 @@ + + diff --git a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests.cs b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests.cs index 95380215..2d404b40 100644 --- a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests.cs +++ b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests.cs @@ -76,6 +76,18 @@ public void OverrideVirtualCallBaseCommand() Assert.That(weaverErrors, Is.Empty); } + [Test] + public void OverrideVirtualCallsBaseCommandWithMultipleBaseClasses() + { + Assert.That(weaverErrors, Is.Empty); + } + + [Test] + public void OverrideVirtualCallsBaseCommandWithOverride() + { + Assert.That(weaverErrors, Is.Empty); + } + [Test] public void AbstractCommand() { diff --git a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallBaseCommand.cs b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallBaseCommand.cs index f60cc667..0784e170 100644 --- a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallBaseCommand.cs +++ b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallBaseCommand.cs @@ -1,6 +1,5 @@ using Mirror; - namespace WeaverCommandTests.OverrideVirtualCallBaseCommand { class OverrideVirtualCallBaseCommand : baseBehaviour diff --git a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithMultipleBaseClasses.cs b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithMultipleBaseClasses.cs new file mode 100644 index 00000000..842fa556 --- /dev/null +++ b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithMultipleBaseClasses.cs @@ -0,0 +1,27 @@ +using Mirror; + +namespace WeaverCommandTests.OverrideVirtualCallsBaseCommandWithMultipleBaseClasses +{ + class OverrideVirtualCallsBaseCommandWithMultipleBaseClasses : middleBehaviour + { + [Command] + protected override void CmdDoSomething() + { + // do somethin + base.CmdDoSomething(); + } + } + + class middleBehaviour : baseBehaviour + { + } + + class baseBehaviour : NetworkBehaviour + { + [Command] + protected virtual void CmdDoSomething() + { + // do more stuff + } + } +} diff --git a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithOverride.cs b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithOverride.cs new file mode 100644 index 00000000..35736d78 --- /dev/null +++ b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCallsBaseCommandWithOverride.cs @@ -0,0 +1,34 @@ +using Mirror; + +namespace WeaverCommandTests.OverrideVirtualCallsBaseCommandWithOverride +{ + class OverrideVirtualCallsBaseCommandWithOverride : middleBehaviour + { + [Command] + protected override void CmdDoSomething() + { + // do something + base.CmdDoSomething(); + } + } + + + class middleBehaviour : baseBehaviour + { + [Command] + protected override void CmdDoSomething() + { + // do something else + base.CmdDoSomething(); + } + } + + class baseBehaviour : NetworkBehaviour + { + [Command] + protected virtual void CmdDoSomething() + { + // do more stuff + } + } +} diff --git a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCommand.cs b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCommand.cs index e6b18766..c02684b2 100644 --- a/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCommand.cs +++ b/Assets/Mirror/Tests/Editor/Weaver/WeaverCommandTests~/OverrideVirtualCommand.cs @@ -1,6 +1,5 @@ using Mirror; - namespace WeaverCommandTests.OverrideVirtualCommand { class OverrideVirtualCommand : baseBehaviour From b9508e756de0b2b2924a87b8f0cc3cffc123454f Mon Sep 17 00:00:00 2001 From: Tri-tip <63820412+Tri-tip@users.noreply.github.com> Date: Fri, 19 Jun 2020 03:14:17 -0700 Subject: [PATCH 14/57] Fixed small typo (#2019) Changed oath to OAuth2 --- doc/Components/Authenticators/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Components/Authenticators/index.md b/doc/Components/Authenticators/index.md index e966a914..f8f4a23b 100644 --- a/doc/Components/Authenticators/index.md +++ b/doc/Components/Authenticators/index.md @@ -2,7 +2,7 @@ When you have a multiplayer game, often you need to store information about your player for later games, keep game stats or communicate with your friends. For all these use cases, you often need a way to uniquely identify a user. Being able to tell users apart is called authentication. There are several methods available, some examples include: - Ask the user for username and password -- Use a third party oath or OpenID identity provider, such as Facebook, Twitter, Google +- Use a third party OAuth2 or OpenID identity provider, such as Facebook, Twitter, Google - Use a third party service such as PlayFab, GameLift or Steam - Use the device id, very popular method in mobile - Use Google Play in Android From 36c0b65e8ba634ada22c00c79ab60f7292dcbc3f Mon Sep 17 00:00:00 2001 From: uwee Date: Sat, 20 Jun 2020 18:39:36 -0400 Subject: [PATCH 15/57] fixes broken ui for Tanks example (#2015) --- .../Mirror/Examples/Tanks/Scenes/Scene.unity | 1134 ++++++++--------- 1 file changed, 553 insertions(+), 581 deletions(-) diff --git a/Assets/Mirror/Examples/Tanks/Scenes/Scene.unity b/Assets/Mirror/Examples/Tanks/Scenes/Scene.unity index 326d5b9c..91a58a20 100644 --- a/Assets/Mirror/Examples/Tanks/Scenes/Scene.unity +++ b/Assets/Mirror/Examples/Tanks/Scenes/Scene.unity @@ -54,7 +54,7 @@ LightmapSettings: m_EnableBakedLightmaps: 0 m_EnableRealtimeLightmaps: 0 m_LightmapEditorSettings: - serializedVersion: 12 + serializedVersion: 10 m_Resolution: 2 m_BakeResolution: 40 m_AtlasSize: 1024 @@ -62,7 +62,6 @@ LightmapSettings: m_AOMaxDistance: 1 m_CompAOExponent: 1 m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 m_Padding: 2 m_LightmapParameters: {fileID: 0} m_LightmapsBakeMode: 1 @@ -77,16 +76,10 @@ LightmapSettings: 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_PVRFilteringMode: 2 m_PVRCulling: 1 m_PVRFilteringGaussRadiusDirect: 1 m_PVRFilteringGaussRadiusIndirect: 5 @@ -94,8 +87,7 @@ LightmapSettings: m_PVRFilteringAtrousPositionSigmaDirect: 0.5 m_PVRFilteringAtrousPositionSigmaIndirect: 2 m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData + m_ShowResolutionOverlay: 1 m_LightingDataAsset: {fileID: 0} m_UseShadowmask: 1 --- !u!196 &4 @@ -120,73 +112,7 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 23800000, guid: 0bc607fa2e315482ebe98797e844e11f, type: 2} ---- !u!1 &3543601 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3543604} - - component: {fileID: 3543603} - - component: {fileID: 3543602} - m_Layer: 0 - m_Name: EventSystem - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &3543602 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3543601} - 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 &3543603 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3543601} - 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 &3543604 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3543601} - 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: 9 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &16255281 +--- !u!1 &20677886 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -194,9 +120,9 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 16255282} - - component: {fileID: 16255284} - - component: {fileID: 16255283} + - component: {fileID: 20677887} + - component: {fileID: 20677889} + - component: {fileID: 20677888} m_Layer: 5 m_Name: Text m_TagString: Untagged @@ -204,18 +130,18 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &16255282 +--- !u!224 &20677887 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 16255281} + m_GameObject: {fileID: 20677886} 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: 1902988042} + m_Father: {fileID: 721760295} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -223,16 +149,16 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &16255283 +--- !u!114 &20677888 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 16255281} + m_GameObject: {fileID: 20677886} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -241,6 +167,8 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} m_FontSize: 14 @@ -255,13 +183,13 @@ MonoBehaviour: m_VerticalOverflow: 0 m_LineSpacing: 1 m_Text: Ready ---- !u!222 &16255284 +--- !u!222 &20677889 CanvasRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 16255281} + m_GameObject: {fileID: 20677886} m_CullTransparentMesh: 0 --- !u!1 &88936773 GameObject: @@ -310,10 +238,9 @@ Camera: m_ClearFlags: 1 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_GateFitMode: 2 m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 @@ -398,7 +325,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} m_Name: m_EditorClassIdentifier: ---- !u!1 &264728359 +--- !u!1 &472317786 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -406,74 +333,76 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 264728360} - - component: {fileID: 264728362} - - component: {fileID: 264728361} + - component: {fileID: 472317787} + - component: {fileID: 472317789} + - component: {fileID: 472317788} m_Layer: 5 - m_Name: PlayerNameInputText + m_Name: Placeholder m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &264728360 +--- !u!224 &472317787 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 264728359} + m_GameObject: {fileID: 472317786} 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: 1045278708} - m_RootOrder: 1 + m_Father: {fileID: 1986496790} + 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.5} m_SizeDelta: {x: -20, y: -13} m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &264728361 +--- !u!114 &472317788 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 264728359} + m_GameObject: {fileID: 472317786} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5} m_RaycastTarget: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} m_FontSize: 14 - m_FontStyle: 0 + m_FontStyle: 2 m_BestFit: 0 m_MinSize: 10 m_MaxSize: 40 m_Alignment: 0 m_AlignByGeometry: 0 - m_RichText: 0 - m_HorizontalOverflow: 1 + m_RichText: 1 + m_HorizontalOverflow: 0 m_VerticalOverflow: 0 m_LineSpacing: 1 - m_Text: ---- !u!222 &264728362 + m_Text: Enter text... +--- !u!222 &472317789 CanvasRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 264728359} + m_GameObject: {fileID: 472317786} m_CullTransparentMesh: 0 --- !u!1 &535739935 GameObject: @@ -564,18 +493,20 @@ MonoBehaviour: m_GameObject: {fileID: 597109994} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0, g: 1, b: 0.22399664, a: 1} + m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 24 + m_FontSize: 20 m_FontStyle: 0 m_BestFit: 0 m_MinSize: 2 @@ -620,12 +551,12 @@ RectTransform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 607305577} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + 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: - {fileID: 597109995} - m_Father: {fileID: 1631056144} + m_Father: {fileID: 1966128035} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} @@ -642,7 +573,7 @@ MonoBehaviour: m_GameObject: {fileID: 607305577} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -651,12 +582,14 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 24 + m_FontSize: 20 m_FontStyle: 0 m_BestFit: 0 - m_MinSize: 0 + m_MinSize: 2 m_MaxSize: 40 m_Alignment: 1 m_AlignByGeometry: 0 @@ -664,7 +597,7 @@ MonoBehaviour: m_HorizontalOverflow: 0 m_VerticalOverflow: 0 m_LineSpacing: 1 - m_Text: 'WINNER:' + m_Text: Winner! --- !u!222 &607305580 CanvasRenderer: m_ObjectHideFlags: 0 @@ -698,12 +631,12 @@ RectTransform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 637114753} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + 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: - {fileID: 1162041874} - m_Father: {fileID: 2086595999} + m_Father: {fileID: 1273045296} m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} @@ -720,7 +653,7 @@ MonoBehaviour: m_GameObject: {fileID: 637114753} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -729,12 +662,14 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 18 + m_FontSize: 14 m_FontStyle: 0 m_BestFit: 0 - m_MinSize: 1 + m_MinSize: 10 m_MaxSize: 40 m_Alignment: 0 m_AlignByGeometry: 0 @@ -776,12 +711,12 @@ RectTransform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 721152070} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + 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: - {fileID: 1278248529} - m_Father: {fileID: 2086595999} + m_Father: {fileID: 1273045296} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 1} @@ -798,7 +733,7 @@ MonoBehaviour: m_GameObject: {fileID: 721152070} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -807,12 +742,14 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 18 + m_FontSize: 14 m_FontStyle: 0 m_BestFit: 0 - m_MinSize: 1 + m_MinSize: 10 m_MaxSize: 40 m_Alignment: 0 m_AlignByGeometry: 0 @@ -829,7 +766,7 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 721152070} m_CullTransparentMesh: 0 ---- !u!1 &1045278707 +--- !u!1 &721760294 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -837,48 +774,47 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1045278708} - - component: {fileID: 1045278711} - - component: {fileID: 1045278710} - - component: {fileID: 1045278709} + - component: {fileID: 721760295} + - component: {fileID: 721760298} + - component: {fileID: 721760297} + - component: {fileID: 721760296} m_Layer: 5 - m_Name: InputField + m_Name: ReadyButton m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &1045278708 +--- !u!224 &721760295 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1045278707} + m_GameObject: {fileID: 721760294} 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: - - {fileID: 2000650900} - - {fileID: 264728360} - m_Father: {fileID: 1423260328} - m_RootOrder: 1 + - {fileID: 20677887} + m_Father: {fileID: 944343261} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 160, y: 30} + m_SizeDelta: {x: 80, y: 30} m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1045278709 +--- !u!114 &721760296 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1045278707} + m_GameObject: {fileID: 721760294} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d199490a83bb2b844b9695cbf13b01ef, type: 3} + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Navigation: @@ -892,56 +828,46 @@ MonoBehaviour: m_NormalColor: {r: 1, g: 1, b: 1, a: 1} m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} m_ColorMultiplier: 1 m_FadeDuration: 0.1 m_SpriteState: m_HighlightedSprite: {fileID: 0} m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} m_DisabledSprite: {fileID: 0} m_AnimationTriggers: m_NormalTrigger: Normal m_HighlightedTrigger: Highlighted m_PressedTrigger: Pressed - m_SelectedTrigger: Highlighted m_DisabledTrigger: Disabled m_Interactable: 1 - m_TargetGraphic: {fileID: 1045278710} - m_TextComponent: {fileID: 264728361} - m_Placeholder: {fileID: 2000650901} - m_ContentType: 4 - m_InputType: 0 - m_AsteriskChar: 42 - m_KeyboardType: 1 - m_LineType: 0 - m_HideMobileInput: 0 - m_CharacterValidation: 3 - m_CharacterLimit: 0 - m_OnEndEdit: - m_PersistentCalls: - m_Calls: [] - m_OnValueChanged: + m_TargetGraphic: {fileID: 721760297} + m_OnClick: m_PersistentCalls: - m_Calls: [] - m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} - m_CustomCaretColor: 0 - m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412} - m_Text: - m_CaretBlinkRate: 0.85 - m_CaretWidth: 1 - m_ReadOnly: 0 ---- !u!114 &1045278710 + m_Calls: + - m_Target: {fileID: 1273045292} + m_MethodName: ReadyButtonHandler + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 1 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &721760297 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1045278707} + m_GameObject: {fileID: 721760294} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -950,7 +876,9 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} m_Type: 1 m_PreserveAspect: 0 m_FillCenter: 1 @@ -959,14 +887,139 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &1045278711 +--- !u!222 &721760298 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 721760294} + m_CullTransparentMesh: 0 +--- !u!1 &754665786 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 754665787} + - component: {fileID: 754665789} + - component: {fileID: 754665788} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &754665787 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 754665786} + 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: 1986496790} + m_RootOrder: 1 + 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.5} + m_SizeDelta: {x: -20, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &754665788 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 754665786} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 0 + m_HorizontalOverflow: 1 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: +--- !u!222 &754665789 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 754665786} + m_CullTransparentMesh: 0 +--- !u!1 &944343260 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 944343261} + - component: {fileID: 944343263} + m_Layer: 5 + m_Name: StartPanel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &944343261 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 944343260} + 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: + - {fileID: 1117608593} + - {fileID: 1986496790} + - {fileID: 721760295} + m_Father: {fileID: 1273045296} + 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: -1080, y: -520} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &944343263 CanvasRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1045278707} + m_GameObject: {fileID: 944343260} m_CullTransparentMesh: 0 --- !u!1 &1107091652 GameObject: @@ -1012,7 +1065,6 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 - m_ReceiveGI: 1 m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -1071,9 +1123,9 @@ GameObject: m_Component: - component: {fileID: 1117608593} - component: {fileID: 1117608595} - - component: {fileID: 1117608594} + - component: {fileID: 1117608596} m_Layer: 5 - m_Name: Text + m_Name: PlayerTextLabel m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -1086,19 +1138,27 @@ RectTransform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1117608592} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + 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: 1423260328} + m_Father: {fileID: 944343261} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 56.86} - m_SizeDelta: {x: 160, y: 90} + m_AnchoredPosition: {x: 0, y: 36.3} + m_SizeDelta: {x: 90, y: 90} m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1117608594 +--- !u!222 &1117608595 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1117608592} + m_CullTransparentMesh: 0 +--- !u!114 &1117608596 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1107,39 +1167,31 @@ MonoBehaviour: m_GameObject: {fileID: 1117608592} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.8301887, g: 0.8301887, b: 0.8301887, a: 1} + m_Color: {r: 1, g: 1, b: 1, a: 1} m_RaycastTarget: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 32 + m_FontSize: 14 m_FontStyle: 0 m_BestFit: 0 - m_MinSize: 2 + m_MinSize: 10 m_MaxSize: 40 - m_Alignment: 4 + m_Alignment: 0 m_AlignByGeometry: 0 m_RichText: 1 m_HorizontalOverflow: 0 m_VerticalOverflow: 0 m_LineSpacing: 1 - m_Text: 'Mirror - - Tanks' ---- !u!222 &1117608595 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1117608592} - m_CullTransparentMesh: 0 + m_Text: 'Player Name:' --- !u!1 &1162041873 GameObject: m_ObjectHideFlags: 0 @@ -1186,7 +1238,7 @@ MonoBehaviour: m_GameObject: {fileID: 1162041873} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -1195,12 +1247,14 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 18 + m_FontSize: 14 m_FontStyle: 0 m_BestFit: 0 - m_MinSize: 1 + m_MinSize: 10 m_MaxSize: 40 m_Alignment: 0 m_AlignByGeometry: 0 @@ -1217,7 +1271,7 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1162041873} m_CullTransparentMesh: 0 ---- !u!1 &1278248528 +--- !u!1 &1273045291 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1225,28 +1279,156 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1278248529} - - component: {fileID: 1278248531} - - component: {fileID: 1278248530} + - component: {fileID: 1273045296} + - component: {fileID: 1273045295} + - component: {fileID: 1273045294} + - component: {fileID: 1273045293} + - component: {fileID: 1273045292} m_Layer: 5 - m_Name: HealthText + m_Name: Canvas m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &1278248529 -RectTransform: +--- !u!114 &1273045292 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1278248528} - 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: 721152071} + m_GameObject: {fileID: 1273045291} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 21139f03d4abf3b4dbeb308fa6c880ef, type: 3} + m_Name: + m_EditorClassIdentifier: + MinimumPlayersForGame: 1 + LocalPlayer: {fileID: 0} + StartPanel: {fileID: 944343260} + GameOverPanel: {fileID: 1966128034} + HealthTextLabel: {fileID: 721152070} + ScoreTextLabel: {fileID: 637114753} + HealthText: {fileID: 1278248530} + ScoreText: {fileID: 1162041875} + PlayerNameText: {fileID: 754665788} + WinnerNameText: {fileID: 597109996} + IsGameReady: 0 + IsGameOver: 0 + players: [] +--- !u!114 &1273045293 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1273045291} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1273045294 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1273045291} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, 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 &1273045295 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1273045291} + 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 &1273045296 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1273045291} + 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: 944343261} + - {fileID: 721152071} + - {fileID: 637114754} + - {fileID: 1966128035} + m_Father: {fileID: 0} + m_RootOrder: 8 + 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 &1278248528 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1278248529} + - component: {fileID: 1278248531} + - component: {fileID: 1278248530} + m_Layer: 5 + m_Name: HealthText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1278248529 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1278248528} + 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: 721152071} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} @@ -1263,7 +1445,7 @@ MonoBehaviour: m_GameObject: {fileID: 1278248528} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -1272,12 +1454,14 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 18 + m_FontSize: 14 m_FontStyle: 0 m_BestFit: 0 - m_MinSize: 1 + m_MinSize: 10 m_MaxSize: 40 m_Alignment: 0 m_AlignByGeometry: 0 @@ -1285,9 +1469,7 @@ MonoBehaviour: m_HorizontalOverflow: 0 m_VerticalOverflow: 0 m_LineSpacing: 1 - m_Text: ' - -' + m_Text: --- !u!222 &1278248531 CanvasRenderer: m_ObjectHideFlags: 0 @@ -1390,109 +1572,47 @@ MonoBehaviour: OnClientConnected: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null OnClientDataReceived: m_PersistentCalls: m_Calls: [] + m_TypeName: Mirror.ClientDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null OnClientError: m_PersistentCalls: m_Calls: [] + m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null OnClientDisconnected: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null OnServerConnected: m_PersistentCalls: m_Calls: [] + m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null OnServerDataReceived: m_PersistentCalls: m_Calls: [] + m_TypeName: Mirror.ServerDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null OnServerError: m_PersistentCalls: m_Calls: [] + m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null OnServerDisconnected: m_PersistentCalls: m_Calls: [] + m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null port: 7777 NoDelay: 1 serverMaxMessageSize: 16384 serverMaxReceivesPerTick: 10000 clientMaxMessageSize: 16384 clientMaxReceivesPerTick: 1000 ---- !u!1 &1423260327 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1423260328} - - component: {fileID: 1423260330} - - component: {fileID: 1423260329} - m_Layer: 5 - m_Name: StartPanel - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!224 &1423260328 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1423260327} - 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: - - {fileID: 1117608593} - - {fileID: 1045278708} - - {fileID: 1902988042} - m_Father: {fileID: 2086595999} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 200, y: 200} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1423260329 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1423260327} - 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.050929725, b: 0.27450982, a: 0.78431374} - m_RaycastTarget: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 &1423260330 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1423260327} - m_CullTransparentMesh: 0 --- !u!1 &1458789072 GameObject: m_ObjectHideFlags: 0 @@ -1579,7 +1699,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} m_Name: m_EditorClassIdentifier: ---- !u!1 &1631056143 +--- !u!1 &1633146726 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1587,9 +1707,75 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1631056144} - - component: {fileID: 1631056146} - - component: {fileID: 1631056145} + - component: {fileID: 1633146729} + - component: {fileID: 1633146728} + - component: {fileID: 1633146727} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1633146727 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633146726} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, 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 &1633146728 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633146726} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1633146729 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1633146726} + 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: 9 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1966128034 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1966128035} + - component: {fileID: 1966128037} + - component: {fileID: 1966128036} m_Layer: 5 m_Name: GameOverPanel m_TagString: Untagged @@ -1597,19 +1783,19 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 0 ---- !u!224 &1631056144 +--- !u!224 &1966128035 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1631056143} + m_GameObject: {fileID: 1966128034} 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: - {fileID: 607305578} - m_Father: {fileID: 2086595999} + m_Father: {fileID: 1273045296} m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} @@ -1617,24 +1803,26 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 300, y: 100} m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1631056145 +--- !u!114 &1966128036 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1631056143} + m_GameObject: {fileID: 1966128034} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} - m_Color: {r: 0.084905684, g: 0.084905684, b: 0.084905684, a: 0.76862746} + m_Color: {r: 1, g: 1, b: 1, a: 0.392} m_RaycastTarget: 1 m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} m_Type: 1 m_PreserveAspect: 0 @@ -1644,16 +1832,15 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &1631056146 +--- !u!222 &1966128037 CanvasRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1631056143} + m_GameObject: {fileID: 1966128034} m_CullTransparentMesh: 0 ---- !u!1 &1902988041 +--- !u!1 &1986496789 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1661,47 +1848,48 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1902988042} - - component: {fileID: 1902988045} - - component: {fileID: 1902988044} - - component: {fileID: 1902988043} + - component: {fileID: 1986496790} + - component: {fileID: 1986496793} + - component: {fileID: 1986496792} + - component: {fileID: 1986496791} m_Layer: 5 - m_Name: ReadyButton + m_Name: InputField m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &1902988042 +--- !u!224 &1986496790 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1902988041} + m_GameObject: {fileID: 1986496789} 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: - - {fileID: 16255282} - m_Father: {fileID: 1423260328} - m_RootOrder: 2 + - {fileID: 472317787} + - {fileID: 754665787} + m_Father: {fileID: 944343261} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: -35} + m_AnchoredPosition: {x: 0, y: 40} m_SizeDelta: {x: 160, y: 30} m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &1902988043 +--- !u!114 &1986496791 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1902988041} + m_GameObject: {fileID: 1986496789} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Script: {fileID: 575553740, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Navigation: @@ -1715,47 +1903,57 @@ MonoBehaviour: m_NormalColor: {r: 1, g: 1, b: 1, a: 1} m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} - m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} m_ColorMultiplier: 1 m_FadeDuration: 0.1 m_SpriteState: m_HighlightedSprite: {fileID: 0} m_PressedSprite: {fileID: 0} - m_SelectedSprite: {fileID: 0} m_DisabledSprite: {fileID: 0} m_AnimationTriggers: m_NormalTrigger: Normal m_HighlightedTrigger: Highlighted m_PressedTrigger: Pressed - m_SelectedTrigger: Highlighted m_DisabledTrigger: Disabled m_Interactable: 1 - m_TargetGraphic: {fileID: 1902988044} - m_OnClick: + m_TargetGraphic: {fileID: 1986496792} + m_TextComponent: {fileID: 754665788} + m_Placeholder: {fileID: 472317788} + m_ContentType: 0 + m_InputType: 0 + m_AsteriskChar: 42 + m_KeyboardType: 0 + m_LineType: 0 + m_HideMobileInput: 0 + m_CharacterValidation: 0 + m_CharacterLimit: 0 + m_OnEndEdit: m_PersistentCalls: - m_Calls: - - m_Target: {fileID: 2086596000} - m_MethodName: ReadyButtonHandler - m_Mode: 1 - m_Arguments: - m_ObjectArgument: {fileID: 0} - m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine - m_IntArgument: 0 - m_FloatArgument: 0 - m_StringArgument: - m_BoolArgument: 0 - m_CallState: 1 ---- !u!114 &1902988044 + m_Calls: [] + m_TypeName: UnityEngine.UI.InputField+SubmitEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.InputField+OnChangeEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null + m_CaretColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_CustomCaretColor: 0 + m_SelectionColor: {r: 0.65882355, g: 0.80784315, b: 1, a: 0.7529412} + m_Text: + m_CaretBlinkRate: 0.85 + m_CaretWidth: 1 + m_ReadOnly: 0 +--- !u!114 &1986496792 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1902988041} + m_GameObject: {fileID: 1986496789} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} m_Name: m_EditorClassIdentifier: m_Material: {fileID: 0} @@ -1764,7 +1962,9 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10911, guid: 0000000000000000f000000000000000, type: 0} m_Type: 1 m_PreserveAspect: 0 m_FillCenter: 1 @@ -1773,91 +1973,13 @@ MonoBehaviour: m_FillClockwise: 1 m_FillOrigin: 0 m_UseSpriteMesh: 0 - m_PixelsPerUnitMultiplier: 1 ---- !u!222 &1902988045 -CanvasRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1902988041} - m_CullTransparentMesh: 0 ---- !u!1 &2000650899 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2000650900} - - component: {fileID: 2000650902} - - component: {fileID: 2000650901} - m_Layer: 5 - m_Name: Placeholder - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &2000650900 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2000650899} - 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: 1045278708} - 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.5} - m_SizeDelta: {x: -20, y: -13} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!114 &2000650901 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2000650899} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5} - m_RaycastTarget: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_FontData: - m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 14 - m_FontStyle: 2 - m_BestFit: 0 - m_MinSize: 10 - m_MaxSize: 40 - m_Alignment: 0 - m_AlignByGeometry: 0 - m_RichText: 1 - m_HorizontalOverflow: 0 - m_VerticalOverflow: 0 - m_LineSpacing: 1 - m_Text: Enter PlayerName... ---- !u!222 &2000650902 +--- !u!222 &1986496793 CanvasRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2000650899} + m_GameObject: {fileID: 1986496789} m_CullTransparentMesh: 0 --- !u!1 &2054208274 GameObject: @@ -1884,13 +2006,12 @@ Light: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2054208274} m_Enabled: 1 - serializedVersion: 9 + serializedVersion: 8 m_Type: 1 m_Color: {r: 1, g: 1, b: 1, a: 1} m_Intensity: 1 m_Range: 10 m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 m_CookieSize: 10 m_Shadows: m_Type: 2 @@ -1900,24 +2021,6 @@ Light: 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} @@ -1925,15 +2028,12 @@ Light: 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 &2054208276 @@ -1950,131 +2050,3 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 50, y: 150, z: 0} ---- !u!1 &2086595995 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2086595999} - - component: {fileID: 2086595998} - - component: {fileID: 2086595997} - - component: {fileID: 2086595996} - - component: {fileID: 2086596000} - m_Layer: 5 - m_Name: Canvas - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &2086595996 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2086595995} - 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 &2086595997 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2086595995} - 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 &2086595998 -Canvas: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2086595995} - 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 &2086595999 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2086595995} - 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: 1423260328} - - {fileID: 721152071} - - {fileID: 637114754} - - {fileID: 1631056144} - m_Father: {fileID: 0} - m_RootOrder: 8 - 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!114 &2086596000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2086595995} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 21139f03d4abf3b4dbeb308fa6c880ef, type: 3} - m_Name: - m_EditorClassIdentifier: - MinimumPlayersForGame: 1 - LocalPlayer: {fileID: 0} - StartPanel: {fileID: 1423260327} - GameOverPanel: {fileID: 1631056143} - HealthTextLabel: {fileID: 721152070} - ScoreTextLabel: {fileID: 637114753} - HealthText: {fileID: 1278248530} - ScoreText: {fileID: 1162041875} - PlayerNameText: {fileID: 264728361} - WinnerNameText: {fileID: 597109996} - IsGameReady: 0 - IsGameOver: 0 - players: [] From a05df81127d9dc44b978329d4d50babde9b83ad6 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 21 Jun 2020 10:52:32 +0100 Subject: [PATCH 16/57] adding if before starting task (#2021) --- Assets/Mirror/Runtime/Transport/Websocket/Client.cs | 12 +++++++++--- Assets/Mirror/Runtime/Transport/Websocket/Server.cs | 12 +++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Assets/Mirror/Runtime/Transport/Websocket/Client.cs b/Assets/Mirror/Runtime/Transport/Websocket/Client.cs index 56c82206..4f8c36c5 100644 --- a/Assets/Mirror/Runtime/Transport/Websocket/Client.cs +++ b/Assets/Mirror/Runtime/Transport/Websocket/Client.cs @@ -89,7 +89,10 @@ async Task ReceiveLoop(WebSocket webSocket, CancellationToken token) { WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - await Task.Run(WaitForEnabled); + if (!enabled) + { + await WaitForEnabledAsync(); + } if (result == null) break; @@ -113,9 +116,12 @@ async Task ReceiveLoop(WebSocket webSocket, CancellationToken token) } } - void WaitForEnabled() + async Task WaitForEnabledAsync() { - while (!enabled) { Task.Delay(10); } + while (!enabled) + { + await Task.Delay(10); + } } public bool ProcessClientMessage() diff --git a/Assets/Mirror/Runtime/Transport/Websocket/Server.cs b/Assets/Mirror/Runtime/Transport/Websocket/Server.cs index 02bc1b07..8418b089 100644 --- a/Assets/Mirror/Runtime/Transport/Websocket/Server.cs +++ b/Assets/Mirror/Runtime/Transport/Websocket/Server.cs @@ -196,7 +196,10 @@ async Task ReceiveLoopAsync(WebSocket webSocket, CancellationToken token) { WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); - await Task.Run(WaitForEnabled); + if (!enabled) + { + await WaitForEnabledAsync(); + } if (result.MessageType == WebSocketMessageType.Close) { @@ -232,9 +235,12 @@ async Task ReceiveLoopAsync(WebSocket webSocket, CancellationToken token) } } - void WaitForEnabled() + async Task WaitForEnabledAsync() { - while (!enabled) { Task.Delay(10); } + while (!enabled) + { + await Task.Delay(10); + } } // a message might come splitted in multiple frames From 3bea342257732030d0b0d0eb69a8f9d90011776c Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 21 Jun 2020 10:54:11 +0100 Subject: [PATCH 17/57] rethrow error with stack (#2013) this will help error be more useful --- Assets/Mirror/Editor/Weaver/Weaver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Mirror/Editor/Weaver/Weaver.cs b/Assets/Mirror/Editor/Weaver/Weaver.cs index 0fc918ab..a62e4850 100644 --- a/Assets/Mirror/Editor/Weaver/Weaver.cs +++ b/Assets/Mirror/Editor/Weaver/Weaver.cs @@ -562,7 +562,7 @@ static bool WeaveModule(ModuleDefinition moduleDefinition) catch (Exception ex) { Error(ex.ToString()); - throw ex; + throw; } } From f18f7a5c3ddb6b7d481a6b318ff828ebcff65cb8 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 21 Jun 2020 11:06:07 +0100 Subject: [PATCH 18/57] making sure that trigger is called on the server (#1998) --- Assets/Mirror/Components/NetworkAnimator.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Mirror/Components/NetworkAnimator.cs b/Assets/Mirror/Components/NetworkAnimator.cs index 9a8c4509..c188ea94 100644 --- a/Assets/Mirror/Components/NetworkAnimator.cs +++ b/Assets/Mirror/Components/NetworkAnimator.cs @@ -392,6 +392,7 @@ public void SetTrigger(int hash) return; } + HandleAnimTriggerMsg(hash); RpcOnAnimationTriggerClientMessage(hash); } } @@ -437,6 +438,7 @@ public void ResetTrigger(int hash) return; } + HandleAnimResetTriggerMsg(hash); RpcOnAnimationResetTriggerClientMessage(hash); } } @@ -520,6 +522,7 @@ void RpcOnAnimationParametersClientMessage(byte[] parameters) [ClientRpc] void RpcOnAnimationTriggerClientMessage(int hash) { + // host handles this before it is sent if (isServer) return; HandleAnimTriggerMsg(hash); @@ -528,6 +531,7 @@ void RpcOnAnimationTriggerClientMessage(int hash) [ClientRpc] void RpcOnAnimationResetTriggerClientMessage(int hash) { + // host handles this before it is sent if (isServer) return; HandleAnimResetTriggerMsg(hash); From 296f6f9cd8fcf4c778c3902b35e1fec95a05f7ab Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 21 Jun 2020 11:06:37 +0100 Subject: [PATCH 19/57] Only setting last parameters values if they have changed (#1999) * only setting last values if they have changed * adding comment --- Assets/Mirror/Components/NetworkAnimator.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Assets/Mirror/Components/NetworkAnimator.cs b/Assets/Mirror/Components/NetworkAnimator.cs index c188ea94..599135fe 100644 --- a/Assets/Mirror/Components/NetworkAnimator.cs +++ b/Assets/Mirror/Components/NetworkAnimator.cs @@ -222,19 +222,23 @@ ulong NextDirtyBits() { int newIntValue = animator.GetInteger(par.nameHash); changed = newIntValue != lastIntParameters[i]; - lastIntParameters[i] = newIntValue; + if (changed) + lastIntParameters[i] = newIntValue; } else if (par.type == AnimatorControllerParameterType.Float) { float newFloatValue = animator.GetFloat(par.nameHash); changed = Mathf.Abs(newFloatValue - lastFloatParameters[i]) > 0.001f; - lastFloatParameters[i] = newFloatValue; + // only set lastValue if it was changed, otherwise value could slowly drift within the 0.001f limit each frame + if (changed) + lastFloatParameters[i] = newFloatValue; } else if (par.type == AnimatorControllerParameterType.Bool) { bool newBoolValue = animator.GetBool(par.nameHash); changed = newBoolValue != lastBoolParameters[i]; - lastBoolParameters[i] = newBoolValue; + if (changed) + lastBoolParameters[i] = newBoolValue; } if (changed) { From 065d32020866fb95b3686b30eb42dda43d9085ca Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 21 Jun 2020 11:09:24 +0100 Subject: [PATCH 20/57] calling animator.enabled before calls to animator (#2000) some functions don't need this check as the check is done before they are called --- Assets/Mirror/Components/NetworkAnimator.cs | 24 +++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Assets/Mirror/Components/NetworkAnimator.cs b/Assets/Mirror/Components/NetworkAnimator.cs index 599135fe..439746b5 100644 --- a/Assets/Mirror/Components/NetworkAnimator.cs +++ b/Assets/Mirror/Components/NetworkAnimator.cs @@ -85,6 +85,9 @@ void FixedUpdate() if (!SendMessagesAllowed) return; + if (!animator.enabled) + return; + CheckSendRate(); for (int i = 0; i < animator.layerCount; i++) @@ -187,7 +190,8 @@ void HandleAnimMsg(int stateHash, float normalizedTime, int layerId, NetworkRead // NOTE: there is no API to play a transition(?) if (stateHash != 0) { - animator.Play(stateHash, layerId, normalizedTime); + if (animator.enabled) + animator.Play(stateHash, layerId, normalizedTime); } ReadParameters(reader); @@ -203,12 +207,14 @@ void HandleAnimParamsMsg(NetworkReader reader) void HandleAnimTriggerMsg(int hash) { - animator.SetTrigger(hash); + if (animator.enabled) + animator.SetTrigger(hash); } void HandleAnimResetTriggerMsg(int hash) { - animator.ResetTrigger(hash); + if (animator.enabled) + animator.ResetTrigger(hash); } ulong NextDirtyBits() @@ -279,6 +285,9 @@ bool WriteParameters(NetworkWriter writer, bool forceAll = false) void ReadParameters(NetworkReader reader) { + bool animatorEnabled = animator.enabled; + // need to read values from NetworkReader even if animator is disabled + ulong dirtyBits = reader.ReadPackedUInt64(); for (int i = 0; i < parameters.Length; i++) { @@ -289,17 +298,20 @@ void ReadParameters(NetworkReader reader) if (par.type == AnimatorControllerParameterType.Int) { int newIntValue = reader.ReadPackedInt32(); - animator.SetInteger(par.nameHash, newIntValue); + if (animatorEnabled) + animator.SetInteger(par.nameHash, newIntValue); } else if (par.type == AnimatorControllerParameterType.Float) { float newFloatValue = reader.ReadSingle(); - animator.SetFloat(par.nameHash, newFloatValue); + if (animatorEnabled) + animator.SetFloat(par.nameHash, newFloatValue); } else if (par.type == AnimatorControllerParameterType.Bool) { bool newBoolValue = reader.ReadBoolean(); - animator.SetBool(par.nameHash, newBoolValue); + if (animatorEnabled) + animator.SetBool(par.nameHash, newBoolValue); } } } From 5b05c46da7bd51508ef759d46dbde81a9bfd2c35 Mon Sep 17 00:00:00 2001 From: Callum Ferguson Date: Tue, 23 Jun 2020 04:11:16 -0400 Subject: [PATCH 21/57] Update discord invite (#2025) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f69b9596..2b3eb9ea 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Following these guidelines helps to communicate that you respect the time of the This is an open source project and we love to receive contributions from our community — you! There are many ways to contribute, from writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into the main project itself. -If you haven't already, come find us in [Discord](https://discord.gg/yTYe3h). We want you working on things you're excited about, and we can give you instant feedback. +If you haven't already, come find us in [Discord](https://discord.gg/N9QVxbM). We want you working on things you're excited about, and we can give you instant feedback. ### I don't want to read this whole thing I just have a question!! From f1fdc959dcd62e7228ecfd656bc87cbabca8c1bc Mon Sep 17 00:00:00 2001 From: James Frowen Date: Tue, 23 Jun 2020 19:39:38 +0100 Subject: [PATCH 22/57] feat: adding demo for mirror cloud services (#2026) * adding mirror list services * fixing code smells * removing runtime example folders * removing matchmaking code till feature is ready * fixing scene path * updating readme to say where example is --- Assets/Mirror/Cloud.meta | 8 + Assets/Mirror/Cloud/ApiConnector.cs | 61 + Assets/Mirror/Cloud/ApiConnector.cs.meta | 11 + Assets/Mirror/Cloud/Core.meta | 8 + Assets/Mirror/Cloud/Core/BaseApi.cs | 25 + Assets/Mirror/Cloud/Core/BaseApi.cs.meta | 11 + Assets/Mirror/Cloud/Core/Events.cs | 12 + Assets/Mirror/Cloud/Core/Events.cs.meta | 11 + Assets/Mirror/Cloud/Core/Extensions.cs | 12 + Assets/Mirror/Cloud/Core/Extensions.cs.meta | 11 + Assets/Mirror/Cloud/Core/ICoroutineRunner.cs | 12 + .../Cloud/Core/ICoroutineRunner.cs.meta | 11 + Assets/Mirror/Cloud/Core/IRequestCreator.cs | 42 + .../Mirror/Cloud/Core/IRequestCreator.cs.meta | 11 + Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs | 26 + .../Cloud/Core/IUnityEqualCheck.cs.meta | 11 + Assets/Mirror/Cloud/Core/JsonStructs.cs | 24 + Assets/Mirror/Cloud/Core/JsonStructs.cs.meta | 11 + Assets/Mirror/Cloud/Core/Logger.cs | 65 + Assets/Mirror/Cloud/Core/Logger.cs.meta | 11 + Assets/Mirror/Cloud/Core/RequestCreator.cs | 144 + .../Mirror/Cloud/Core/RequestCreator.cs.meta | 11 + Assets/Mirror/Cloud/ListServer.meta | 8 + Assets/Mirror/Cloud/ListServer/ListServer.cs | 66 + .../Cloud/ListServer/ListServer.cs.meta | 11 + .../Cloud/ListServer/ListServerBaseApi.cs | 9 + .../ListServer/ListServerBaseApi.cs.meta | 11 + .../Cloud/ListServer/ListServerClientApi.cs | 70 + .../ListServer/ListServerClientApi.cs.meta | 11 + .../Mirror/Cloud/ListServer/ListServerJson.cs | 45 + .../Cloud/ListServer/ListServerJson.cs.meta | 11 + .../Cloud/ListServer/ListServerServerApi.cs | 222 ++ .../ListServer/ListServerServerApi.cs.meta | 11 + .../Mirror/Cloud/Mirror.CloudServices.asmdef | 14 + .../Cloud/Mirror.CloudServices.asmdef.meta | 7 + Assets/Mirror/Cloud/README.md | 12 + Assets/Mirror/Cloud/README.md.meta | 7 + Assets/Mirror/Cloud/version.txt | 1 + Assets/Mirror/Cloud/version.txt.meta | 7 + .../Mirror/Examples/PongWithListServer.meta | 8 + .../PongWithListServer/PhysicsMaterials.meta | 8 + .../BallMaterial.physicsMaterial2D | 11 + .../BallMaterial.physicsMaterial2D.meta | 8 + .../Examples/PongWithListServer/Prefabs.meta | 8 + .../PongWithListServer/Prefabs/Ball.prefab | 183 ++ .../Prefabs/Ball.prefab.meta | 7 + .../Prefabs/ListServer Canvas.prefab | 2693 +++++++++++++++++ .../Prefabs/ListServer Canvas.prefab.meta | 7 + .../Prefabs/NetworkManager.prefab | 154 + .../Prefabs/NetworkManager.prefab.meta | 7 + .../PongWithListServer/Prefabs/Racket.prefab | 185 ++ .../Prefabs/Racket.prefab.meta | 7 + .../Prefabs/ServerListItem.prefab | 640 ++++ .../Prefabs/ServerListItem.prefab.meta | 7 + .../Examples/PongWithListServer/Scenes.meta | 8 + .../Scenes/ListServerLobbyScene.unity | 615 ++++ .../Scenes/ListServerLobbyScene.unity.meta | 7 + .../Scenes/PongGameScene.unity | 958 ++++++ .../Scenes/PongGameScene.unity.meta | 7 + .../Examples/PongWithListServer/Scripts.meta | 8 + .../PongWithListServer/Scripts/ApiUpdater.cs | 83 + .../Scripts/ApiUpdater.cs.meta | 11 + .../Scripts/InstantiateNetworkManager.cs | 17 + .../Scripts/InstantiateNetworkManager.cs.meta | 11 + .../Mirror.Examples.CloudService.asmdef | 16 + .../Mirror.Examples.CloudService.asmdef.meta | 7 + .../Scripts/NetworkManagerListServerPong.cs | 55 + .../NetworkManagerListServerPong.cs.meta | 11 + .../PongWithListServer/Scripts/Pong.meta | 8 + .../PongWithListServer/Scripts/Pong/Ball.cs | 61 + .../Scripts/Pong/Ball.cs.meta | 11 + .../Scripts/Pong/BallManager.cs | 53 + .../Scripts/Pong/BallManager.cs.meta | 11 + .../PongWithListServer/Scripts/Pong/Player.cs | 21 + .../Scripts/Pong/Player.cs.meta | 11 + .../PongWithListServer/Scripts/QuitButton.cs | 36 + .../Scripts/QuitButton.cs.meta | 11 + .../Scripts/ServerListManager.cs | 63 + .../Scripts/ServerListManager.cs.meta | 11 + .../Scripts/ServerListUI.cs | 48 + .../Scripts/ServerListUI.cs.meta | 11 + .../Scripts/ServerListUIItem.cs | 34 + .../Scripts/ServerListUIItem.cs.meta | 11 + .../Examples/PongWithListServer/Sprites.meta | 8 + .../PongWithListServer/Sprites/Ball.png | Bin 0 -> 2791 bytes .../PongWithListServer/Sprites/Ball.png.meta | 88 + .../PongWithListServer/Sprites/DottedLine.png | Bin 0 -> 2799 bytes .../Sprites/DottedLine.png.meta | 88 + .../PongWithListServer/Sprites/Racket.png | Bin 0 -> 2800 bytes .../Sprites/Racket.png.meta | 88 + .../Sprites/WallHorizontal.png | Bin 0 -> 2796 bytes .../Sprites/WallHorizontal.png.meta | 88 + .../Sprites/WallVertical.png | Bin 0 -> 2800 bytes .../Sprites/WallVertical.png.meta | 88 + 94 files changed, 7668 insertions(+) create mode 100644 Assets/Mirror/Cloud.meta create mode 100644 Assets/Mirror/Cloud/ApiConnector.cs create mode 100644 Assets/Mirror/Cloud/ApiConnector.cs.meta create mode 100644 Assets/Mirror/Cloud/Core.meta create mode 100644 Assets/Mirror/Cloud/Core/BaseApi.cs create mode 100644 Assets/Mirror/Cloud/Core/BaseApi.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/Events.cs create mode 100644 Assets/Mirror/Cloud/Core/Events.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/Extensions.cs create mode 100644 Assets/Mirror/Cloud/Core/Extensions.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/ICoroutineRunner.cs create mode 100644 Assets/Mirror/Cloud/Core/ICoroutineRunner.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/IRequestCreator.cs create mode 100644 Assets/Mirror/Cloud/Core/IRequestCreator.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs create mode 100644 Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/JsonStructs.cs create mode 100644 Assets/Mirror/Cloud/Core/JsonStructs.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/Logger.cs create mode 100644 Assets/Mirror/Cloud/Core/Logger.cs.meta create mode 100644 Assets/Mirror/Cloud/Core/RequestCreator.cs create mode 100644 Assets/Mirror/Cloud/Core/RequestCreator.cs.meta create mode 100644 Assets/Mirror/Cloud/ListServer.meta create mode 100644 Assets/Mirror/Cloud/ListServer/ListServer.cs create mode 100644 Assets/Mirror/Cloud/ListServer/ListServer.cs.meta create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs.meta create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs.meta create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerJson.cs create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerJson.cs.meta create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs create mode 100644 Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs.meta create mode 100644 Assets/Mirror/Cloud/Mirror.CloudServices.asmdef create mode 100644 Assets/Mirror/Cloud/Mirror.CloudServices.asmdef.meta create mode 100644 Assets/Mirror/Cloud/README.md create mode 100644 Assets/Mirror/Cloud/README.md.meta create mode 100644 Assets/Mirror/Cloud/version.txt create mode 100644 Assets/Mirror/Cloud/version.txt.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D create mode 100644 Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab create mode 100644 Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scenes.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Pong.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs create mode 100644 Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/DottedLine.png create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/DottedLine.png.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/Racket.png create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/Racket.png.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/WallHorizontal.png create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/WallHorizontal.png.meta create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/WallVertical.png create mode 100644 Assets/Mirror/Examples/PongWithListServer/Sprites/WallVertical.png.meta diff --git a/Assets/Mirror/Cloud.meta b/Assets/Mirror/Cloud.meta new file mode 100644 index 00000000..e2c44def --- /dev/null +++ b/Assets/Mirror/Cloud.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 73a9bb2dacafa8141bce8feef34e33a7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/ApiConnector.cs b/Assets/Mirror/Cloud/ApiConnector.cs new file mode 100644 index 00000000..21b0c546 --- /dev/null +++ b/Assets/Mirror/Cloud/ApiConnector.cs @@ -0,0 +1,61 @@ +using Mirror.CloudServices.ListServerService; +using UnityEngine; + +namespace Mirror.CloudServices +{ + /// + /// Used to requests and responses from the mirror api + /// + public interface IApiConnector + { + ListServer ListServer { get; } + } + + /// + /// Used to requests and responses from the mirror api + /// + [DisallowMultipleComponent] + [AddComponentMenu("Network/CloudServices/ApiConnector")] + [HelpURL("https://mirror-networking.com/docs/CloudServices/ApiConnector.html")] + public class ApiConnector : MonoBehaviour, IApiConnector, ICoroutineRunner + { + #region Inspector + [Header("Settings")] + + [Tooltip("Base URL of api, including https")] + [SerializeField] string ApiAddress = ""; + + [Tooltip("Api key required to access api")] + [SerializeField] string ApiKey = ""; + + [Header("Events")] + + [Tooltip("Triggered when server list updates")] + [SerializeField] ServerListEvent _onServerListUpdated = new ServerListEvent(); + #endregion + + IRequestCreator requestCreator; + + public ListServer ListServer { get; private set; } + + void Awake() + { + requestCreator = new RequestCreator(ApiAddress, ApiKey, this); + + InitListServer(); + } + + void InitListServer() + { + IListServerServerApi serverApi = new ListServerServerApi(this, requestCreator); + IListServerClientApi clientApi = new ListServerClientApi(this, requestCreator, _onServerListUpdated); + ListServer = new ListServer(serverApi, clientApi); + } + + public void OnDestroy() + { + ListServer.ServerApi.Shutdown(); + ListServer.ClientApi.Shutdown(); + } + } +} diff --git a/Assets/Mirror/Cloud/ApiConnector.cs.meta b/Assets/Mirror/Cloud/ApiConnector.cs.meta new file mode 100644 index 00000000..9279c0cc --- /dev/null +++ b/Assets/Mirror/Cloud/ApiConnector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bdb99a29e179d14cb0acc43f175d9ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core.meta b/Assets/Mirror/Cloud/Core.meta new file mode 100644 index 00000000..8c000591 --- /dev/null +++ b/Assets/Mirror/Cloud/Core.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3f34c32971e65984c93a15376ec11c65 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/BaseApi.cs b/Assets/Mirror/Cloud/Core/BaseApi.cs new file mode 100644 index 00000000..520360cd --- /dev/null +++ b/Assets/Mirror/Cloud/Core/BaseApi.cs @@ -0,0 +1,25 @@ +using System; + +namespace Mirror.CloudServices +{ + public interface IBaseApi + { + /// + /// Cleans up any data created by the instance + /// For Example: removing server from list + /// + void Shutdown(); + } + + public abstract class BaseApi + { + protected readonly ICoroutineRunner runner; + protected readonly IRequestCreator requestCreator; + + protected BaseApi(ICoroutineRunner runner, IRequestCreator requestCreator) + { + this.runner = runner ?? throw new ArgumentNullException(nameof(runner)); + this.requestCreator = requestCreator ?? throw new ArgumentNullException(nameof(requestCreator)); + } + } +} diff --git a/Assets/Mirror/Cloud/Core/BaseApi.cs.meta b/Assets/Mirror/Cloud/Core/BaseApi.cs.meta new file mode 100644 index 00000000..f66b84e1 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/BaseApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70f563b7a7210ae43bbcde5cb7721a94 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/Events.cs b/Assets/Mirror/Cloud/Core/Events.cs new file mode 100644 index 00000000..7c61d323 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/Events.cs @@ -0,0 +1,12 @@ +using System; +using Mirror.CloudServices.ListServerService; +using UnityEngine.Events; + +namespace Mirror.CloudServices +{ + [Serializable] + public class ServerListEvent : UnityEvent { } + + [Serializable] + public class MatchFoundEvent : UnityEvent { } +} diff --git a/Assets/Mirror/Cloud/Core/Events.cs.meta b/Assets/Mirror/Cloud/Core/Events.cs.meta new file mode 100644 index 00000000..150d85b2 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/Events.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7c472a3ea1bc4348bd5a0b05bf7cc3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/Extensions.cs b/Assets/Mirror/Cloud/Core/Extensions.cs new file mode 100644 index 00000000..1c728bdc --- /dev/null +++ b/Assets/Mirror/Cloud/Core/Extensions.cs @@ -0,0 +1,12 @@ +using UnityEngine.Networking; + +namespace Mirror.CloudServices +{ + public static class Extensions + { + public static bool IsOk(this UnityWebRequest webRequest) + { + return 200 <= webRequest.responseCode && webRequest.responseCode <= 299; + } + } +} diff --git a/Assets/Mirror/Cloud/Core/Extensions.cs.meta b/Assets/Mirror/Cloud/Core/Extensions.cs.meta new file mode 100644 index 00000000..6bf6291e --- /dev/null +++ b/Assets/Mirror/Cloud/Core/Extensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97501e783fc67a4459b15d10e6c63563 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs b/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs new file mode 100644 index 00000000..82ac5f91 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs @@ -0,0 +1,12 @@ +using System.Collections; +using UnityEngine; + +namespace Mirror.CloudServices +{ + public interface ICoroutineRunner : IUnityEqualCheck + { + Coroutine StartCoroutine(IEnumerator routine); + void StopCoroutine(IEnumerator routine); + void StopCoroutine(Coroutine routine); + } +} diff --git a/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs.meta b/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs.meta new file mode 100644 index 00000000..f1149a99 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 43472c60a7c72e54eafe559290dd0fc6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/IRequestCreator.cs b/Assets/Mirror/Cloud/Core/IRequestCreator.cs new file mode 100644 index 00000000..84776b92 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/IRequestCreator.cs @@ -0,0 +1,42 @@ +using System.Collections; +using UnityEngine.Networking; + +namespace Mirror.CloudServices +{ + public delegate void RequestSuccess(string responseBody); + + public delegate void RequestFail(string responseBody); + + /// + /// Objects that can be sent to the Api must have this interface + /// + public interface ICanBeJson { } + + /// + /// Methods to create and send UnityWebRequest + /// + public interface IRequestCreator + { + UnityWebRequest Delete(string page); + UnityWebRequest Get(string page); + UnityWebRequest Patch(string page, T json) where T : struct, ICanBeJson; + UnityWebRequest Post(string page, T json) where T : struct, ICanBeJson; + + /// + /// Sends Request to api and invokes callback when finished + /// Starts Coroutine of SendRequestEnumerator + /// + /// + /// + /// + void SendRequest(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null); + /// + /// Sends Request to api and invokes callback when finished + /// + /// + /// + /// + /// + IEnumerator SendRequestEnumerator(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null); + } +} diff --git a/Assets/Mirror/Cloud/Core/IRequestCreator.cs.meta b/Assets/Mirror/Cloud/Core/IRequestCreator.cs.meta new file mode 100644 index 00000000..966c5031 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/IRequestCreator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b80b95532a9d6e8418aa676a261e4f69 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs b/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs new file mode 100644 index 00000000..6603edb4 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +namespace Mirror.CloudServices +{ + /// + /// Adds Extension to check if unity object is null. + /// Use these methods to stop MissingReferenceException + /// + public interface IUnityEqualCheck + { + + } + + public static class UnityEqualCheckExtension + { + public static bool IsNull(this IUnityEqualCheck obj) + { + return (obj as Object) == null; + } + + public static bool IsNotNull(this IUnityEqualCheck obj) + { + return (obj as Object) != null; + } + } +} diff --git a/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs.meta b/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs.meta new file mode 100644 index 00000000..7cb2a59f --- /dev/null +++ b/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 05185b973ba389a4588fc8a99c75a4f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/JsonStructs.cs b/Assets/Mirror/Cloud/Core/JsonStructs.cs new file mode 100644 index 00000000..bbc24b77 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/JsonStructs.cs @@ -0,0 +1,24 @@ +using System; + +namespace Mirror.CloudServices +{ + [Serializable] + public struct CreatedIdJson : ICanBeJson + { + public string id; + } + + [Serializable] + public struct ErrorJson : ICanBeJson + { + public string code; + public string message; + + public int HtmlCode => int.Parse(code); + } + + [Serializable] + public struct EmptyJson : ICanBeJson + { + } +} diff --git a/Assets/Mirror/Cloud/Core/JsonStructs.cs.meta b/Assets/Mirror/Cloud/Core/JsonStructs.cs.meta new file mode 100644 index 00000000..2c040090 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/JsonStructs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0688c0fdae5376e4ea74d5c3904eed17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/Logger.cs b/Assets/Mirror/Cloud/Core/Logger.cs new file mode 100644 index 00000000..90aff07f --- /dev/null +++ b/Assets/Mirror/Cloud/Core/Logger.cs @@ -0,0 +1,65 @@ +using System; +using UnityEngine; +using UnityEngine.Networking; + +namespace Mirror.CloudServices +{ + public static class Logger + { + public static bool VerboseLogging = false; + static readonly ILogger logger = LogFactory.GetLogger("MirrorCloudServices"); + + public static void LogRequest(string page, string method, bool hasJson, string json) + { + if (hasJson) + { + logger.LogFormat(LogType.Log, "Request: {0} {1} {2}", method, page, json); + } + else + { + logger.LogFormat(LogType.Log, "Request: {0} {1}", method, page); + } + } + + public static void LogResponse(UnityWebRequest statusRequest) + { + long code = statusRequest.responseCode; + LogType logType = statusRequest.IsOk() + ? LogType.Log + : LogType.Error; + + string format = "Response: {0} {1} {2} {3}"; + if (logger.IsLogTypeAllowed(logType)) + { + // we split path like this to make sure api key doesn't leak + Uri uri = new Uri(statusRequest.url); + string path = string.Join("", uri.Segments); + logger.LogFormat(logType, format, statusRequest.method, code, path, statusRequest.downloadHandler.text); + } + } + + internal static void Log(string msg) + { + if (logger.LogEnabled()) + logger.Log(msg); + } + + internal static void LogWarning(string msg) + { + if (logger.WarnEnabled()) + logger.LogWarning(msg); + } + + internal static void LogError(string msg) + { + if (logger.ErrorEnabled()) + logger.LogError(msg); + } + + internal static void Verbose(string msg) + { + if (VerboseLogging && logger.LogEnabled()) + logger.Log(msg); + } + } +} diff --git a/Assets/Mirror/Cloud/Core/Logger.cs.meta b/Assets/Mirror/Cloud/Core/Logger.cs.meta new file mode 100644 index 00000000..5984ce30 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/Logger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 457ba2df6cb6e1542996c17c715ee81b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Core/RequestCreator.cs b/Assets/Mirror/Cloud/Core/RequestCreator.cs new file mode 100644 index 00000000..c92a594d --- /dev/null +++ b/Assets/Mirror/Cloud/Core/RequestCreator.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections; +using System.Text; +using UnityEngine; +using UnityEngine.Networking; + +namespace Mirror.CloudServices +{ + /// + /// Methods to create and send UnityWebRequest + /// + public class RequestCreator : IRequestCreator + { + const string GET = "GET"; + const string POST = "POST"; + const string PATCH = "PATCH"; + const string DELETE = "DELETE"; + + public readonly string baseAddress; + public readonly string apiKey; + readonly ICoroutineRunner runner; + + public RequestCreator(string baseAddress, string apiKey, ICoroutineRunner coroutineRunner) + { + if (string.IsNullOrEmpty(baseAddress)) + { + throw new ArgumentNullException(nameof(baseAddress)); + } + + if (string.IsNullOrEmpty(apiKey)) + { + throw new ArgumentNullException(nameof(apiKey)); + } + + this.baseAddress = baseAddress; + this.apiKey = apiKey; + + runner = coroutineRunner ?? throw new ArgumentNullException(nameof(coroutineRunner)); + } + + + Uri CreateUri(string page) + { + return new Uri(string.Format("{0}/{1}?key={2}", baseAddress, page, apiKey)); + } + + UnityWebRequest CreateWebRequest(string page, string method, string json = null) + { + bool hasJson = !string.IsNullOrEmpty(json); + Logger.LogRequest(page, method, hasJson, json); + + UnityWebRequest request = new UnityWebRequest(CreateUri(page)); + request.method = method; + if (hasJson) + { + request.SetRequestHeader("Content-Type", "application/json"); + } + + request.downloadHandler = new DownloadHandlerBuffer(); + + byte[] bodyRaw = hasJson + ? Encoding.UTF8.GetBytes(json) + : null; + + request.uploadHandler = new UploadHandlerRaw(bodyRaw); + + return request; + } + + + + /// + /// Create Get Request to page + /// + /// + /// + public UnityWebRequest Get(string page) + { + return CreateWebRequest(page, GET); + } + + /// + /// Creates Post Request to page with Json body + /// + /// + /// + /// + /// + public UnityWebRequest Post(string page, T json) where T : struct, ICanBeJson + { + string jsonString = JsonUtility.ToJson(json); + return CreateWebRequest(page, POST, jsonString); + } + + /// + /// Creates Patch Request to page with Json body + /// + /// + /// + /// + /// + public UnityWebRequest Patch(string page, T json) where T : struct, ICanBeJson + { + string jsonString = JsonUtility.ToJson(json); + return CreateWebRequest(page, PATCH, jsonString); + } + + /// + /// Create Delete Request to page + /// + /// + /// + public UnityWebRequest Delete(string page) + { + return CreateWebRequest(page, DELETE); + } + + + public void SendRequest(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null) + { + runner.StartCoroutine(SendRequestEnumerator(request, onSuccess, onFail)); + } + + public IEnumerator SendRequestEnumerator(UnityWebRequest request, RequestSuccess onSuccess = null, RequestFail onFail = null) + { + using (UnityWebRequest webRequest = request) + { + yield return webRequest.SendWebRequest(); + Logger.LogResponse(webRequest); + + string text = webRequest.downloadHandler.text; + Logger.Verbose(text); + if (webRequest.IsOk()) + { + onSuccess?.Invoke(text); + } + else + { + onFail?.Invoke(text); + } + } + } + } +} diff --git a/Assets/Mirror/Cloud/Core/RequestCreator.cs.meta b/Assets/Mirror/Cloud/Core/RequestCreator.cs.meta new file mode 100644 index 00000000..eb139af4 --- /dev/null +++ b/Assets/Mirror/Cloud/Core/RequestCreator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cfaa626443cc7c94eae138a2e3a04d7c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/ListServer.meta b/Assets/Mirror/Cloud/ListServer.meta new file mode 100644 index 00000000..bc85c3d0 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c4c4be148a492b143a881cd08bf7e320 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/ListServer/ListServer.cs b/Assets/Mirror/Cloud/ListServer/ListServer.cs new file mode 100644 index 00000000..a4c90c52 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServer.cs @@ -0,0 +1,66 @@ +using System; +using UnityEngine.Events; + +namespace Mirror.CloudServices.ListServerService +{ + public sealed class ListServer + { + public readonly IListServerServerApi ServerApi; + public readonly IListServerClientApi ClientApi; + + public ListServer(IListServerServerApi serverApi, IListServerClientApi clientApi) + { + ServerApi = serverApi ?? throw new ArgumentNullException(nameof(serverApi)); + ClientApi = clientApi ?? throw new ArgumentNullException(nameof(clientApi)); + } + } + + public interface IListServerServerApi : IBaseApi + { + /// + /// Has a server been added to the list with this connection + /// + bool ServerInList { get; } + /// + /// Add a server to the list + /// + /// + void AddServer(ServerJson server); + /// + /// Update the current server + /// + /// + void UpdateServer(int newPlayerCount); + /// + /// Update the current server + /// + /// + void UpdateServer(ServerJson server); + /// + /// Removes the current server + /// + void RemoveServer(); + } + + public interface IListServerClientApi : IBaseApi + { + /// + /// Called when the server list is updated + /// + event UnityAction onServerListUpdated; + + /// + /// Get the server list once + /// + void GetServerList(); + /// + /// Start getting the server list every interval + /// + /// + void StartGetServerListRepeat(int interval); + /// + /// Stop getting the server list + /// + void StopGetServerListRepeat(); + } +} diff --git a/Assets/Mirror/Cloud/ListServer/ListServer.cs.meta b/Assets/Mirror/Cloud/ListServer/ListServer.cs.meta new file mode 100644 index 00000000..519876dc --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f0311899162c5b49a3c11fa9bd9c133 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs b/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs new file mode 100644 index 00000000..fa3944aa --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs @@ -0,0 +1,9 @@ +namespace Mirror.CloudServices.ListServerService +{ + public abstract class ListServerBaseApi : BaseApi + { + protected ListServerBaseApi(ICoroutineRunner runner, IRequestCreator requestCreator) : base(runner, requestCreator) + { + } + } +} diff --git a/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs.meta b/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs.meta new file mode 100644 index 00000000..a9d32ea0 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6838f9df45594d48873518cbb75b329 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs b/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs new file mode 100644 index 00000000..8b877d11 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs @@ -0,0 +1,70 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.Networking; + +namespace Mirror.CloudServices.ListServerService +{ + public sealed class ListServerClientApi : ListServerBaseApi, IListServerClientApi + { + readonly ServerListEvent _onServerListUpdated; + + Coroutine getServerListRepeatCoroutine; + + public event UnityAction onServerListUpdated + { + add => _onServerListUpdated.AddListener(value); + remove => _onServerListUpdated.RemoveListener(value); + } + + public ListServerClientApi(ICoroutineRunner runner, IRequestCreator requestCreator, ServerListEvent onServerListUpdated) : base(runner, requestCreator) + { + _onServerListUpdated = onServerListUpdated; + } + + public void Shutdown() + { + StopGetServerListRepeat(); + } + + public void GetServerList() + { + runner.StartCoroutine(getServerList()); + } + + public void StartGetServerListRepeat(int interval) + { + getServerListRepeatCoroutine = runner.StartCoroutine(GetServerListRepeat(interval)); + } + + public void StopGetServerListRepeat() + { + // if runner is null it has been destroyed and will alraedy be null + if (runner.IsNotNull() && getServerListRepeatCoroutine != null) + { + runner.StopCoroutine(getServerListRepeatCoroutine); + } + } + + IEnumerator GetServerListRepeat(int interval) + { + while (true) + { + yield return getServerList(); + + yield return new WaitForSeconds(interval); + } + } + IEnumerator getServerList() + { + UnityWebRequest request = requestCreator.Get("servers"); + yield return requestCreator.SendRequestEnumerator(request, onSuccess); + + void onSuccess(string responseBody) + { + ServerCollectionJson serverlist = JsonUtility.FromJson(responseBody); + _onServerListUpdated?.Invoke(serverlist); + } + } + } +} diff --git a/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs.meta b/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs.meta new file mode 100644 index 00000000..306bf7c6 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d49649fb32cb96b46b10f013b38a4b50 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/ListServer/ListServerJson.cs b/Assets/Mirror/Cloud/ListServer/ListServerJson.cs new file mode 100644 index 00000000..af937ad8 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerJson.cs @@ -0,0 +1,45 @@ +using System; + +namespace Mirror.CloudServices.ListServerService +{ + [Serializable] + public struct ServerCollectionJson : ICanBeJson + { + public ServerJson[] servers; + } + + [Serializable] + public struct ServerJson : ICanBeJson + { + public string protocol; + public int port; + public int playerCount; + public int maxPlayerCount; + + /// + /// optional + /// + public string displayName; + /// + /// This is returns from the api, any incoming address fields will be ignored + /// + public string address; + } + + [Serializable] + public struct PartialServerJson : ICanBeJson + { + /// + /// optional + /// + public int playerCount; + /// + /// optional + /// + public int maxPlayerCount; + /// + /// optional + /// + public string displayName; + } +} diff --git a/Assets/Mirror/Cloud/ListServer/ListServerJson.cs.meta b/Assets/Mirror/Cloud/ListServer/ListServerJson.cs.meta new file mode 100644 index 00000000..7e206f11 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerJson.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a963606335eae0f47abe7ecb5fd028ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs b/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs new file mode 100644 index 00000000..a9827879 --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs @@ -0,0 +1,222 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Networking; + +namespace Mirror.CloudServices.ListServerService +{ + public sealed class ListServerServerApi : ListServerBaseApi, IListServerServerApi + { + const int PingInterval = 15; + const int MaxPingFails = 3; + + ServerJson currentServer; + string serverId; + + Coroutine _pingCoroutine; + /// + /// If the server has already been added + /// + bool added; + /// + /// if a request is currently sending + /// + bool sending; + /// + /// If an update request was recently sent + /// + bool skipNextPing; + /// + /// How many failed pings in a row + /// + int pingFails = 0; + + public bool ServerInList => added; + + public ListServerServerApi(ICoroutineRunner runner, IRequestCreator requestCreator) : base(runner, requestCreator) + { + } + + public void Shutdown() + { + stopPingCoroutine(); + if (added) + { + removeServerWithoutCoroutine(); + } + added = false; + } + + public void AddServer(ServerJson server) + { + if (added) { Logger.LogWarning("AddServer called when server was already adding or added"); return; } + bool valid = ValidateServerJson(server); + if (!valid) { return; } + + runner.StartCoroutine(addServer(server)); + } + + bool ValidateServerJson(ServerJson server) + { + if (string.IsNullOrEmpty(server.protocol)) + { + Logger.LogError("ServerJson should not have empty protocol"); + return false; + } + if (server.port == 0) + { + Logger.LogError("ServerJson should not have port equal 0"); + return false; + } + if (server.maxPlayerCount == 0) + { + Logger.LogError("ServerJson should not have maxPlayerCount equal 0"); + return false; + } + + return true; + } + + public void UpdateServer(int newPlayerCount) + { + if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); return; } + + currentServer.playerCount = newPlayerCount; + UpdateServer(currentServer); + } + + public void UpdateServer(ServerJson server) + { + // TODO, use PartialServerJson as Arg Instead + if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); return; } + + PartialServerJson partialServer = new PartialServerJson + { + displayName = server.displayName, + playerCount = server.playerCount, + maxPlayerCount = server.maxPlayerCount, + }; + + runner.StartCoroutine(updateServer(partialServer)); + } + + public void RemoveServer() + { + if (!added) { return; } + + stopPingCoroutine(); + runner.StartCoroutine(removeServer()); + } + + void stopPingCoroutine() + { + if (_pingCoroutine != null) + { + runner.StopCoroutine(_pingCoroutine); + _pingCoroutine = null; + } + } + + IEnumerator addServer(ServerJson server) + { + added = true; + sending = true; + currentServer = server; + + UnityWebRequest request = requestCreator.Post("servers", currentServer); + yield return requestCreator.SendRequestEnumerator(request, onSuccess, onFail); + sending = false; + + void onSuccess(string responseBody) + { + CreatedIdJson created = JsonUtility.FromJson(responseBody); + serverId = created.id; + + // Start ping to keep server alive + _pingCoroutine = runner.StartCoroutine(ping()); + } + void onFail(string responseBody) + { + added = false; + } + } + + IEnumerator updateServer(PartialServerJson server) + { + // wait to not be sending + while (sending) + { + yield return new WaitForSeconds(1); + } + + // We need to check added incase Update is called soon after Add, and add failed + if (!added) { Logger.LogWarning("UpdateServer called when before server was added"); yield break; } + + sending = true; + UnityWebRequest request = requestCreator.Patch("servers/" + serverId, server); + yield return requestCreator.SendRequestEnumerator(request, onSuccess); + sending = false; + + void onSuccess(string responseBody) + { + skipNextPing = true; + + if (_pingCoroutine == null) + { + _pingCoroutine = runner.StartCoroutine(ping()); + } + } + } + + /// + /// Keeps server alive in database + /// + /// + IEnumerator ping() + { + while (pingFails <= MaxPingFails) + { + yield return new WaitForSeconds(PingInterval); + if (skipNextPing) { continue; } + + sending = true; + UnityWebRequest request = requestCreator.Patch("servers/" + serverId, new EmptyJson()); + yield return requestCreator.SendRequestEnumerator(request, onSuccess, onFail); + sending = false; + } + + Logger.LogWarning("Max ping fails reached, stoping to ping server"); + _pingCoroutine = null; + + + void onSuccess(string responseBody) + { + pingFails = 0; + } + void onFail(string responseBody) + { + pingFails++; + } + } + + IEnumerator removeServer() + { + sending = true; + UnityWebRequest request = requestCreator.Delete("servers/" + serverId); + yield return requestCreator.SendRequestEnumerator(request); + sending = false; + + added = false; + } + + void removeServerWithoutCoroutine() + { + UnityWebRequest request = requestCreator.Delete("servers/" + serverId); + UnityWebRequestAsyncOperation operation = request.SendWebRequest(); + + operation.completed += (op) => + { + Logger.LogResponse(request); + }; + } + } +} diff --git a/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs.meta b/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs.meta new file mode 100644 index 00000000..82e23fdf --- /dev/null +++ b/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 675f0d0fd4e82b04290c4d30c8d78ede +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef b/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef new file mode 100644 index 00000000..ce45ae1c --- /dev/null +++ b/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Mirror.CloudServices", + "references": [ + "Mirror" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef.meta b/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef.meta new file mode 100644 index 00000000..bd17c2b3 --- /dev/null +++ b/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c21ba7b8c3183cb47b7fe3b3799d49c4 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/README.md b/Assets/Mirror/Cloud/README.md new file mode 100644 index 00000000..4b08f603 --- /dev/null +++ b/Assets/Mirror/Cloud/README.md @@ -0,0 +1,12 @@ +# Mirror Cloud Services + +Example has api key that can be used for as a demo. + +To get a api key to use within your game buy here... + + +## Example + +An example for this can be found in Mirror/Examples/PongWithListServer/ + +*Note: you can not connect to your own public ip address, you will need at least people to test this* \ No newline at end of file diff --git a/Assets/Mirror/Cloud/README.md.meta b/Assets/Mirror/Cloud/README.md.meta new file mode 100644 index 00000000..d669f54f --- /dev/null +++ b/Assets/Mirror/Cloud/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 04945d14ccbed964597a1ee00805c059 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Cloud/version.txt b/Assets/Mirror/Cloud/version.txt new file mode 100644 index 00000000..7b0bc8d6 --- /dev/null +++ b/Assets/Mirror/Cloud/version.txt @@ -0,0 +1 @@ +MirrorCloudServices v0.1.0 \ No newline at end of file diff --git a/Assets/Mirror/Cloud/version.txt.meta b/Assets/Mirror/Cloud/version.txt.meta new file mode 100644 index 00000000..1e13fd52 --- /dev/null +++ b/Assets/Mirror/Cloud/version.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bf81e376b88e68e48a47531b8bfeb0f4 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer.meta b/Assets/Mirror/Examples/PongWithListServer.meta new file mode 100644 index 00000000..2bc653e4 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4144fadaccca8e343a08615df4ae7c71 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials.meta b/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials.meta new file mode 100644 index 00000000..cfda6333 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d8e1da28ca3b5f8438755cdc36d237ed +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D b/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D new file mode 100644 index 00000000..137d57e6 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!62 &6200000 +PhysicsMaterial2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: BallMaterial + friction: 0 + bounciness: 1 diff --git a/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta b/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta new file mode 100644 index 00000000..91411f7a --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2161ffa457162a94e91fbd9aa782e4cb +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs.meta b/Assets/Mirror/Examples/PongWithListServer/Prefabs.meta new file mode 100644 index 00000000..13d381b3 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1624cce23d35a294cad9eb3c0969e68f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab new file mode 100644 index 00000000..8496b2ad --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab @@ -0,0 +1,183 @@ +%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: 114692463781779748} + - component: {fileID: 114121325390084138} + m_Layer: 0 + m_Name: Ball + 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_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_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: 2c19e4cb225706240af7a8fbbf2ebfe2, 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: 2161ffa457162a94e91fbd9aa782e4cb, 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 + m_AssetId: a4b57f17790d9634ea5fd0fe80b214fd + hasSpawned: 0 +--- !u!114 &114692463781779748 +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: b4e9cc0829b13e54594a80883836bda7, type: 3} + m_Name: + m_EditorClassIdentifier: + syncMode: 0 + syncInterval: 0.1 + speed: 30 + rigidbody2d: {fileID: 50354248948880112} +--- !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 diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab.meta b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab.meta new file mode 100644 index 00000000..d65bf3b4 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a4b57f17790d9634ea5fd0fe80b214fd +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab new file mode 100644 index 00000000..af1c8aff --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab @@ -0,0 +1,2693 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4971607475450741445 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475450741444} + - component: {fileID: 4971607475450741442} + - component: {fileID: 4971607475450741443} + m_Layer: 5 + m_Name: TextFootnote + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475450741444 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475450741445} + 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: 4971607475451386690} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: -10} + m_SizeDelta: {x: 0, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607475450741442 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475450741445} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475450741443 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475450741445} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 2 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '* Host your own List Server with: mirror-networking.com/list-server' +--- !u!1 &4971607475451386691 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475451386690} + - component: {fileID: 4971607475451386751} + - component: {fileID: 4971607475451386688} + m_Layer: 5 + m_Name: ServerListPanel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475451386690 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475451386691} + 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: + - {fileID: 4971607475748769786} + - {fileID: 4971607476240074303} + - {fileID: 4971607475515065360} + - {fileID: 4971607477325490914} + - {fileID: 4971607476994082406} + - {fileID: 4971607477083899161} + - {fileID: 4971607475450741444} + m_Father: {fileID: 4971607477202590071} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 526, y: 400} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607475451386751 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475451386691} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475451386688 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475451386691} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19215687, g: 0.19215687, b: 0.19215687, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!1 &4971607475471872081 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475471872080} + - component: {fileID: 4971607475471872078} + - component: {fileID: 4971607475471872079} + m_Layer: 5 + m_Name: TitleBar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475471872080 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475471872081} + 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: + - {fileID: 4971607477307762874} + m_Father: {fileID: 4971607476985653604} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 20} + m_Pivot: {x: 0.5, y: 1} +--- !u!222 &4971607475471872078 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475471872081} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475471872079 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475471872081} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.31764707, g: 0.31764707, b: 0.31764707, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!1 &4971607475508337488 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607477202590071} + m_Layer: 5 + m_Name: ServerList + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607477202590071 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475508337488} + 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: + - {fileID: 4971607475577112185} + - {fileID: 4971607475451386690} + - {fileID: 4971607476985653604} + m_Father: {fileID: 4971607476965432301} + 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!1 &4971607475515065361 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475515065360} + - component: {fileID: 4971607475515065358} + - component: {fileID: 4971607475515065359} + m_Layer: 5 + m_Name: TextStatus + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475515065360 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475515065361} + 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: 4971607475451386690} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -3, y: -19} + m_SizeDelta: {x: 157.79, y: 19} + m_Pivot: {x: 1, y: 1} +--- !u!222 &4971607475515065358 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475515065361} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475515065359 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475515065361} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0.24313726} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 2 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 5 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Status +--- !u!1 &4971607475577112186 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475577112185} + - component: {fileID: 4971607475577112183} + - component: {fileID: 4971607475577112184} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475577112185 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475577112186} + 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: 4971607477202590071} + 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!222 &4971607475577112183 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475577112186} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475577112184 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475577112186} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.39215687, g: 0.58431375, b: 0.92941177, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 +--- !u!1 &4971607475626354595 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475626354594} + - component: {fileID: 4971607475626354592} + - component: {fileID: 4971607475626354593} + - component: {fileID: 7202607427830828079} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475626354594 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475626354595} + 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: 4971607477325490914} + 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: 20} + m_Pivot: {x: 0, y: 1} +--- !u!222 &4971607475626354592 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475626354595} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475626354593 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475626354595} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Action +--- !u!114 &7202607427830828079 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475626354595} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 50 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &4971607475641435052 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475641435051} + - component: {fileID: 4971607475641435048} + - component: {fileID: 4971607475641435049} + - component: {fileID: 4971607475641435050} + m_Layer: 5 + m_Name: Scrollbar Vertical + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475641435051 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475641435052} + 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: + - {fileID: 4971607477557945088} + m_Father: {fileID: 4971607476994082406} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 0} + m_Pivot: {x: 1, y: 1} +--- !u!222 &4971607475641435048 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475641435052} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475641435049 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475641435052} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.24313726, g: 0.24313726, b: 0.24313726, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &4971607475641435050 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475641435052} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -2061169968, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.4117647, g: 0.4117647, b: 0.4117647, a: 1} + m_HighlightedColor: {r: 0.41176474, g: 0.41176474, b: 0.41176474, a: 1} + m_PressedColor: {r: 0.41176474, g: 0.41176474, b: 0.41176474, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 4971607476873278911} + m_HandleRect: {fileID: 4971607476873278848} + m_Direction: 2 + m_Value: 0 + m_Size: 1 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Scrollbar+ScrollEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &4971607475644947933 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475644947932} + - component: {fileID: 2647107856379666145} + m_Layer: 5 + m_Name: Content + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475644947932 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475644947933} + 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: 4971607476994082406} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 0, y: 0.000015258789} + m_SizeDelta: {x: 560, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &2647107856379666145 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475644947933} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 +--- !u!1 &4971607475748769787 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475748769786} + - component: {fileID: 4971607475748769783} + - component: {fileID: 4971607475748769784} + m_Layer: 5 + m_Name: TitleBar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475748769786 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475748769787} + 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: + - {fileID: 4971607476042025200} + m_Father: {fileID: 4971607475451386690} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 20} + m_Pivot: {x: 0.5, y: 1} +--- !u!222 &4971607475748769783 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475748769787} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475748769784 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475748769787} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.31764707, g: 0.31764707, b: 0.31764707, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!1 &4971607475793899370 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475793899369} + - component: {fileID: 4971607475793899366} + - component: {fileID: 4971607475793899367} + - component: {fileID: 4971607475793899368} + m_Layer: 5 + m_Name: ButtonRefresh + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475793899369 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475793899370} + 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: + - {fileID: 4971607476258920763} + m_Father: {fileID: 4971607477083899161} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 2, y: 0} + m_SizeDelta: {x: 260, y: 20} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &4971607475793899366 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475793899370} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475793899367 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475793899370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &4971607475793899368 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475793899370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1} + m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1} + m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1} + m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.2509804} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 4971607475793899367} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &4971607475797070506 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607475797070505} + - component: {fileID: 4971607475797070502} + - component: {fileID: 4971607475797070503} + - component: {fileID: 4971607475797070504} + m_Layer: 5 + m_Name: ButtonServerOnly + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607475797070505 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475797070506} + 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: + - {fileID: 4971607476892233254} + m_Father: {fileID: 4971607477083899161} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: -2, y: 0} + m_SizeDelta: {x: 260, y: 20} + m_Pivot: {x: 1, y: 0.5} +--- !u!222 &4971607475797070502 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475797070506} + m_CullTransparentMesh: 0 +--- !u!114 &4971607475797070503 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475797070506} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &4971607475797070504 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607475797070506} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1} + m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1} + m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1} + m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.2509804} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 4971607475797070503} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &4971607476029058371 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476029058370} + - component: {fileID: 4971607476029058368} + - component: {fileID: 4971607476029058369} + - component: {fileID: 1412813690393573607} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476029058370 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476029058371} + 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: 4971607477325490914} + m_RootOrder: 0 + 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: 20} + m_Pivot: {x: 0, y: 1} +--- !u!222 &4971607476029058368 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476029058371} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476029058369 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476029058371} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Server Name +--- !u!114 &1412813690393573607 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476029058371} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 250 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &4971607476042025201 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476042025200} + - component: {fileID: 4971607476042025198} + - component: {fileID: 4971607476042025199} + m_Layer: 5 + m_Name: TextTitle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476042025200 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476042025201} + 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: 4971607475748769786} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -36, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607476042025198 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476042025201} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476042025199 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476042025201} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.23137255, g: 1, b: 0.6862745, a: 1} + m_RaycastTarget: 0 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Mirror Cloud Services Demo +--- !u!1 &4971607476137863973 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476137863972} + - component: {fileID: 4971607476137863970} + - component: {fileID: 4971607476137863971} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476137863972 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476137863973} + 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: 4971607476488526554} + 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!222 &4971607476137863970 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476137863973} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476137863971 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476137863973} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Cancel +--- !u!1 &4971607476213912987 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476213912986} + - component: {fileID: 4971607476213912984} + - component: {fileID: 4971607476213912985} + m_Layer: 5 + m_Name: TextStatus + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476213912986 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476213912987} + 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: 4971607476985653604} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -29} + m_SizeDelta: {x: 0, y: 18} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607476213912984 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476213912987} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476213912985 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476213912987} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Status +--- !u!1 &4971607476240074240 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476240074303} + - component: {fileID: 4971607476240074301} + - component: {fileID: 4971607476240074302} + m_Layer: 5 + m_Name: TextJoinServer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476240074303 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476240074240} + 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: 4971607475451386690} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: -29} + m_SizeDelta: {x: 0, y: 18} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607476240074301 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476240074240} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476240074302 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476240074240} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Join Server +--- !u!1 &4971607476258920764 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476258920763} + - component: {fileID: 4971607476258920761} + - component: {fileID: 4971607476258920762} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476258920763 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476258920764} + 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: 4971607475793899369} + 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!222 &4971607476258920761 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476258920764} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476258920762 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476258920764} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Refresh +--- !u!1 &4971607476373752082 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476373752081} + - component: {fileID: 4971607476373752079} + - component: {fileID: 4971607476373752080} + - component: {fileID: 5475127446238777370} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476373752081 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476373752082} + 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: 4971607477325490914} + m_RootOrder: 1 + 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: 20} + m_Pivot: {x: 0, y: 1} +--- !u!222 &4971607476373752079 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476373752082} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476373752080 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476373752082} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Players +--- !u!114 &5475127446238777370 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476373752082} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 50 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &4971607476435516857 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476435516856} + - component: {fileID: 4971607476435516854} + - component: {fileID: 4971607476435516855} + - component: {fileID: 3191646931833320471} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476435516856 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476435516857} + 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: 4971607477325490914} + m_RootOrder: 2 + 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: 20} + m_Pivot: {x: 0, y: 1} +--- !u!222 &4971607476435516854 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476435516857} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476435516855 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476435516857} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Address +--- !u!114 &3191646931833320471 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476435516857} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 100 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &4971607476488526555 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476488526554} + - component: {fileID: 4971607476488526551} + - component: {fileID: 4971607476488526552} + - component: {fileID: 4971607476488526553} + m_Layer: 5 + m_Name: ButtonCancel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476488526554 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476488526555} + 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: + - {fileID: 4971607476137863972} + m_Father: {fileID: 4971607476985653604} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 4, y: 16} + m_SizeDelta: {x: -8, y: 20} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &4971607476488526551 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476488526555} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476488526552 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476488526555} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &4971607476488526553 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476488526555} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1} + m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1} + m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1} + m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.2509804} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 4971607476488526552} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!1 &4971607476873278849 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476873278848} + - component: {fileID: 4971607476873278910} + - component: {fileID: 4971607476873278911} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476873278848 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476873278849} + 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: 4971607477557945088} + m_RootOrder: 0 + 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: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607476873278910 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476873278849} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476873278911 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476873278849} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 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 +--- !u!1 &4971607476892233255 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476892233254} + - component: {fileID: 4971607476892233252} + - component: {fileID: 4971607476892233253} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476892233254 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476892233255} + 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: 4971607475797070505} + 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!222 &4971607476892233252 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476892233255} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476892233253 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476892233255} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Server Only +--- !u!1 &4971607476965432305 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476965432301} + - component: {fileID: 4971607476965432302} + - component: {fileID: 4971607476965432303} + - component: {fileID: 4971607476965432304} + - component: {fileID: 1640965657294869647} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476965432301 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476965432305} + 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: 4971607477202590071} + m_Father: {fileID: 0} + m_RootOrder: 0 + 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!223 &4971607476965432302 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476965432305} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 1 + 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!114 &4971607476965432303 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476965432305} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1280, y: 720} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &4971607476965432304 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476965432305} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1640965657294869647 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476965432305} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bfc354d4a7f63ca45a653bf5d479afa0, type: 3} + m_Name: + m_EditorClassIdentifier: + listUI: {fileID: 4251621586964734305} + refreshButton: {fileID: 4971607475793899368} + startServerButton: {fileID: 4971607475797070504} + autoRefreshServerlist: 1 + refreshinterval: 20 +--- !u!1 &4971607476985653605 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476985653604} + - component: {fileID: 4971607476985653602} + - component: {fileID: 4971607476985653603} + m_Layer: 5 + m_Name: ConnectingPanel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &4971607476985653604 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476985653605} + 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: + - {fileID: 4971607475471872080} + - {fileID: 4971607476213912986} + - {fileID: 4971607477294315701} + - {fileID: 4971607476488526554} + m_Father: {fileID: 4971607477202590071} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 250, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607476985653602 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476985653605} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476985653603 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476985653605} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19215687, g: 0.19215687, b: 0.19215687, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!1 &4971607476994082407 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607476994082406} + - component: {fileID: 4251621586964734305} + - component: {fileID: 4971607476994082402} + - component: {fileID: 4971607476994082403} + - component: {fileID: 4971607476994082404} + - component: {fileID: 4971607476994082405} + m_Layer: 5 + m_Name: ServerList Scroll View + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607476994082406 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476994082407} + 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: + - {fileID: 4971607475644947932} + - {fileID: 4971607475641435051} + m_Father: {fileID: 4971607475451386690} + m_RootOrder: 4 + 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: -13} + m_SizeDelta: {x: -2, y: -86} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &4251621586964734305 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476994082407} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ed11184fcffcdc04c9850d82c8014926, type: 3} + m_Name: + m_EditorClassIdentifier: + itemPrefab: {fileID: 4474820569724777087, guid: 37cfbf43e3fc8d046ac443022029d319, + type: 3} + parent: {fileID: 4971607475644947932} +--- !u!114 &4971607476994082402 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476994082407} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1367256648, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 4971607475644947932} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 2 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 0} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 4971607475641435050} + m_HorizontalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 1 + m_HorizontalScrollbarSpacing: -3 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.ScrollRect+ScrollRectEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!222 &4971607476994082403 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476994082407} + m_CullTransparentMesh: 0 +--- !u!114 &4971607476994082404 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476994082407} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.25882354, g: 0.25882354, b: 0.25882354, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &4971607476994082405 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607476994082407} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1200242548, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 1 +--- !u!1 &4971607477083899162 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607477083899161} + - component: {fileID: 4971607477083899159} + - component: {fileID: 4971607477083899160} + m_Layer: 5 + m_Name: PanelStartServer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607477083899161 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477083899162} + 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: + - {fileID: 4971607475793899369} + - {fileID: 4971607475797070505} + m_Father: {fileID: 4971607475451386690} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 16} + m_SizeDelta: {x: -4, y: 28} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607477083899159 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477083899162} + m_CullTransparentMesh: 0 +--- !u!114 &4971607477083899160 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477083899162} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.25882354, g: 0.25882354, b: 0.25882354, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!1 &4971607477294315702 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607477294315701} + - component: {fileID: 4971607477294315699} + - component: {fileID: 4971607477294315700} + m_Layer: 5 + m_Name: TextConnecting + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607477294315701 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477294315702} + 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: 4971607476985653604} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607477294315699 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477294315702} + m_CullTransparentMesh: 0 +--- !u!114 &4971607477294315700 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477294315702} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.23137255, b: 0.5803922, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 1 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Connecting... +--- !u!1 &4971607477307762875 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607477307762874} + - component: {fileID: 4971607477307762872} + - component: {fileID: 4971607477307762873} + m_Layer: 5 + m_Name: TextTitle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607477307762874 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477307762875} + 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: 4971607475471872080} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: -36, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607477307762872 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477307762875} + m_CullTransparentMesh: 0 +--- !u!114 &4971607477307762873 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477307762875} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.23137255, g: 1, b: 0.6862745, a: 1} + m_RaycastTarget: 0 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: +--- !u!1 &4971607477325490915 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607477325490914} + - component: {fileID: 4971607477325490912} + - component: {fileID: 4971607477325490913} + - component: {fileID: 4346059805251566766} + m_Layer: 5 + m_Name: PanelTableHeader + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607477325490914 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477325490915} + 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: + - {fileID: 4971607476029058370} + - {fileID: 4971607476373752081} + - {fileID: 4971607476435516856} + - {fileID: 4971607475626354594} + m_Father: {fileID: 4971607475451386690} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -0.5, y: -48} + m_SizeDelta: {x: -1, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4971607477325490912 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477325490915} + m_CullTransparentMesh: 0 +--- !u!114 &4971607477325490913 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477325490915} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.25882354, g: 0.25882354, b: 0.25882354, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &4346059805251566766 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477325490915} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -405508275, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 0 +--- !u!1 &4971607477557945089 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4971607477557945088} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4971607477557945088 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4971607477557945089} + 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: + - {fileID: 4971607476873278848} + m_Father: {fileID: 4971607475641435051} + 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: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab.meta b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab.meta new file mode 100644 index 00000000..2c5e3d6d --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e16e442bbd8d4434cb606afd72bcd08b +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab b/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab new file mode 100644 index 00000000..04199c66 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab @@ -0,0 +1,154 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4798169800353248846 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4798169800353248837} + - component: {fileID: 4798169800353248833} + - component: {fileID: 5399210850297115757} + - component: {fileID: 1442807832621757098} + - component: {fileID: 4798169800353248834} + m_Layer: 0 + m_Name: NetworkManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4798169800353248837 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + 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!114 &4798169800353248833 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8bdb99a29e179d14cb0acc43f175d9ad, type: 3} + m_Name: + m_EditorClassIdentifier: + ApiAddress: https://mirror-matchmaking-service-n4ovagixja-ew.a.run.app + ApiKey: AIzaSyA86z6Rvh946XUJ7ZeaK4_CUCpM8g322Uc + _onServerListUpdated: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.CloudServices.ServerListEvent, Mirror.CloudServices, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &5399210850297115757 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1f6e5d5acb5879f45a2235ae0f44dc92, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1442807832621757098 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 068feff770f710141afa4a90063a5e6c, type: 3} + m_Name: + m_EditorClassIdentifier: + dontDestroyOnLoad: 1 + runInBackground: 1 + startOnHeadless: 1 + showDebugMessages: 1 + serverTickRate: 30 + offlineScene: Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity + onlineScene: Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity + transport: {fileID: 4798169800353248834} + networkAddress: localhost + maxConnections: 2 + disconnectInactiveConnections: 0 + disconnectInactiveTimeout: 60 + authenticator: {fileID: 0} + playerPrefab: {fileID: 1240244544407914, guid: 63ff03a40ac17a8488d37b9b4e1ffd3f, + type: 3} + autoCreatePlayer: 1 + playerSpawnMethod: 1 + spawnPrefabs: + - {fileID: 1080679924113744, guid: a4b57f17790d9634ea5fd0fe80b214fd, type: 3} +--- !u!114 &4798169800353248834 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3} + m_Name: + m_EditorClassIdentifier: + OnClientConnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + OnClientDataReceived: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.ClientDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnClientError: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnClientDisconnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + OnServerConnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + OnServerDataReceived: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.ServerDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnServerError: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnServerDisconnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + port: 7777 + NoDelay: 1 + serverMaxMessageSize: 16384 + serverMaxReceivesPerTick: 10000 + clientMaxMessageSize: 16384 + clientMaxReceivesPerTick: 1000 diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab.meta b/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab.meta new file mode 100644 index 00000000..aa060b58 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f9aa4197a8467cd49a35cba69f73ad73 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab new file mode 100644 index 00000000..94aa10c7 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab @@ -0,0 +1,185 @@ +%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: 114626868563338794} + - component: {fileID: 114398896143473162} + m_Layer: 0 + m_Name: Racket + 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: bdb0ccb2f147a3d47abe396bd18c5dbe, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2, y: 4} + 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: 2, y: 4} + 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 + m_AssetId: + hasSpawned: 0 +--- !u!114 &114626868563338794 +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: 2b6cfd54b79bb464dbc6ae7f331ed45f, type: 3} + m_Name: + m_EditorClassIdentifier: + syncMode: 0 + syncInterval: 0.1 + speed: 1500 + rigidbody2d: {fileID: 50389918509199184} +--- !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 diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab.meta b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab.meta new file mode 100644 index 00000000..51188867 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 63ff03a40ac17a8488d37b9b4e1ffd3f +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab new file mode 100644 index 00000000..29a15656 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab @@ -0,0 +1,640 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1009505356919436 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224428085307354514} + - component: {fileID: 222534217462828066} + - component: {fileID: 114077992825021022} + - component: {fileID: 9086842666106688486} + m_Layer: 5 + m_Name: TextPlayers + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224428085307354514 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1009505356919436} + 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: 224813910264502154} + m_RootOrder: 1 + 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: 16} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &222534217462828066 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1009505356919436} + m_CullTransparentMesh: 0 +--- !u!114 &114077992825021022 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1009505356919436} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '[Players]' +--- !u!114 &9086842666106688486 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1009505356919436} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 50 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &1259177336467004 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224813910264502154} + - component: {fileID: 222443701544564472} + - component: {fileID: 114424214131292870} + - component: {fileID: 114618400118094574} + - component: {fileID: 4474820569724777087} + m_Layer: 5 + m_Name: ServerStatusSlot + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224813910264502154 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1259177336467004} + 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: + - {fileID: 224596263305646570} + - {fileID: 224428085307354514} + - {fileID: 2588874080615256095} + - {fileID: 224530003443674914} + m_Father: {fileID: 0} + m_RootOrder: 0 + 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.5, y: 0.5} +--- !u!222 &222443701544564472 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1259177336467004} + m_CullTransparentMesh: 0 +--- !u!114 &114424214131292870 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1259177336467004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.2509804, g: 0.2509804, b: 0.2509804, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &114618400118094574 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1259177336467004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -405508275, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 0 +--- !u!114 &4474820569724777087 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1259177336467004} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c67eda1b451338a428df87fda1e3a7c9, type: 3} + m_Name: + m_EditorClassIdentifier: + nameText: {fileID: 114105517410707240} + namePlayers: {fileID: 114077992825021022} + playersFormat: '{0} / {1}' + addressText: {fileID: 1711666012325280996} + joinButton: {fileID: 114358377111651776} +--- !u!1 &1368168976437814 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224596263305646570} + - component: {fileID: 222703717971346548} + - component: {fileID: 114105517410707240} + - component: {fileID: 1575265727429870122} + m_Layer: 5 + m_Name: TextTitle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224596263305646570 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368168976437814} + 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: 224813910264502154} + m_RootOrder: 0 + 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: 16} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &222703717971346548 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368168976437814} + m_CullTransparentMesh: 0 +--- !u!114 &114105517410707240 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368168976437814} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '[Title]' +--- !u!114 &1575265727429870122 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368168976437814} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 250 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &1462871638010074 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224530003443674914} + - component: {fileID: 222322555260831376} + - component: {fileID: 114653458098104780} + - component: {fileID: 114358377111651776} + - component: {fileID: 3029759900116860951} + m_Layer: 5 + m_Name: ButtonJoin + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224530003443674914 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1462871638010074} + 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: + - {fileID: 224615151935076648} + m_Father: {fileID: 224813910264502154} + 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: 18} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &222322555260831376 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1462871638010074} + m_CullTransparentMesh: 0 +--- !u!114 &114653458098104780 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1462871638010074} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 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 +--- !u!114 &114358377111651776 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1462871638010074} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 0.32156864, g: 0.32156864, b: 0.32156864, a: 1} + m_HighlightedColor: {r: 0.3529412, g: 0.3529412, b: 0.3529412, a: 1} + m_PressedColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 1} + m_DisabledColor: {r: 0.3882353, g: 0.3882353, b: 0.3882353, a: 0.37254903} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 114653458098104780} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &3029759900116860951 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1462871638010074} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 50 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!1 &1575165076438694 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 224615151935076648} + - component: {fileID: 222903696298421472} + - component: {fileID: 114447744505293664} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &224615151935076648 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1575165076438694} + 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: 224530003443674914} + 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!222 &222903696298421472 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1575165076438694} + m_CullTransparentMesh: 0 +--- !u!114 &114447744505293664 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1575165076438694} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Join +--- !u!1 &2231260898927249423 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2588874080615256095} + - component: {fileID: 2389080155505640677} + - component: {fileID: 1711666012325280996} + - component: {fileID: 5562993960699473238} + m_Layer: 5 + m_Name: TextAddress + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2588874080615256095 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2231260898927249423} + 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: 224813910264502154} + m_RootOrder: 2 + 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: 16} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2389080155505640677 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2231260898927249423} + m_CullTransparentMesh: 0 +--- !u!114 &1711666012325280996 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2231260898927249423} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 12 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 40 + m_Alignment: 3 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '[Address]' +--- !u!114 &5562993960699473238 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2231260898927249423} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1679637790, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 100 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab.meta b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab.meta new file mode 100644 index 00000000..2e930b92 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 37cfbf43e3fc8d046ac443022029d319 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes.meta b/Assets/Mirror/Examples/PongWithListServer/Scenes.meta new file mode 100644 index 00000000..d7376214 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d41f99f706c19884da8409b895f978d8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity b/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity new file mode 100644 index 00000000..71c720e3 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity @@ -0,0 +1,615 @@ +%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, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 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: 512 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + 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 &460456769 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 460456772} + - component: {fileID: 460456771} + - component: {fileID: 460456770} + 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 &460456770 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 460456769} + m_Enabled: 1 +--- !u!20 &460456771 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 460456769} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0.44313726, g: 0, b: 0.33105087, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + 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: 0 + 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 &460456772 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 460456769} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + 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 &631456684 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 631456686} + - component: {fileID: 631456685} + m_Layer: 0 + m_Name: InstantiateNetworkManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &631456685 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 631456684} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dbabb497385c20346a3c8bda4ae69508, type: 3} + m_Name: + m_EditorClassIdentifier: + prefab: {fileID: 4798169800353248846, guid: f9aa4197a8467cd49a35cba69f73ad73, type: 3} +--- !u!4 &631456686 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 631456684} + 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: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1092693834 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1092693837} + - component: {fileID: 1092693836} + - component: {fileID: 1092693835} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1092693835 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092693834} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, 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 &1092693836 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092693834} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1092693837 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092693834} + 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: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1621652715 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 4971607476965432305, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Name + value: ListServer Canvas + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_ChildControlWidth + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Spacing + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Left + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Right + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_RootOrder + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Pivot.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Pivot.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607477325490914, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: -0.5 + objectReference: {fileID: 0} + - target: {fileID: 4971607477325490914, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058369, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752080, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516855, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354593, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.y + value: 22 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0.000015258789 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4971607475641435050, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Value + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4971607476873278848, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476873278848, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476873278848, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476985653605, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4346059805251566766, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Left + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 4346059805251566766, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Right + value: 5 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e16e442bbd8d4434cb606afd72bcd08b, type: 3} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity.meta b/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity.meta new file mode 100644 index 00000000..21f8b1f7 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1f04219b066ed4646a078c4c3b2b9180 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity b/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity new file mode 100644 index 00000000..c9ab0cdc --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity @@ -0,0 +1,958 @@ +%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: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 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, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +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: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 0 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 1024 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 0 +--- !u!196 &5 +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 &289876230 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 289876232} + - component: {fileID: 289876231} + m_Layer: 0 + m_Name: DottedLine + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!212 &289876231 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 289876230} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + 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_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: 4ca12bae2c4cf2b419098a2a2026123e, 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: 29} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!4 &289876232 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 289876230} + 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: 1607538195} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &473997959 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 473997961} + - component: {fileID: 473997960} + m_Layer: 0 + m_Name: RacketSpawnLeft + m_TagString: Untagged + m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &473997960 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 473997959} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &473997961 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 473997959} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -20, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1420561038} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &753891880 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 753891882} + - component: {fileID: 753891881} + - component: {fileID: 753891883} + m_Layer: 0 + m_Name: WallBottom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!212 &753891881 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 753891880} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + 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_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: 0e02a5d1b4172d444aa04f1082aed12b, 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: 32} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!4 &753891882 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 753891880} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: -16, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1607538195} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!61 &753891883 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 753891880} + 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: 50, y: 1} + newSize: {x: 1, y: 32} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 50, y: 1} + m_EdgeRadius: 0 +--- !u!1 &1344976652 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1344976655} + - component: {fileID: 1344976654} + - component: {fileID: 1344976653} + m_Layer: 0 + m_Name: Ball Manager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1344976653 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1344976652} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9cc796972dc396a42ba3686bd952e329, type: 3} + m_Name: + m_EditorClassIdentifier: + syncMode: 0 + syncInterval: 0.1 + ballPrefab: {fileID: 1080679924113744, guid: a4b57f17790d9634ea5fd0fe80b214fd, type: 3} +--- !u!114 &1344976654 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1344976652} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b91ecbcc199f4492b9a91e820070131, type: 3} + m_Name: + m_EditorClassIdentifier: + sceneId: 2956121996 + serverOnly: 1 + m_AssetId: + hasSpawned: 0 +--- !u!4 &1344976655 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1344976652} + 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: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1352350029 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1352350031} + - component: {fileID: 1352350030} + - component: {fileID: 1352350032} + m_Layer: 0 + m_Name: WallLeft + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!212 &1352350030 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1352350029} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + 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_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: f43241f798f4cf944be80d465435c252, 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: 32} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!4 &1352350031 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1352350029} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -24.5, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1607538195} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!61 &1352350032 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1352350029} + 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: 1, y: 32} + newSize: {x: 1, y: 32} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 1, y: 32} + m_EdgeRadius: 0 +--- !u!1 &1368547944 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1368547946} + - component: {fileID: 1368547945} + - component: {fileID: 1368547947} + m_Layer: 0 + m_Name: WallTop + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!212 &1368547945 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368547944} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + 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_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: 0e02a5d1b4172d444aa04f1082aed12b, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 50, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!4 &1368547946 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368547944} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 16, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1607538195} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!61 &1368547947 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1368547944} + 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: 50, y: 1} + newSize: {x: 50, y: 1} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 50, y: 1} + m_EdgeRadius: 0 +--- !u!1 &1397990094 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1397990096} + - component: {fileID: 1397990095} + m_Layer: 0 + m_Name: RacketSpawnRight + m_TagString: Untagged + m_Icon: {fileID: -964228994112308473, guid: 0000000000000000d000000000000000, type: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1397990095 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1397990094} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 41f84591ce72545258ea98cb7518d8b9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1397990096 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1397990094} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 20, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1420561038} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1420561037 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1420561038} + m_Layer: 0 + m_Name: Start Positions + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1420561038 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1420561037} + 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: + - {fileID: 473997961} + - {fileID: 1397990096} + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1575697329 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1575697331} + - component: {fileID: 1575697330} + - component: {fileID: 1575697332} + m_Layer: 0 + m_Name: WallRight + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!212 &1575697330 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1575697329} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + 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_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: f43241f798f4cf944be80d465435c252, 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: 32} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!4 &1575697331 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1575697329} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 24.5, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1607538195} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!61 &1575697332 +BoxCollider2D: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1575697329} + 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: 1, y: 32} + newSize: {x: 1, y: 32} + adaptiveTilingThreshold: 0.5 + drawMode: 0 + adaptiveTiling: 0 + m_AutoTiling: 0 + serializedVersion: 2 + m_Size: {x: 1, y: 32} + m_EdgeRadius: 0 +--- !u!1 &1599481325 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1599481328} + - component: {fileID: 1599481327} + - component: {fileID: 1599481326} + m_Layer: 0 + m_Name: Main Camera + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1599481326 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1599481325} + m_Enabled: 1 +--- !u!20 &1599481327 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1599481325} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + 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: 40 + m_Depth: 0 + 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 &1599481328 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1599481325} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + 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 &1607538194 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1607538195} + m_Layer: 0 + m_Name: Table + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1607538195 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1607538194} + 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: + - {fileID: 1368547946} + - {fileID: 753891882} + - {fileID: 1575697331} + - {fileID: 1352350031} + - {fileID: 289876232} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1822812614 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1822812616} + - component: {fileID: 1822812615} + m_Layer: 0 + m_Name: Quit Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1822812615 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1822812614} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76dab753e7255254687cd57985d8d675, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &1822812616 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1822812614} + 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: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity.meta b/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity.meta new file mode 100644 index 00000000..d2895fe1 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 75b237ba71346fd4f9b72184410f2190 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts.meta new file mode 100644 index 00000000..98f8874b --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 34eab05520abb87469a3311727c1d637 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs new file mode 100644 index 00000000..6847c0a6 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs @@ -0,0 +1,83 @@ +using System; +using Mirror.CloudServices.ListServerService; +using UnityEngine; + +namespace Mirror.CloudServices.Example +{ + public class ApiUpdater : MonoBehaviour + { + NetworkManagerListServerPong manager; + ApiConnector connector; + + void Start() + { + manager = NetworkManager.singleton as NetworkManagerListServerPong; + connector = manager.GetComponent(); + + manager.onPlayerListChanged += onPlayerListChanged; + manager.onServerStarted += ServerStartedHandler; + manager.onServerStopped += ServerStoppedHandler; + } + + + void OnDestroy() + { + manager.onPlayerListChanged -= onPlayerListChanged; + manager.onServerStarted -= ServerStartedHandler; + manager.onServerStopped -= ServerStoppedHandler; + } + + void onPlayerListChanged(int playerCount) + { + if (connector.ListServer.ServerApi.ServerInList) + { + // update player count so that other players can see + if (playerCount < 2) + { + connector.ListServer.ServerApi.UpdateServer(playerCount); + } + // remove server when there is more thasn 2 players + else + { + connector.ListServer.ServerApi.RemoveServer(); + } + } + else + { + // if not in list, and player counts drops below 2, add server to list + if (playerCount < 2) + { + AddServer(playerCount); + } + } + } + + void ServerStartedHandler() + { + AddServer(0); + } + + void AddServer(int playerCount) + { + Transport transport = Transport.activeTransport; + + Uri uri = transport.ServerUri(); + int port = uri.Port; + string protocol = uri.Scheme; + + connector.ListServer.ServerApi.AddServer(new ServerJson + { + displayName = $"Pong Game {(UnityEngine.Random.value * 1000).ToString("0")}", + protocol = protocol, + port = port, + maxPlayerCount = NetworkManager.singleton.maxConnections, + playerCount = playerCount + }); + } + + void ServerStoppedHandler() + { + connector.ListServer.ServerApi.RemoveServer(); + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs.meta new file mode 100644 index 00000000..98a4c110 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f6e5d5acb5879f45a2235ae0f44dc92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs new file mode 100644 index 00000000..cbaed04c --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs @@ -0,0 +1,17 @@ +using UnityEngine; + +namespace Mirror.CloudServices.Examples +{ + public class InstantiateNetworkManager : MonoBehaviour + { + public GameObject prefab; + + private void Awake() + { + if (NetworkManager.singleton == null) + { + Instantiate(prefab); + } + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs.meta new file mode 100644 index 00000000..4b7219be --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dbabb497385c20346a3c8bda4ae69508 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef b/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef new file mode 100644 index 00000000..9e360964 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Mirror.Examples.CloudService", + "references": [ + "Mirror", + "Mirror.Components", + "Mirror.CloudServices" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef.meta new file mode 100644 index 00000000..15f6cdcf --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f254fa29fb722934c9ecbe22427014cd +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs new file mode 100644 index 00000000..8d19585b --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs @@ -0,0 +1,55 @@ +using System; + +namespace Mirror.CloudServices.Example +{ + public class NetworkManagerListServerPong : NetworkManager + { + /// + /// Called when Server Starts + /// + public event Action onServerStarted; + + /// + /// Called when Server Stops + /// + public event Action onServerStopped; + + /// + /// Called when players leaves or joins the room + /// + public event OnPlayerListChanged onPlayerListChanged; + + public delegate void OnPlayerListChanged(int playerCount); + + + int connectionCount => NetworkServer.connections.Count; + + public override void OnServerConnect(NetworkConnection conn) + { + int count = connectionCount; + if (count > maxConnections) + { + conn.Disconnect(); + return; + } + + onPlayerListChanged?.Invoke(count); + } + + public override void OnServerDisconnect(NetworkConnection conn) + { + base.OnServerDisconnect(conn); + onPlayerListChanged?.Invoke(connectionCount); + } + + public override void OnStartServer() + { + onServerStarted?.Invoke(); + } + + public override void OnStopServer() + { + onServerStopped?.Invoke(); + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta new file mode 100644 index 00000000..5c4294f7 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 068feff770f710141afa4a90063a5e6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong.meta new file mode 100644 index 00000000..91af07d4 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6e75061ebf1c0394f8459b06094d603e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs new file mode 100644 index 00000000..6fea47aa --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs @@ -0,0 +1,61 @@ +using UnityEngine; + +namespace Mirror.CloudServices.Examples.Pong +{ + public class Ball : NetworkBehaviour + { + public float speed = 30; + public Rigidbody2D 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()) + { + // 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; + } + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs.meta new file mode 100644 index 00000000..a6fc2724 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4e9cc0829b13e54594a80883836bda7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs new file mode 100644 index 00000000..09861ccf --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs @@ -0,0 +1,53 @@ +using Mirror.CloudServices.Example; +using UnityEngine; + +namespace Mirror.CloudServices.Examples.Pong +{ + public class BallManager : NetworkBehaviour + { + [SerializeField] GameObject ballPrefab = null; + GameObject ball; + NetworkManagerListServerPong manager; + + public override void OnStartServer() + { + manager = (NetworkManager.singleton as NetworkManagerListServerPong); + manager.onPlayerListChanged += onPlayerListChanged; + } + public override void OnStopServer() + { + manager.onPlayerListChanged -= onPlayerListChanged; + } + + private void onPlayerListChanged(int playerCount) + { + if (playerCount >= 2) + { + SpawnBall(); + } + if (playerCount < 2) + { + DestroyBall(); + } + } + + void SpawnBall() + { + if (ball != null) + return; + + ball = Instantiate(ballPrefab); + NetworkServer.Spawn(ball); + } + + void DestroyBall() + { + if (ball == null) + return; + + // destroy ball + NetworkServer.Destroy(ball); + ball = null; + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs.meta new file mode 100644 index 00000000..b914a33e --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9cc796972dc396a42ba3686bd952e329 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs new file mode 100644 index 00000000..ba11ddc8 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs @@ -0,0 +1,21 @@ +using UnityEngine; + +namespace Mirror.CloudServices.Examples.Pong +{ + public class Player : NetworkBehaviour + { + public float speed = 1500; + public Rigidbody2D 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) + return; + + rigidbody2d.velocity = new Vector2(0, Input.GetAxisRaw("Vertical")) * speed * Time.fixedDeltaTime; + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs.meta new file mode 100644 index 00000000..1c858281 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b6cfd54b79bb464dbc6ae7f331ed45f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs new file mode 100644 index 00000000..ac4bd491 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs @@ -0,0 +1,36 @@ +using UnityEngine; + +namespace Mirror.Examples.Pong +{ + public class QuitButton : MonoBehaviour + { + void OnGUI() + { + NetworkManager manager = NetworkManager.singleton; + if (manager == null) + return; + + if (manager.mode == NetworkManagerMode.ServerOnly) + { + if (GUILayout.Button("Stop Server")) + { + manager.StopServer(); + } + } + else if (manager.mode == NetworkManagerMode.Host) + { + if (GUILayout.Button("Stop Host")) + { + manager.StopHost(); + } + } + else if (manager.mode == NetworkManagerMode.ClientOnly) + { + if (GUILayout.Button("Stop Client")) + { + manager.StopClient(); + } + } + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs.meta new file mode 100644 index 00000000..67341ea8 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 76dab753e7255254687cd57985d8d675 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs new file mode 100644 index 00000000..c878d198 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs @@ -0,0 +1,63 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace Mirror.CloudServices.Example +{ + public class ServerListManager : MonoBehaviour + { + [Header("UI")] + [SerializeField] ServerListUI listUI = null; + + [Header("Buttons")] + [SerializeField] Button refreshButton = null; + [SerializeField] Button startServerButton = null; + + + [Header("Auto Refresh")] + [SerializeField] bool autoRefreshServerlist = false; + [SerializeField] int refreshinterval = 20; + + ApiConnector connector; + + void Start() + { + NetworkManager manager = NetworkManager.singleton; + connector = manager.GetComponent(); + + connector.ListServer.ClientApi.onServerListUpdated += listUI.UpdateList; + + if (autoRefreshServerlist) + { + connector.ListServer.ClientApi.StartGetServerListRepeat(refreshinterval); + } + + AddButtonHandlers(); + } + + void AddButtonHandlers() + { + refreshButton.onClick.AddListener(RefreshButtonHandler); + startServerButton.onClick.AddListener(StartServerButtonHandler); + } + + void OnDestroy() + { + if (autoRefreshServerlist) + { + connector.ListServer.ClientApi.StopGetServerListRepeat(); + } + + connector.ListServer.ClientApi.onServerListUpdated -= listUI.UpdateList; + } + + public void RefreshButtonHandler() + { + connector.ListServer.ClientApi.GetServerList(); + } + + public void StartServerButtonHandler() + { + NetworkManager.singleton.StartServer(); + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs.meta new file mode 100644 index 00000000..74c6a0f2 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bfc354d4a7f63ca45a653bf5d479afa0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs new file mode 100644 index 00000000..62f05127 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using Mirror.CloudServices.ListServerService; +using UnityEngine; + +namespace Mirror.CloudServices.Example +{ + public class ServerListUI : MonoBehaviour + { + [SerializeField] ServerListUIItem itemPrefab = null; + [SerializeField] Transform parent = null; + + readonly List items = new List(); + + void OnValidate() + { + if (parent == null) + { + parent = transform; + } + } + + public void UpdateList(ServerCollectionJson serverCollection) + { + DeleteOldItems(); + CreateNewItems(serverCollection.servers); + } + + void CreateNewItems(ServerJson[] servers) + { + foreach (ServerJson server in servers) + { + ServerListUIItem clone = Instantiate(itemPrefab, parent); + clone.Setup(server); + items.Add(clone); + } + } + + void DeleteOldItems() + { + foreach (ServerListUIItem item in items) + { + Destroy(item.gameObject); + } + + items.Clear(); + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs.meta new file mode 100644 index 00000000..f7fe4f2e --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed11184fcffcdc04c9850d82c8014926 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs new file mode 100644 index 00000000..c3e122d7 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs @@ -0,0 +1,34 @@ +using System; +using Mirror.CloudServices.ListServerService; +using UnityEngine; +using UnityEngine.UI; + +namespace Mirror.CloudServices.Example +{ + public class ServerListUIItem : MonoBehaviour + { + [SerializeField] Text nameText = null; + [SerializeField] Text namePlayers = null; + [SerializeField] string playersFormat = "{0} / {1}"; + [SerializeField] Text addressText = null; + + [SerializeField] Button joinButton = null; + + ServerJson server; + + public void Setup(ServerJson server) + { + this.server = server; + nameText.text = server.displayName; + namePlayers.text = string.Format(playersFormat, server.playerCount, server.maxPlayerCount); + addressText.text = server.address; + + joinButton.onClick.AddListener(OnJoinClicked); + } + + void OnJoinClicked() + { + NetworkManager.singleton.StartClient(new Uri(server.address)); + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs.meta b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs.meta new file mode 100644 index 00000000..d8857e80 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c67eda1b451338a428df87fda1e3a7c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites.meta b/Assets/Mirror/Examples/PongWithListServer/Sprites.meta new file mode 100644 index 00000000..420618f3 --- /dev/null +++ b/Assets/Mirror/Examples/PongWithListServer/Sprites.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e53836b13b642484a95c5acdd3017d30 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png b/Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png new file mode 100644 index 0000000000000000000000000000000000000000..20c4387c8b1306491974318a9d601c60207d069f GIT binary patch literal 2791 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 Date: Wed, 24 Jun 2020 22:12:00 +0100 Subject: [PATCH 23/57] adding doc comment for SpawnMessag (#2027) --- Assets/Mirror/Runtime/Messages.cs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Assets/Mirror/Runtime/Messages.cs b/Assets/Mirror/Runtime/Messages.cs index cc15c9c0..57fef86e 100644 --- a/Assets/Mirror/Runtime/Messages.cs +++ b/Assets/Mirror/Runtime/Messages.cs @@ -204,16 +204,43 @@ public void Serialize(NetworkWriter writer) #region Internal System Messages public struct SpawnMessage : IMessageBase { + /// + /// netId of new or existing object + /// public uint netId; + /// + /// Is the spawning object the local player. Sets ClientScene.localPlayer + /// public bool isLocalPlayer; + /// + /// Sets hasAuthority on the spawned object + /// public bool isOwner; + /// + /// The id of the scene object to spawn + /// public ulong sceneId; + /// + /// The id of the prefab to spawn + /// If sceneId != 0 then it is used instead of assetId + /// public Guid assetId; + /// + /// Local position + /// public Vector3 position; + /// + /// Local rotation + /// public Quaternion rotation; + /// + /// Local scale + /// public Vector3 scale; - // the serialized component data - // -> ArraySegment to avoid unnecessary allocations + /// + /// The serialized component data + /// ArraySegment to avoid unnecessary allocations + /// public ArraySegment payload; public void Deserialize(NetworkReader reader) From 54a69bbc833dc881c74c8fddaa29980069588e7a Mon Sep 17 00:00:00 2001 From: James Frowen Date: Wed, 24 Jun 2020 22:13:12 +0100 Subject: [PATCH 24/57] Fixing warning messages (#2030) * disabling warning for empty method * removing null propagation null propagation in untiy can cause MissingReferenceException --- Assets/Mirror/Runtime/NetworkReader.cs | 15 +++++++++++++-- Assets/Mirror/Runtime/Transport/Transport.cs | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Assets/Mirror/Runtime/NetworkReader.cs b/Assets/Mirror/Runtime/NetworkReader.cs index c33fcc87..37f90144 100644 --- a/Assets/Mirror/Runtime/NetworkReader.cs +++ b/Assets/Mirror/Runtime/NetworkReader.cs @@ -340,8 +340,19 @@ public static byte[] ReadBytes(this NetworkReader reader, int count) } public static Guid ReadGuid(this NetworkReader reader) => new Guid(reader.ReadBytes(16)); - public static Transform ReadTransform(this NetworkReader reader) => reader.ReadNetworkIdentity()?.transform; - public static GameObject ReadGameObject(this NetworkReader reader) => reader.ReadNetworkIdentity()?.gameObject; + public static Transform ReadTransform(this NetworkReader reader) + { + // Dont use null propagation here as it could lead to MissingReferenceException + NetworkIdentity networkIdentity = reader.ReadNetworkIdentity(); + return networkIdentity != null ? networkIdentity.transform : null; + } + + public static GameObject ReadGameObject(this NetworkReader reader) + { + // Dont use null propagation here as it could lead to MissingReferenceException + NetworkIdentity networkIdentity = reader.ReadNetworkIdentity(); + return networkIdentity != null ? networkIdentity.gameObject : null; + } public static NetworkIdentity ReadNetworkIdentity(this NetworkReader reader) { diff --git a/Assets/Mirror/Runtime/Transport/Transport.cs b/Assets/Mirror/Runtime/Transport/Transport.cs index 6cd9fd5d..8fc09c30 100644 --- a/Assets/Mirror/Runtime/Transport/Transport.cs +++ b/Assets/Mirror/Runtime/Transport/Transport.cs @@ -200,7 +200,9 @@ public virtual void ClientConnect(Uri uri) // e.g. in uSurvival Transport would apply Cmds before // ShoulderRotation.LateUpdate, resulting in projectile // spawns at the point before shoulder rotation. +#pragma warning disable UNT0001 // Empty Unity message public void Update() { } +#pragma warning restore UNT0001 // Empty Unity message /// /// called when quitting the application by closing the window / pressing stop in the editor From 7d0e907b73530c9a625eaf663837b7eeb36fcee6 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Thu, 25 Jun 2020 01:58:47 +0100 Subject: [PATCH 25/57] feat: More examples for Mirror Cloud Service (#2029) * fixing pong spawn points * renaming files and asmdef * More Cloud examples * Moving pong example to cloud folder * Moving shared code to GUI folder * Adding readme for examples * Adding tank example --- ...oudServices.asmdef => Mirror.Cloud.asmdef} | 2 +- ...s.asmdef.meta => Mirror.Cloud.asmdef.meta} | 0 .../Scripts/Pong.meta => Cloud.meta} | 2 +- Assets/Mirror/Examples/Cloud/GUI.meta | 8 + Assets/Mirror/Examples/Cloud/GUI/Prefabs.meta | 8 + .../GUI}/Prefabs/ListServer Canvas.prefab | 0 .../Prefabs/ListServer Canvas.prefab.meta | 0 .../GUI}/Prefabs/ServerListItem.prefab | 0 .../GUI}/Prefabs/ServerListItem.prefab.meta | 0 Assets/Mirror/Examples/Cloud/GUI/README.md | 8 + .../Mirror/Examples/Cloud/GUI/README.md.meta | 7 + Assets/Mirror/Examples/Cloud/GUI/Scripts.meta | 8 + .../GUI}/Scripts/ApiUpdater.cs | 7 +- .../GUI}/Scripts/ApiUpdater.cs.meta | 0 .../GUI}/Scripts/InstantiateNetworkManager.cs | 3 + .../Scripts/InstantiateNetworkManager.cs.meta | 0 .../Scripts/Mirror.Examples.Cloud.GUI.asmdef} | 5 +- .../Mirror.Examples.Cloud.GUI.asmdef.meta | 7 + .../GUI/Scripts/NetworkManagerListServer.cs} | 5 +- .../Scripts/NetworkManagerListServer.cs.meta | 11 + .../GUI/Scripts/QuitButtonHUD.cs} | 5 +- .../GUI/Scripts/QuitButtonHUD.cs.meta} | 0 .../GUI}/Scripts/ServerListManager.cs | 3 + .../GUI}/Scripts/ServerListManager.cs.meta | 0 .../GUI}/Scripts/ServerListUI.cs | 3 + .../GUI}/Scripts/ServerListUI.cs.meta | 0 .../GUI}/Scripts/ServerListUIItem.cs | 3 + .../GUI}/Scripts/ServerListUIItem.cs.meta | 0 .../{ => Cloud}/PongWithListServer.meta | 2 +- .../PongWithListServer/PhysicsMaterials.meta | 0 .../BallMaterial.physicsMaterial2D | 0 .../BallMaterial.physicsMaterial2D.meta | 0 .../PongWithListServer/Prefabs.meta | 0 .../PongWithListServer/Prefabs/Ball.prefab | 0 .../Prefabs/Ball.prefab.meta | 0 .../Prefabs/NetworkManagerPong.prefab} | 10 +- .../Prefabs/NetworkManagerPong.prefab.meta} | 0 .../PongWithListServer/Prefabs/Racket.prefab | 0 .../Prefabs/Racket.prefab.meta | 0 .../Cloud/PongWithListServer/README.md | 19 + .../Cloud/PongWithListServer/README.md.meta | 7 + .../PongWithListServer/Scenes.meta | 0 .../Scenes/ListServerLobbyScenePong.unity} | 0 .../ListServerLobbyScenePong.unity.meta} | 0 .../Scenes/PongGameScene.unity | 0 .../Scenes/PongGameScene.unity.meta | 0 .../PongWithListServer/Scripts.meta | 0 .../PongWithListServer/Scripts}/Ball.cs | 0 .../PongWithListServer/Scripts}/Ball.cs.meta | 0 .../Scripts}/BallManager.cs | 0 .../Scripts}/BallManager.cs.meta | 0 .../Scripts/Mirror.Examples.Cloud.Pong.asmdef | 16 + .../Mirror.Examples.Cloud.Pong.asmdef.meta} | 0 .../Scripts/NetworkManagerListServerPong.cs | 20 + .../NetworkManagerListServerPong.cs.meta | 0 .../PongWithListServer/Scripts}/Player.cs | 0 .../Scripts}/Player.cs.meta | 0 .../PongWithListServer/Sprites.meta | 0 .../PongWithListServer/Sprites/Ball.png | Bin .../PongWithListServer/Sprites/Ball.png.meta | 0 .../PongWithListServer/Sprites/DottedLine.png | Bin .../Sprites/DottedLine.png.meta | 0 .../PongWithListServer/Sprites/Racket.png | Bin .../Sprites/Racket.png.meta | 0 .../Sprites/WallHorizontal.png | Bin .../Sprites/WallHorizontal.png.meta | 0 .../Sprites/WallVertical.png | Bin .../Sprites/WallVertical.png.meta | 0 .../Examples/Cloud/TanksWithListServer.meta | 8 + .../Cloud/TanksWithListServer/Prefabs.meta | 8 + .../Prefabs/TanksNetworkManager.prefab | 154 +++++ .../Prefabs/TanksNetworkManager.prefab.meta | 7 + .../Cloud/TanksWithListServer/README.md | 19 + .../Cloud/TanksWithListServer/README.md.meta | 7 + .../Cloud/TanksWithListServer/Scenes.meta | 8 + .../Scenes/ListServerLobbySceneTanks.unity | 615 ++++++++++++++++++ .../ListServerLobbySceneTanks.unity.meta | 7 + 77 files changed, 987 insertions(+), 15 deletions(-) rename Assets/Mirror/Cloud/{Mirror.CloudServices.asmdef => Mirror.Cloud.asmdef} (88%) rename Assets/Mirror/Cloud/{Mirror.CloudServices.asmdef.meta => Mirror.Cloud.asmdef.meta} (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Pong.meta => Cloud.meta} (77%) create mode 100644 Assets/Mirror/Examples/Cloud/GUI.meta create mode 100644 Assets/Mirror/Examples/Cloud/GUI/Prefabs.meta rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Prefabs/ListServer Canvas.prefab (100%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Prefabs/ListServer Canvas.prefab.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Prefabs/ServerListItem.prefab (100%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Prefabs/ServerListItem.prefab.meta (100%) create mode 100644 Assets/Mirror/Examples/Cloud/GUI/README.md create mode 100644 Assets/Mirror/Examples/Cloud/GUI/README.md.meta create mode 100644 Assets/Mirror/Examples/Cloud/GUI/Scripts.meta rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ApiUpdater.cs (93%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ApiUpdater.cs.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/InstantiateNetworkManager.cs (75%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/InstantiateNetworkManager.cs.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef => Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef} (73%) create mode 100644 Assets/Mirror/Examples/Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef.meta rename Assets/Mirror/Examples/{PongWithListServer/Scripts/NetworkManagerListServerPong.cs => Cloud/GUI/Scripts/NetworkManagerListServer.cs} (89%) create mode 100644 Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs.meta rename Assets/Mirror/Examples/{PongWithListServer/Scripts/QuitButton.cs => Cloud/GUI/Scripts/QuitButtonHUD.cs} (86%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/QuitButton.cs.meta => Cloud/GUI/Scripts/QuitButtonHUD.cs.meta} (100%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ServerListManager.cs (93%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ServerListManager.cs.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ServerListUI.cs (94%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ServerListUI.cs.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ServerListUIItem.cs (91%) rename Assets/Mirror/Examples/{PongWithListServer => Cloud/GUI}/Scripts/ServerListUIItem.cs.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer.meta (77%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/PhysicsMaterials.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Prefabs.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Prefabs/Ball.prefab (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Prefabs/Ball.prefab.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer/Prefabs/NetworkManager.prefab => Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab} (94%) rename Assets/Mirror/Examples/{PongWithListServer/Prefabs/NetworkManager.prefab.meta => Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab.meta} (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Prefabs/Racket.prefab (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Prefabs/Racket.prefab.meta (100%) create mode 100644 Assets/Mirror/Examples/Cloud/PongWithListServer/README.md create mode 100644 Assets/Mirror/Examples/Cloud/PongWithListServer/README.md.meta rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Scenes.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scenes/ListServerLobbyScene.unity => Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity} (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scenes/ListServerLobbyScene.unity.meta => Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity.meta} (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Scenes/PongGameScene.unity (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Scenes/PongGameScene.unity.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Scripts.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Pong => Cloud/PongWithListServer/Scripts}/Ball.cs (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Pong => Cloud/PongWithListServer/Scripts}/Ball.cs.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Pong => Cloud/PongWithListServer/Scripts}/BallManager.cs (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Pong => Cloud/PongWithListServer/Scripts}/BallManager.cs.meta (100%) create mode 100644 Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Mirror.Examples.Cloud.Pong.asmdef rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef.meta => Cloud/PongWithListServer/Scripts/Mirror.Examples.Cloud.Pong.asmdef.meta} (100%) create mode 100644 Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Pong => Cloud/PongWithListServer/Scripts}/Player.cs (100%) rename Assets/Mirror/Examples/{PongWithListServer/Scripts/Pong => Cloud/PongWithListServer/Scripts}/Player.cs.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/Ball.png (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/Ball.png.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/DottedLine.png (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/DottedLine.png.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/Racket.png (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/Racket.png.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/WallHorizontal.png (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/WallHorizontal.png.meta (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/WallVertical.png (100%) rename Assets/Mirror/Examples/{ => Cloud}/PongWithListServer/Sprites/WallVertical.png.meta (100%) create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer.meta create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs.meta create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab.meta create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md.meta create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes.meta create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity create mode 100644 Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity.meta diff --git a/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef b/Assets/Mirror/Cloud/Mirror.Cloud.asmdef similarity index 88% rename from Assets/Mirror/Cloud/Mirror.CloudServices.asmdef rename to Assets/Mirror/Cloud/Mirror.Cloud.asmdef index ce45ae1c..dbea9716 100644 --- a/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef +++ b/Assets/Mirror/Cloud/Mirror.Cloud.asmdef @@ -1,5 +1,5 @@ { - "name": "Mirror.CloudServices", + "name": "Mirror.Cloud", "references": [ "Mirror" ], diff --git a/Assets/Mirror/Cloud/Mirror.CloudServices.asmdef.meta b/Assets/Mirror/Cloud/Mirror.Cloud.asmdef.meta similarity index 100% rename from Assets/Mirror/Cloud/Mirror.CloudServices.asmdef.meta rename to Assets/Mirror/Cloud/Mirror.Cloud.asmdef.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong.meta b/Assets/Mirror/Examples/Cloud.meta similarity index 77% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Pong.meta rename to Assets/Mirror/Examples/Cloud.meta index 91af07d4..f8e53b05 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong.meta +++ b/Assets/Mirror/Examples/Cloud.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 6e75061ebf1c0394f8459b06094d603e +guid: c6191af3a22db3a40bb6e21d80a01c25 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Mirror/Examples/Cloud/GUI.meta b/Assets/Mirror/Examples/Cloud/GUI.meta new file mode 100644 index 00000000..2e9376d7 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/GUI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 07ef3468f70974a4cb7a8d5111df054b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/Cloud/GUI/Prefabs.meta b/Assets/Mirror/Examples/Cloud/GUI/Prefabs.meta new file mode 100644 index 00000000..edc2d694 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/GUI/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b85187580967c4a42bae2e12c90f2944 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab b/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab rename to Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab.meta b/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/ListServer Canvas.prefab.meta rename to Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab b/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ServerListItem.prefab similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab rename to Assets/Mirror/Examples/Cloud/GUI/Prefabs/ServerListItem.prefab diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab.meta b/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ServerListItem.prefab.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/ServerListItem.prefab.meta rename to Assets/Mirror/Examples/Cloud/GUI/Prefabs/ServerListItem.prefab.meta diff --git a/Assets/Mirror/Examples/Cloud/GUI/README.md b/Assets/Mirror/Examples/Cloud/GUI/README.md new file mode 100644 index 00000000..2703b4d0 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/GUI/README.md @@ -0,0 +1,8 @@ +# Cloud GUI + +This folder contains an example of a List server canvas and scripts that can help set up a GUI. + + +## Other Examples + +See `PongWithListServer` or `TanksWithListServer` for playable examples \ No newline at end of file diff --git a/Assets/Mirror/Examples/Cloud/GUI/README.md.meta b/Assets/Mirror/Examples/Cloud/GUI/README.md.meta new file mode 100644 index 00000000..7e59c07e --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/GUI/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 59f7b35f70aa0d34090c75ea13b576e5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts.meta new file mode 100644 index 00000000..baf76f8d --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c82fa6103a4c0147af4ec3cf57f98d0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs similarity index 93% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs index 6847c0a6..5b1582e7 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs @@ -4,14 +4,17 @@ namespace Mirror.CloudServices.Example { + /// + /// This component should be put on the NetworkManager object + /// public class ApiUpdater : MonoBehaviour { - NetworkManagerListServerPong manager; + NetworkManagerListServer manager; ApiConnector connector; void Start() { - manager = NetworkManager.singleton as NetworkManagerListServerPong; + manager = NetworkManager.singleton as NetworkManagerListServer; connector = manager.GetComponent(); manager.onPlayerListChanged += onPlayerListChanged; diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ApiUpdater.cs.meta rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs similarity index 75% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs index cbaed04c..f8f2bc16 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs @@ -2,6 +2,9 @@ namespace Mirror.CloudServices.Examples { + /// + /// Instantiate a new NetworkManager if one does not already exist + /// public class InstantiateNetworkManager : MonoBehaviour { public GameObject prefab; diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/InstantiateNetworkManager.cs.meta rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef b/Assets/Mirror/Examples/Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef similarity index 73% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef index 9e360964..9f621c84 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef @@ -1,9 +1,8 @@ { - "name": "Mirror.Examples.CloudService", + "name": "Mirror.Examples.Cloud.GUI", "references": [ "Mirror", - "Mirror.Components", - "Mirror.CloudServices" + "Mirror.Cloud" ], "optionalUnityReferences": [], "includePlatforms": [], diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef.meta new file mode 100644 index 00000000..f19330d7 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/Mirror.Examples.Cloud.GUI.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3a6616cce1637584a82fc72820ffd75c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs similarity index 89% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs index 8d19585b..2f6bc9a1 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs @@ -2,7 +2,10 @@ namespace Mirror.CloudServices.Example { - public class NetworkManagerListServerPong : NetworkManager + /// + /// Network Manager with events that are used by the list server + /// + public class NetworkManagerListServer : NetworkManager { /// /// Called when Server Starts diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs.meta new file mode 100644 index 00000000..86775dfd --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95bebb8e810e2954485291a26324f7d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/QuitButtonHUD.cs similarity index 86% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/QuitButtonHUD.cs index ac4bd491..adb849cd 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/QuitButtonHUD.cs @@ -2,7 +2,10 @@ namespace Mirror.Examples.Pong { - public class QuitButton : MonoBehaviour + /// + /// Simular to NetworkManagerHUD but just quit buttons + /// + public class QuitButtonHUD : MonoBehaviour { void OnGUI() { diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/QuitButtonHUD.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/QuitButton.cs.meta rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/QuitButtonHUD.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs similarity index 93% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs index c878d198..905baa1a 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs @@ -3,6 +3,9 @@ namespace Mirror.CloudServices.Example { + /// + /// Uses the ApiConnector on NetworkManager to update the Server list + /// public class ServerListManager : MonoBehaviour { [Header("UI")] diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListManager.cs.meta rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs similarity index 94% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs index 62f05127..6e6f20f8 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs @@ -4,6 +4,9 @@ namespace Mirror.CloudServices.Example { + /// + /// Displays the list of servers + /// public class ServerListUI : MonoBehaviour { [SerializeField] ServerListUIItem itemPrefab = null; diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUI.cs.meta rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs similarity index 91% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs index c3e122d7..753e8e4a 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs @@ -5,6 +5,9 @@ namespace Mirror.CloudServices.Example { + /// + /// Displays a server created by ServerListUI + /// public class ServerListUIItem : MonoBehaviour { [SerializeField] Text nameText = null; diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs.meta b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/ServerListUIItem.cs.meta rename to Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer.meta similarity index 77% rename from Assets/Mirror/Examples/PongWithListServer.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer.meta index 2bc653e4..477c2ab8 100644 --- a/Assets/Mirror/Examples/PongWithListServer.meta +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4144fadaccca8e343a08615df4ae7c71 +guid: ceb3581477b32e44d8e26574395c922e folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/PhysicsMaterials.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/PhysicsMaterials.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D b/Assets/Mirror/Examples/Cloud/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D rename to Assets/Mirror/Examples/Cloud/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D diff --git a/Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/PhysicsMaterials/BallMaterial.physicsMaterial2D.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Ball.prefab similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Ball.prefab diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Ball.prefab.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/Ball.prefab.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Ball.prefab.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab similarity index 94% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab index 04199c66..875b45e1 100644 --- a/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab @@ -14,7 +14,7 @@ GameObject: - component: {fileID: 1442807832621757098} - component: {fileID: 4798169800353248834} m_Layer: 0 - m_Name: NetworkManager + m_Name: NetworkManagerPong m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -51,7 +51,7 @@ MonoBehaviour: _onServerListUpdated: m_PersistentCalls: m_Calls: [] - m_TypeName: Mirror.CloudServices.ServerListEvent, Mirror.CloudServices, Version=0.0.0.0, + m_TypeName: Mirror.CloudServices.ServerListEvent, Mirror.Cloud, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null --- !u!114 &5399210850297115757 MonoBehaviour: @@ -80,10 +80,10 @@ MonoBehaviour: dontDestroyOnLoad: 1 runInBackground: 1 startOnHeadless: 1 - showDebugMessages: 1 + showDebugMessages: 0 serverTickRate: 30 - offlineScene: Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity - onlineScene: Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity + offlineScene: Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity + onlineScene: Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/PongGameScene.unity transport: {fileID: 4798169800353248834} networkAddress: localhost maxConnections: 2 diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/NetworkManager.prefab.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Racket.prefab similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Racket.prefab diff --git a/Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Racket.prefab.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Prefabs/Racket.prefab.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/Racket.prefab.meta diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/README.md b/Assets/Mirror/Examples/Cloud/PongWithListServer/README.md new file mode 100644 index 00000000..00494682 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/README.md @@ -0,0 +1,19 @@ +# Pong with Cloud List server + +This is an example that uses the list server to find games of pong + +## Setup + +Add the following scenes to build settings +``` +Mirror\Examples\Cloud\PongWithListServer\Scenes\ListServerLobbyScenePong.unity +Mirror\Examples\Cloud\PongWithListServer\Scenes\PongGameScene.unity +``` +> Note: you can not connect to your own public ip address, to test out ServerOnly you will need a 2nd person (or a 2nd internet connection) + +## Api Key + +Api key on the NetworkManager is a demo key that should not be used in production. + +Visit [Mirror Networking](https://mirror-networking.com/list-server/) to get an api key that you can use in your game. + diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/README.md.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/README.md.meta new file mode 100644 index 00000000..da5aecab --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 668b542bf443511438b9c50dd68e1091 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scenes.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scenes/ListServerLobbyScene.unity.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/ListServerLobbyScenePong.unity.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/PongGameScene.unity similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/PongGameScene.unity diff --git a/Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/PongGameScene.unity.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scenes/PongGameScene.unity.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scenes/PongGameScene.unity.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Ball.cs.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/BallManager.cs.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs.meta diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Mirror.Examples.Cloud.Pong.asmdef b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Mirror.Examples.Cloud.Pong.asmdef new file mode 100644 index 00000000..9a5d2808 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Mirror.Examples.Cloud.Pong.asmdef @@ -0,0 +1,16 @@ +{ + "name": "Mirror.Examples.Cloud.Pong", + "references": [ + "Mirror", + "Mirror.Cloud", + "Mirror.Examples.Cloud.GUI" + ], + "optionalUnityReferences": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Mirror.Examples.Cloud.Pong.asmdef.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Mirror.Examples.CloudService.asmdef.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Mirror.Examples.Cloud.Pong.asmdef.meta diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs new file mode 100644 index 00000000..ed6770e8 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +namespace Mirror.CloudServices.Example +{ + public sealed class NetworkManagerListServerPong : NetworkManagerListServer + { + public override void OnServerAddPlayer(NetworkConnection conn) + { + Debug.Assert(startPositions.Count == 2, "Pong Scene should have 2 start Poitions"); + // add player at correct spawn position + Transform startPos = numPlayers == 0 ? startPositions[0] : startPositions[1]; + + GameObject player = startPos != null + ? Instantiate(playerPrefab, startPos.position, startPos.rotation) + : Instantiate(playerPrefab); + + NetworkServer.AddPlayerForConnection(conn, player); + } + } +} diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs diff --git a/Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Scripts/Pong/Player.cs.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Ball.png similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Ball.png diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Ball.png.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/Ball.png.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Ball.png.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/DottedLine.png b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/DottedLine.png similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/DottedLine.png rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/DottedLine.png diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/DottedLine.png.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/DottedLine.png.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/DottedLine.png.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/DottedLine.png.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/Racket.png b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Racket.png similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/Racket.png rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Racket.png diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/Racket.png.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Racket.png.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/Racket.png.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/Racket.png.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/WallHorizontal.png b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallHorizontal.png similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/WallHorizontal.png rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallHorizontal.png diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/WallHorizontal.png.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallHorizontal.png.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/WallHorizontal.png.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallHorizontal.png.meta diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/WallVertical.png b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallVertical.png similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/WallVertical.png rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallVertical.png diff --git a/Assets/Mirror/Examples/PongWithListServer/Sprites/WallVertical.png.meta b/Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallVertical.png.meta similarity index 100% rename from Assets/Mirror/Examples/PongWithListServer/Sprites/WallVertical.png.meta rename to Assets/Mirror/Examples/Cloud/PongWithListServer/Sprites/WallVertical.png.meta diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer.meta b/Assets/Mirror/Examples/Cloud/TanksWithListServer.meta new file mode 100644 index 00000000..f1e18981 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 816c29ddda530574b8af14be57ac34a4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs.meta b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs.meta new file mode 100644 index 00000000..2e77bea6 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 372672d455977e74a8b08ca2a0cb8fc5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab new file mode 100644 index 00000000..c2a47e88 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab @@ -0,0 +1,154 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4798169800353248846 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4798169800353248837} + - component: {fileID: 4798169800353248833} + - component: {fileID: 5399210850297115757} + - component: {fileID: 1442807832621757098} + - component: {fileID: 4798169800353248834} + m_Layer: 0 + m_Name: TanksNetworkManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4798169800353248837 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + 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!114 &4798169800353248833 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8bdb99a29e179d14cb0acc43f175d9ad, type: 3} + m_Name: + m_EditorClassIdentifier: + ApiAddress: https://mirror-matchmaking-service-n4ovagixja-ew.a.run.app + ApiKey: AIzaSyA86z6Rvh946XUJ7ZeaK4_CUCpM8g322Uc + _onServerListUpdated: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.CloudServices.ServerListEvent, Mirror.Cloud, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &5399210850297115757 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1f6e5d5acb5879f45a2235ae0f44dc92, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1442807832621757098 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 068feff770f710141afa4a90063a5e6c, type: 3} + m_Name: + m_EditorClassIdentifier: + dontDestroyOnLoad: 1 + runInBackground: 1 + startOnHeadless: 1 + showDebugMessages: 0 + serverTickRate: 30 + offlineScene: Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity + onlineScene: Assets/Mirror/Examples/Tanks/Scenes/Scene.unity + transport: {fileID: 4798169800353248834} + networkAddress: localhost + maxConnections: 4 + disconnectInactiveConnections: 0 + disconnectInactiveTimeout: 60 + authenticator: {fileID: 0} + playerPrefab: {fileID: 1916082411674582, guid: 6f43bf5488a7443d19ab2a83c6b91f35, + type: 3} + autoCreatePlayer: 1 + playerSpawnMethod: 1 + spawnPrefabs: + - {fileID: 5890560936853567077, guid: b7dd46dbf38c643f09e206f9fa4be008, type: 3} +--- !u!114 &4798169800353248834 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c7424c1070fad4ba2a7a96b02fbeb4bb, type: 3} + m_Name: + m_EditorClassIdentifier: + OnClientConnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + OnClientDataReceived: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.ClientDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnClientError: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventException, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnClientDisconnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine.CoreModule, Version=0.0.0.0, + Culture=neutral, PublicKeyToken=null + OnServerConnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + OnServerDataReceived: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.ServerDataReceivedEvent, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnServerError: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventIntException, Mirror, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + OnServerDisconnected: + m_PersistentCalls: + m_Calls: [] + m_TypeName: Mirror.UnityEventInt, Mirror, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + port: 7777 + NoDelay: 1 + serverMaxMessageSize: 16384 + serverMaxReceivesPerTick: 10000 + clientMaxMessageSize: 16384 + clientMaxReceivesPerTick: 1000 diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab.meta b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab.meta new file mode 100644 index 00000000..450f5e9f --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 88a1085bbf219a045928e71a44a98080 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md b/Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md new file mode 100644 index 00000000..c4c1e27a --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md @@ -0,0 +1,19 @@ +# Pong with Cloud List server + +This is an example that uses the list server to find games of tanks + +## Setup + +Add the following scenes to build settings +``` +Assets\Mirror\Examples\Cloud\TanksWithListServer\Scenes\ListServerLobbySceneTanks.unity +Assets\Mirror\Examples\Tanks\Scenes\Scene.unity +``` +> Note: you can not connect to your own public ip address, to test out ServerOnly you will need a 2nd person (or a 2nd internet connection) + +## Api Key + +Api key on the NetworkManager is a demo key that should not be used in production. + +Visit [Mirror Networking](https://mirror-networking.com/list-server/) to get an api key that you can use in your game. + diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md.meta b/Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md.meta new file mode 100644 index 00000000..11fa495d --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f100746ca01e2ef4682e18813b248fa9 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes.meta b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes.meta new file mode 100644 index 00000000..4d77ac95 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 171a7ce331c27824ba49b4bde0488574 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity new file mode 100644 index 00000000..e200d6c2 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity @@ -0,0 +1,615 @@ +%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, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 10 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 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: 512 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + 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 &460456769 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 460456772} + - component: {fileID: 460456771} + - component: {fileID: 460456770} + 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 &460456770 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 460456769} + m_Enabled: 1 +--- !u!20 &460456771 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 460456769} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0.44313726, g: 0, b: 0.33105087, a: 0} + m_projectionMatrixMode: 1 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_GateFitMode: 2 + 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: 0 + 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 &460456772 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 460456769} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + 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 &631456684 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 631456686} + - component: {fileID: 631456685} + m_Layer: 0 + m_Name: InstantiateNetworkManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &631456685 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 631456684} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dbabb497385c20346a3c8bda4ae69508, type: 3} + m_Name: + m_EditorClassIdentifier: + prefab: {fileID: 4798169800353248846, guid: 88a1085bbf219a045928e71a44a98080, type: 3} +--- !u!4 &631456686 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 631456684} + 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: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1092693834 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1092693837} + - component: {fileID: 1092693836} + - component: {fileID: 1092693835} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1092693835 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092693834} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, 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 &1092693836 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092693834} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1092693837 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1092693834} + 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: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1001 &1621652715 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 4971607476965432305, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Name + value: ListServer Canvas + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_ChildControlWidth + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Spacing + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Left + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 2647107856379666145, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Right + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_RootOrder + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Pivot.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476965432301, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Pivot.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607477325490914, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: -0.5 + objectReference: {fileID: 0} + - target: {fileID: 4971607477325490914, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: -1 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058370, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476029058369, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752081, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476373752080, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516856, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476435516855, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354594, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475626354593, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.y + value: 22 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -0.000015258789 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4971607475644947932, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 4971607475641435050, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Value + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4971607476873278848, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476873278848, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476873278848, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4971607476985653605, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4346059805251566766, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Left + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 4346059805251566766, guid: e16e442bbd8d4434cb606afd72bcd08b, + type: 3} + propertyPath: m_Padding.m_Right + value: 5 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: e16e442bbd8d4434cb606afd72bcd08b, type: 3} diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity.meta b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity.meta new file mode 100644 index 00000000..4e2e0a03 --- /dev/null +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Scenes/ListServerLobbySceneTanks.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 50c1ef995f7f09d4e851c197cac6519f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: From 18691dabe016c1c1e26a56ddee74c9fa8cb4d634 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Thu, 25 Jun 2020 12:14:50 +0100 Subject: [PATCH 26/57] adding game name to api updater (#2036) --- .../Examples/Cloud/GUI/Scripts/ApiUpdater.cs | 3 ++- .../Prefabs/NetworkManagerPong.prefab | 1 + .../Prefabs/TanksNetworkManager.prefab | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs index 5b1582e7..f744d203 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs @@ -11,6 +11,7 @@ public class ApiUpdater : MonoBehaviour { NetworkManagerListServer manager; ApiConnector connector; + public string gameName = "Game"; void Start() { @@ -70,7 +71,7 @@ void AddServer(int playerCount) connector.ListServer.ServerApi.AddServer(new ServerJson { - displayName = $"Pong Game {(UnityEngine.Random.value * 1000).ToString("0")}", + displayName = $"{gameName} {(UnityEngine.Random.value * 1000).ToString("0")}", protocol = protocol, port = port, maxPlayerCount = NetworkManager.singleton.maxConnections, diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab index 875b45e1..5049ba1d 100644 --- a/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab @@ -65,6 +65,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 1f6e5d5acb5879f45a2235ae0f44dc92, type: 3} m_Name: m_EditorClassIdentifier: + gameName: Pong Game --- !u!114 &1442807832621757098 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab index c2a47e88..d1794430 100644 --- a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab @@ -11,6 +11,7 @@ GameObject: - component: {fileID: 4798169800353248837} - component: {fileID: 4798169800353248833} - component: {fileID: 5399210850297115757} + - component: {fileID: 5256484632236059241} - component: {fileID: 1442807832621757098} - component: {fileID: 4798169800353248834} m_Layer: 0 @@ -65,6 +66,19 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 1f6e5d5acb5879f45a2235ae0f44dc92, type: 3} m_Name: m_EditorClassIdentifier: + gameName: Tanks Game +--- !u!114 &5256484632236059241 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4798169800353248846} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76dab753e7255254687cd57985d8d675, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!114 &1442807832621757098 MonoBehaviour: m_ObjectHideFlags: 0 From 7c9afca7c54c961d51dfb1824bbdeedf37505106 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Thu, 25 Jun 2020 15:23:09 +0100 Subject: [PATCH 27/57] deleting old list server (#2034) * deleting old list server * fixing prefab name --- .../GUI/Prefabs/ListServer Canvas.prefab | 2 +- Assets/Mirror/Examples/ListServer.meta | 8 - .../Mirror/Examples/ListServer/ListServer.cs | 347 -- .../Examples/ListServer/ListServer.cs.meta | 11 - Assets/Mirror/Examples/ListServer/Scenes.meta | 8 - .../Examples/ListServer/Scenes/NavMesh.asset | Bin 5444 -> 0 bytes .../ListServer/Scenes/NavMesh.asset.meta | 8 - .../Examples/ListServer/Scenes/Scene.unity | 3391 ----------------- .../ListServer/Scenes/Scene.unity.meta | 8 - Assets/Mirror/Examples/ListServer/UI.meta | 8 - .../ListServer/UI/ServerStatusSlot.prefab | 635 --- .../UI/ServerStatusSlot.prefab.meta | 7 - .../ListServer/UI/UIServerStatusSlot.cs | 16 - .../ListServer/UI/UIServerStatusSlot.cs.meta | 11 - 14 files changed, 1 insertion(+), 4459 deletions(-) delete mode 100644 Assets/Mirror/Examples/ListServer.meta delete mode 100644 Assets/Mirror/Examples/ListServer/ListServer.cs delete mode 100644 Assets/Mirror/Examples/ListServer/ListServer.cs.meta delete mode 100644 Assets/Mirror/Examples/ListServer/Scenes.meta delete mode 100644 Assets/Mirror/Examples/ListServer/Scenes/NavMesh.asset delete mode 100644 Assets/Mirror/Examples/ListServer/Scenes/NavMesh.asset.meta delete mode 100644 Assets/Mirror/Examples/ListServer/Scenes/Scene.unity delete mode 100644 Assets/Mirror/Examples/ListServer/Scenes/Scene.unity.meta delete mode 100644 Assets/Mirror/Examples/ListServer/UI.meta delete mode 100644 Assets/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab delete mode 100644 Assets/Mirror/Examples/ListServer/UI/ServerStatusSlot.prefab.meta delete mode 100644 Assets/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs delete mode 100644 Assets/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs.meta diff --git a/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab b/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab index af1c8aff..7a4e6d41 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab +++ b/Assets/Mirror/Examples/Cloud/GUI/Prefabs/ListServer Canvas.prefab @@ -1999,7 +1999,7 @@ GameObject: - component: {fileID: 4971607476965432304} - component: {fileID: 1640965657294869647} m_Layer: 5 - m_Name: Canvas + m_Name: ListServer Canvas m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 diff --git a/Assets/Mirror/Examples/ListServer.meta b/Assets/Mirror/Examples/ListServer.meta deleted file mode 100644 index af33e59e..00000000 --- a/Assets/Mirror/Examples/ListServer.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e192f90e0acbb41f88dfe3dba300a5c9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Mirror/Examples/ListServer/ListServer.cs b/Assets/Mirror/Examples/ListServer/ListServer.cs deleted file mode 100644 index dad836aa..00000000 --- a/Assets/Mirror/Examples/ListServer/ListServer.cs +++ /dev/null @@ -1,347 +0,0 @@ -// add this component to the NetworkManager -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using UnityEngine; -using UnityEngine.UI; - -namespace Mirror.Examples.ListServer -{ - public class ServerStatus - { - public string ip; - // not all transports use a port. assume default port. feel free to also send a port if needed. - //public ushort port; - public string title; - public ushort players; - public ushort capacity; - - public int lastLatency = -1; -#if !UNITY_WEBGL - // Ping isn't known in WebGL builds - public Ping ping; -#endif - public ServerStatus(string ip, /*ushort port,*/ string title, ushort players, ushort capacity) - { - this.ip = ip; - //this.port = port; - this.title = title; - this.players = players; - this.capacity = capacity; -#if !UNITY_WEBGL - // Ping isn't known in WebGL builds - ping = new Ping(ip); -#endif - } - } - - [RequireComponent(typeof(NetworkManager))] - public class ListServer : MonoBehaviour - { - static readonly ILogger logger = LogFactory.GetLogger(typeof(ListServer)); - - [Header("List Server Connection")] - public string listServerIp = "127.0.0.1"; - public ushort gameServerToListenPort = 8887; - public ushort clientToListenPort = 8888; - public string gameServerTitle = "Deathmatch"; - - Telepathy.Client gameServerToListenConnection = new Telepathy.Client(); - Telepathy.Client clientToListenConnection = new Telepathy.Client(); - - [Header("UI")] - public GameObject mainPanel; - public Transform content; - public Text statusText; - public UIServerStatusSlot slotPrefab; - public Button serverAndPlayButton; - public Button serverOnlyButton; - public GameObject connectingPanel; - public Text connectingText; - public Button connectingCancelButton; - int connectingDots = 0; - - // all the servers, stored as dict with unique ip key so we can - // update them more easily - // (use "ip:port" if port is needed) - Dictionary list = new Dictionary(); - - void Start() - { - // examples - //list["127.0.0.1"] = new ServerStatus("127.0.0.1", "Deathmatch", 3, 10); - //list["192.168.0.1"] = new ServerStatus("192.168.0.1", "Free for all", 7, 10); - //list["172.217.22.3"] = new ServerStatus("172.217.22.3", "5vs5", 10, 10); - //list["172.217.16.142"] = new ServerStatus("172.217.16.142", "Hide & Seek Mod", 0, 10); - - // Update once a second. no need to try to reconnect or read data - // in each Update call - // -> calling it more than 1/second would also cause significantly - // more broadcasts in the list server. - InvokeRepeating(nameof(Tick), 0, 1); - } - - bool IsConnecting() => NetworkClient.active && !ClientScene.ready; - bool FullyConnected() => NetworkClient.active && ClientScene.ready; - - // should we use the client to listen connection? - bool UseClientToListen() - { - return !NetworkManager.isHeadless && !NetworkServer.active && !FullyConnected(); - } - - // should we use the game server to listen connection? - bool UseGameServerToListen() - { - return NetworkServer.active; - } - - void Tick() - { - TickGameServer(); - TickClient(); - } - - // send server status to list server - void SendStatus() - { - BinaryWriter writer = new BinaryWriter(new MemoryStream()); - - // create message - writer.Write((ushort)NetworkServer.connections.Count); - writer.Write((ushort)NetworkManager.singleton.maxConnections); - byte[] titleBytes = Encoding.UTF8.GetBytes(gameServerTitle); - writer.Write((ushort)titleBytes.Length); - writer.Write(titleBytes); - writer.Flush(); - - // list server only allows up to 128 bytes per message - if (writer.BaseStream.Position <= 128) - { - // send it - gameServerToListenConnection.Send(((MemoryStream)writer.BaseStream).ToArray()); - } - else logger.LogError("[List Server] List Server will reject messages longer than 128 bytes. Please use a shorter title."); - } - - void TickGameServer() - { - // send server data to listen - if (UseGameServerToListen()) - { - // connected yet? - if (gameServerToListenConnection.Connected) - { - SendStatus(); - } - // otherwise try to connect - // (we may have just started the game) - else if (!gameServerToListenConnection.Connecting) - { - logger.Log("[List Server] GameServer connecting......"); - gameServerToListenConnection.Connect(listServerIp, gameServerToListenPort); - } - } - // shouldn't use game server, but still using it? - else if (gameServerToListenConnection.Connected) - { - gameServerToListenConnection.Disconnect(); - } - } - - void ParseMessage(byte[] bytes) - { - // note: we don't use ReadString here because the list server - // doesn't know C#'s '7-bit-length + utf8' encoding for strings - BinaryReader reader = new BinaryReader(new MemoryStream(bytes, false), Encoding.UTF8); - byte ipBytesLength = reader.ReadByte(); - byte[] ipBytes = reader.ReadBytes(ipBytesLength); - string ip = new IPAddress(ipBytes).ToString(); - //ushort port = reader.ReadUInt16(); <- not all Transports use a port. assume default. - ushort players = reader.ReadUInt16(); - ushort capacity = reader.ReadUInt16(); - ushort titleLength = reader.ReadUInt16(); - string title = Encoding.UTF8.GetString(reader.ReadBytes(titleLength)); - //logger.Log("PARSED: ip=" + ip + /*" port=" + port +*/ " players=" + players + " capacity= " + capacity + " title=" + title); - - // build key - string key = ip/* + ":" + port*/; - - // find existing or create new one - if (list.TryGetValue(key, out ServerStatus server)) - { - // refresh - server.title = title; - server.players = players; - server.capacity = capacity; - } - else - { - // create - server = new ServerStatus(ip, /*port,*/ title, players, capacity); - } - - // save - list[key] = server; - } - - void TickClient() - { - // receive client data from listen - if (UseClientToListen()) - { - // connected yet? - if (clientToListenConnection.Connected) - { - // receive latest game server info - while (clientToListenConnection.GetNextMessage(out Telepathy.Message message)) - { - // connected? - if (message.eventType == Telepathy.EventType.Connected) - logger.Log("[List Server] Client connected!"); - // data message? - else if (message.eventType == Telepathy.EventType.Data) - ParseMessage(message.data); - // disconnected? - else if (message.eventType == Telepathy.EventType.Disconnected) - logger.Log("[List Server] Client disconnected."); - } - -#if !UNITY_WEBGL - // Ping isn't known in WebGL builds - // ping again if previous ping finished - foreach (ServerStatus server in list.Values) - { - if (server.ping.isDone) - { - server.lastLatency = server.ping.time; - server.ping = new Ping(server.ip); - } - } -#endif - } - // otherwise try to connect - // (we may have just joined the menu/disconnect from game server) - else if (!clientToListenConnection.Connecting) - { - logger.Log("[List Server] Client connecting..."); - clientToListenConnection.Connect(listServerIp, clientToListenPort); - } - } - // shouldn't use client, but still using it? (e.g. after joining) - else if (clientToListenConnection.Connected) - { - clientToListenConnection.Disconnect(); - list.Clear(); - } - - // refresh UI afterwards - OnUI(); - } - - // instantiate/remove enough prefabs to match amount - public static void BalancePrefabs(GameObject prefab, int amount, Transform parent) - { - // instantiate until amount - for (int i = parent.childCount; i < amount; ++i) - { - Instantiate(prefab, parent, false); - } - - // delete everything that's too much - // (backwards loop because Destroy changes childCount) - for (int i = parent.childCount - 1; i >= amount; --i) - Destroy(parent.GetChild(i).gameObject); - } - - void OnUI() - { - // only show while client not connected and server not started - if (!NetworkManager.singleton.isNetworkActive || IsConnecting()) - { - mainPanel.SetActive(true); - - // status text - if (clientToListenConnection.Connecting) - { - //statusText.color = Color.yellow; - statusText.text = "Connecting..."; - } - else if (clientToListenConnection.Connected) - { - //statusText.color = Color.green; - statusText.text = "Connected!"; - } - else - { - //statusText.color = Color.gray; - statusText.text = "Disconnected"; - } - - // instantiate/destroy enough slots - BalancePrefabs(slotPrefab.gameObject, list.Count, content); - - // refresh all members - for (int i = 0; i < list.Values.Count; ++i) - { - UIServerStatusSlot slot = content.GetChild(i).GetComponent(); - ServerStatus server = list.Values.ToList()[i]; - slot.titleText.text = server.title; - slot.playersText.text = server.players + "/" + server.capacity; - slot.latencyText.text = server.lastLatency != -1 ? server.lastLatency.ToString() : "..."; - slot.addressText.text = server.ip; - slot.joinButton.interactable = !IsConnecting(); - slot.joinButton.gameObject.SetActive(server.players < server.capacity); - slot.joinButton.onClick.RemoveAllListeners(); - slot.joinButton.onClick.AddListener(() => - { - NetworkManager.singleton.networkAddress = server.ip; - NetworkManager.singleton.StartClient(); - }); - } - - // server buttons - serverAndPlayButton.interactable = !IsConnecting(); - serverAndPlayButton.onClick.RemoveAllListeners(); - serverAndPlayButton.onClick.AddListener(() => - { - NetworkManager.singleton.StartHost(); - }); - - serverOnlyButton.interactable = !IsConnecting(); - serverOnlyButton.onClick.RemoveAllListeners(); - serverOnlyButton.onClick.AddListener(() => - { - NetworkManager.singleton.StartServer(); - }); - } - else mainPanel.SetActive(false); - - // show connecting panel while connecting - if (IsConnecting()) - { - connectingPanel.SetActive(true); - - // . => .. => ... => .... - connectingDots = ((connectingDots + 1) % 4); - connectingText.text = "Connecting" + new string('.', connectingDots); - - // cancel button - connectingCancelButton.onClick.RemoveAllListeners(); - connectingCancelButton.onClick.AddListener(NetworkManager.singleton.StopClient); - } - else connectingPanel.SetActive(false); - } - - // disconnect everything when pressing Stop in the Editor - void OnApplicationQuit() - { - if (gameServerToListenConnection.Connected) - gameServerToListenConnection.Disconnect(); - if (clientToListenConnection.Connected) - clientToListenConnection.Disconnect(); - } - } -} diff --git a/Assets/Mirror/Examples/ListServer/ListServer.cs.meta b/Assets/Mirror/Examples/ListServer/ListServer.cs.meta deleted file mode 100644 index 35af6c4d..00000000 --- a/Assets/Mirror/Examples/ListServer/ListServer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 69f796b44735c414783d66f47b150c5f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Mirror/Examples/ListServer/Scenes.meta b/Assets/Mirror/Examples/ListServer/Scenes.meta deleted file mode 100644 index e0412be3..00000000 --- a/Assets/Mirror/Examples/ListServer/Scenes.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9826d673f42ad4c59b8fc27ae86729e1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Mirror/Examples/ListServer/Scenes/NavMesh.asset b/Assets/Mirror/Examples/ListServer/Scenes/NavMesh.asset deleted file mode 100644 index 3acffc80e7884117f6ba1c24763179df0d46214e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5444 zcmb`KTWl0%6vxlD+ZGYAMNn>HQ9(ed-Ihy{i`%lT1-X>ARODiv?oQj0z0}=VXu-<} z0t$u)W8#xZNrag8!NezhFex#<5b#BOFi{^&Fg_U`j1N9o&;Pr1=c7tv9GIQ+{pQU7 zJLi0tnG#jsAX<mN3i3(^eM}e6 zJ;pyA&uqgZ)Xs5^b8x7`z2Lzt#1n~eUO2&#b0iL4F7jQ%&miCXgpTC<*!LAa5yxD^ zBlI2n?%+0b?&oVwfLO!&)!-B0VSOHBjI-be_zHdK%mWX=qe6d>+u#ovUJ;6aK6o7d zm7(|-fb$7H%5m!WA2d8l1-4J}i5MR;yh8Y&;x_VKXz>e*FS7UtiZ8bKM~W}8_!Y&M zTKrSRAGY}CiZ8SHRmC5%_%+3AE&i?I%Pszc;+XHUZn6%)DE^qmu|83s$1VP+;wvm3 zWoP)WwD?@bpHRGvy%sWC%jbG#tN5%A@T^=%3FeretHJpMzr=H=L-92hKdd;`YpMUB z;!jz;p!iygzoB@Y#V;!Uw8cMGyuO5EKjHmH#2+i+mzZBwyrG1{|C-{B7XMyx>^V9w z`2VapYNz?{%;xgO#uwTE9>6Xa^L)PIykAmv99*vJrOdJJnv8#VU2ih};dT8CIG@m8 z%^FyDSVNl)kJ2q(j~n?O_MR<**Rp?w7{@qsjPF*9wj=Z`AM_!eoyt*x}^V)B5omY?H zQvXAx|AOIR{R0-)`Y&2s>mM{+)@@YP?GSiyXWb5i$EWI}-@iw|`9!{-um%LtBo zhWDkc#dW?pi|c%c443-1mHw-ShxPLo*ZTNYsivuTw7ze6RE+x{tdDvY1xJ0NbbiKQ*X#6zpop_PG!OBeMIwI5 zbzZMoT<7(=;Zk3((>Dwc>%VDntshui>%V1qgl_TsqMq}@JUeB${I1aNqth1G`fpoY z>z}dsX4c2JoHd;L<+^QUj`?=Z@NmEHSX}q}uElk~=M9gD^~HY!h<@?iiery+Y`0q& zOgO$n9UXptOKZyWbNSX`-^~`hTy`5}dfU9TyCcCyhvN^jA^bY>ZokvFBU|vDY|@3B zlImvfg4RVtXlHs&H|CMSNA>ql|QpU@6x&u5I&3V_M zjFT-o>FsVh-Q}HdDX9&~QE&Y@hv^Eo0K=9Pbfd^ewWysR2&>5B2@i7?ercYEBt?XKrj&qxj ziTL=~`HAtdF??%_!?xvp=>uDC_q?Oo$6ZSDE@#vW#D%h%HLX_;Y62 zl-s{prFp{b?s*C^k!R2T%kk1YaYyIId2rq`XKl;eq|Y>Y^3&0Pe`b^?{Gzn@Kjo=& zEbZ%`#}i&8#uNEsJkdsO$V=PuIyKJ7Z^{R+Z#kY6R0i etc. -using UnityEngine; -using UnityEngine.UI; - -namespace Mirror.Examples.ListServer -{ - public class UIServerStatusSlot : MonoBehaviour - { - public Text titleText; - public Text playersText; - public Text latencyText; - public Text addressText; - public Button joinButton; - } -} \ No newline at end of file diff --git a/Assets/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs.meta b/Assets/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs.meta deleted file mode 100644 index a3fee6dc..00000000 --- a/Assets/Mirror/Examples/ListServer/UI/UIServerStatusSlot.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7f24d39c9182b4098bcfd0c2546d0bf2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From e36449cb22d8a2dede0133cf229bc12885c36bdb Mon Sep 17 00:00:00 2001 From: James Frowen Date: Thu, 25 Jun 2020 16:13:47 +0100 Subject: [PATCH 28/57] fix: changing namespace to match folder name (#2037) * updating namespace * updating example name spaces --- Assets/Mirror/Cloud/ApiConnector.cs | 4 ++-- Assets/Mirror/Cloud/Core/BaseApi.cs | 2 +- Assets/Mirror/Cloud/Core/Events.cs | 4 ++-- Assets/Mirror/Cloud/Core/Extensions.cs | 2 +- Assets/Mirror/Cloud/Core/ICoroutineRunner.cs | 2 +- Assets/Mirror/Cloud/Core/IRequestCreator.cs | 2 +- Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs | 2 +- Assets/Mirror/Cloud/Core/JsonStructs.cs | 2 +- Assets/Mirror/Cloud/Core/Logger.cs | 2 +- Assets/Mirror/Cloud/Core/RequestCreator.cs | 2 +- Assets/Mirror/Cloud/ListServer/ListServer.cs | 2 +- Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs | 2 +- Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs | 2 +- Assets/Mirror/Cloud/ListServer/ListServerJson.cs | 2 +- Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs | 2 +- Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs | 4 ++-- .../Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs | 2 +- .../Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs | 2 +- Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs | 2 +- Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs | 4 ++-- Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs | 4 ++-- .../PongWithListServer/Prefabs/NetworkManagerPong.prefab | 2 +- .../Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs | 2 +- .../Examples/Cloud/PongWithListServer/Scripts/BallManager.cs | 4 ++-- .../Scripts/NetworkManagerListServerPong.cs | 2 +- .../Examples/Cloud/PongWithListServer/Scripts/Player.cs | 2 +- .../TanksWithListServer/Prefabs/TanksNetworkManager.prefab | 2 +- 27 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Assets/Mirror/Cloud/ApiConnector.cs b/Assets/Mirror/Cloud/ApiConnector.cs index 21b0c546..fb6713f6 100644 --- a/Assets/Mirror/Cloud/ApiConnector.cs +++ b/Assets/Mirror/Cloud/ApiConnector.cs @@ -1,7 +1,7 @@ -using Mirror.CloudServices.ListServerService; +using Mirror.Cloud.ListServerService; using UnityEngine; -namespace Mirror.CloudServices +namespace Mirror.Cloud { /// /// Used to requests and responses from the mirror api diff --git a/Assets/Mirror/Cloud/Core/BaseApi.cs b/Assets/Mirror/Cloud/Core/BaseApi.cs index 520360cd..720f5981 100644 --- a/Assets/Mirror/Cloud/Core/BaseApi.cs +++ b/Assets/Mirror/Cloud/Core/BaseApi.cs @@ -1,6 +1,6 @@ using System; -namespace Mirror.CloudServices +namespace Mirror.Cloud { public interface IBaseApi { diff --git a/Assets/Mirror/Cloud/Core/Events.cs b/Assets/Mirror/Cloud/Core/Events.cs index 7c61d323..ffee4d32 100644 --- a/Assets/Mirror/Cloud/Core/Events.cs +++ b/Assets/Mirror/Cloud/Core/Events.cs @@ -1,8 +1,8 @@ using System; -using Mirror.CloudServices.ListServerService; +using Mirror.Cloud.ListServerService; using UnityEngine.Events; -namespace Mirror.CloudServices +namespace Mirror.Cloud { [Serializable] public class ServerListEvent : UnityEvent { } diff --git a/Assets/Mirror/Cloud/Core/Extensions.cs b/Assets/Mirror/Cloud/Core/Extensions.cs index 1c728bdc..fa7dfa70 100644 --- a/Assets/Mirror/Cloud/Core/Extensions.cs +++ b/Assets/Mirror/Cloud/Core/Extensions.cs @@ -1,6 +1,6 @@ using UnityEngine.Networking; -namespace Mirror.CloudServices +namespace Mirror.Cloud { public static class Extensions { diff --git a/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs b/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs index 82ac5f91..7fe3bbf3 100644 --- a/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs +++ b/Assets/Mirror/Cloud/Core/ICoroutineRunner.cs @@ -1,7 +1,7 @@ using System.Collections; using UnityEngine; -namespace Mirror.CloudServices +namespace Mirror.Cloud { public interface ICoroutineRunner : IUnityEqualCheck { diff --git a/Assets/Mirror/Cloud/Core/IRequestCreator.cs b/Assets/Mirror/Cloud/Core/IRequestCreator.cs index 84776b92..2709707f 100644 --- a/Assets/Mirror/Cloud/Core/IRequestCreator.cs +++ b/Assets/Mirror/Cloud/Core/IRequestCreator.cs @@ -1,7 +1,7 @@ using System.Collections; using UnityEngine.Networking; -namespace Mirror.CloudServices +namespace Mirror.Cloud { public delegate void RequestSuccess(string responseBody); diff --git a/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs b/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs index 6603edb4..be5e057c 100644 --- a/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs +++ b/Assets/Mirror/Cloud/Core/IUnityEqualCheck.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace Mirror.CloudServices +namespace Mirror.Cloud { /// /// Adds Extension to check if unity object is null. diff --git a/Assets/Mirror/Cloud/Core/JsonStructs.cs b/Assets/Mirror/Cloud/Core/JsonStructs.cs index bbc24b77..7827abcb 100644 --- a/Assets/Mirror/Cloud/Core/JsonStructs.cs +++ b/Assets/Mirror/Cloud/Core/JsonStructs.cs @@ -1,6 +1,6 @@ using System; -namespace Mirror.CloudServices +namespace Mirror.Cloud { [Serializable] public struct CreatedIdJson : ICanBeJson diff --git a/Assets/Mirror/Cloud/Core/Logger.cs b/Assets/Mirror/Cloud/Core/Logger.cs index 90aff07f..32e22ae0 100644 --- a/Assets/Mirror/Cloud/Core/Logger.cs +++ b/Assets/Mirror/Cloud/Core/Logger.cs @@ -2,7 +2,7 @@ using UnityEngine; using UnityEngine.Networking; -namespace Mirror.CloudServices +namespace Mirror.Cloud { public static class Logger { diff --git a/Assets/Mirror/Cloud/Core/RequestCreator.cs b/Assets/Mirror/Cloud/Core/RequestCreator.cs index c92a594d..7195c0e7 100644 --- a/Assets/Mirror/Cloud/Core/RequestCreator.cs +++ b/Assets/Mirror/Cloud/Core/RequestCreator.cs @@ -4,7 +4,7 @@ using UnityEngine; using UnityEngine.Networking; -namespace Mirror.CloudServices +namespace Mirror.Cloud { /// /// Methods to create and send UnityWebRequest diff --git a/Assets/Mirror/Cloud/ListServer/ListServer.cs b/Assets/Mirror/Cloud/ListServer/ListServer.cs index a4c90c52..8b4af805 100644 --- a/Assets/Mirror/Cloud/ListServer/ListServer.cs +++ b/Assets/Mirror/Cloud/ListServer/ListServer.cs @@ -1,7 +1,7 @@ using System; using UnityEngine.Events; -namespace Mirror.CloudServices.ListServerService +namespace Mirror.Cloud.ListServerService { public sealed class ListServer { diff --git a/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs b/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs index fa3944aa..05d2e2e6 100644 --- a/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs +++ b/Assets/Mirror/Cloud/ListServer/ListServerBaseApi.cs @@ -1,4 +1,4 @@ -namespace Mirror.CloudServices.ListServerService +namespace Mirror.Cloud.ListServerService { public abstract class ListServerBaseApi : BaseApi { diff --git a/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs b/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs index 8b877d11..22867c17 100644 --- a/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs +++ b/Assets/Mirror/Cloud/ListServer/ListServerClientApi.cs @@ -3,7 +3,7 @@ using UnityEngine.Events; using UnityEngine.Networking; -namespace Mirror.CloudServices.ListServerService +namespace Mirror.Cloud.ListServerService { public sealed class ListServerClientApi : ListServerBaseApi, IListServerClientApi { diff --git a/Assets/Mirror/Cloud/ListServer/ListServerJson.cs b/Assets/Mirror/Cloud/ListServer/ListServerJson.cs index af937ad8..72688000 100644 --- a/Assets/Mirror/Cloud/ListServer/ListServerJson.cs +++ b/Assets/Mirror/Cloud/ListServer/ListServerJson.cs @@ -1,6 +1,6 @@ using System; -namespace Mirror.CloudServices.ListServerService +namespace Mirror.Cloud.ListServerService { [Serializable] public struct ServerCollectionJson : ICanBeJson diff --git a/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs b/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs index a9827879..1d66ae2a 100644 --- a/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs +++ b/Assets/Mirror/Cloud/ListServer/ListServerServerApi.cs @@ -2,7 +2,7 @@ using UnityEngine; using UnityEngine.Networking; -namespace Mirror.CloudServices.ListServerService +namespace Mirror.Cloud.ListServerService { public sealed class ListServerServerApi : ListServerBaseApi, IListServerServerApi { diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs index f744d203..b99a3097 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ApiUpdater.cs @@ -1,8 +1,8 @@ using System; -using Mirror.CloudServices.ListServerService; +using Mirror.Cloud.ListServerService; using UnityEngine; -namespace Mirror.CloudServices.Example +namespace Mirror.Cloud.Example { /// /// This component should be put on the NetworkManager object diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs index f8f2bc16..2bf8299c 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/InstantiateNetworkManager.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace Mirror.CloudServices.Examples +namespace Mirror.Cloud.Examples { /// /// Instantiate a new NetworkManager if one does not already exist diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs index 2f6bc9a1..498d0375 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/NetworkManagerListServer.cs @@ -1,6 +1,6 @@ using System; -namespace Mirror.CloudServices.Example +namespace Mirror.Cloud.Example { /// /// Network Manager with events that are used by the list server diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs index 905baa1a..0d720197 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs @@ -1,7 +1,7 @@ using UnityEngine; using UnityEngine.UI; -namespace Mirror.CloudServices.Example +namespace Mirror.Cloud.Example { /// /// Uses the ApiConnector on NetworkManager to update the Server list diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs index 6e6f20f8..f42e4592 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUI.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using Mirror.CloudServices.ListServerService; +using Mirror.Cloud.ListServerService; using UnityEngine; -namespace Mirror.CloudServices.Example +namespace Mirror.Cloud.Example { /// /// Displays the list of servers diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs index 753e8e4a..f018a5ee 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListUIItem.cs @@ -1,9 +1,9 @@ using System; -using Mirror.CloudServices.ListServerService; +using Mirror.Cloud.ListServerService; using UnityEngine; using UnityEngine.UI; -namespace Mirror.CloudServices.Example +namespace Mirror.Cloud.Example { /// /// Displays a server created by ServerListUI diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab index 5049ba1d..ae23d06d 100644 --- a/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Prefabs/NetworkManagerPong.prefab @@ -51,7 +51,7 @@ MonoBehaviour: _onServerListUpdated: m_PersistentCalls: m_Calls: [] - m_TypeName: Mirror.CloudServices.ServerListEvent, Mirror.Cloud, Version=0.0.0.0, + m_TypeName: Mirror.Cloud.ServerListEvent, Mirror.Cloud, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null --- !u!114 &5399210850297115757 MonoBehaviour: diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs index 6fea47aa..199b1fd1 100644 --- a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Ball.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace Mirror.CloudServices.Examples.Pong +namespace Mirror.Cloud.Examples.Pong { public class Ball : NetworkBehaviour { diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs index 09861ccf..99a40c59 100644 --- a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/BallManager.cs @@ -1,7 +1,7 @@ -using Mirror.CloudServices.Example; +using Mirror.Cloud.Example; using UnityEngine; -namespace Mirror.CloudServices.Examples.Pong +namespace Mirror.Cloud.Examples.Pong { public class BallManager : NetworkBehaviour { diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs index ed6770e8..cfa32f43 100644 --- a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/NetworkManagerListServerPong.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace Mirror.CloudServices.Example +namespace Mirror.Cloud.Example { public sealed class NetworkManagerListServerPong : NetworkManagerListServer { diff --git a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs index ba11ddc8..6fadd8c9 100644 --- a/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs +++ b/Assets/Mirror/Examples/Cloud/PongWithListServer/Scripts/Player.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace Mirror.CloudServices.Examples.Pong +namespace Mirror.Cloud.Examples.Pong { public class Player : NetworkBehaviour { diff --git a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab index d1794430..7f01682e 100644 --- a/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab +++ b/Assets/Mirror/Examples/Cloud/TanksWithListServer/Prefabs/TanksNetworkManager.prefab @@ -52,7 +52,7 @@ MonoBehaviour: _onServerListUpdated: m_PersistentCalls: m_Calls: [] - m_TypeName: Mirror.CloudServices.ServerListEvent, Mirror.Cloud, Version=0.0.0.0, + m_TypeName: Mirror.Cloud.ServerListEvent, Mirror.Cloud, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null --- !u!114 &5399210850297115757 MonoBehaviour: From 9468278c731a969cb40ff88b9a2975aa3262bcee Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 26 Jun 2020 01:00:08 +0100 Subject: [PATCH 29/57] adding cloud to api docs (#2038) --- doc/doc.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/doc.csproj b/doc/doc.csproj index 11e8f6a5..3d74cf6b 100644 --- a/doc/doc.csproj +++ b/doc/doc.csproj @@ -6,6 +6,7 @@ + \ No newline at end of file From 78bd284b6fcdda3ab45ba985f22ea6662268c998 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 26 Jun 2020 09:47:49 +0100 Subject: [PATCH 30/57] fixing null ref (#2043) --- Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs index 0d720197..14e8e2eb 100644 --- a/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs +++ b/Assets/Mirror/Examples/Cloud/GUI/Scripts/ServerListManager.cs @@ -45,6 +45,9 @@ void AddButtonHandlers() void OnDestroy() { + if (connector == null) + return; + if (autoRefreshServerlist) { connector.ListServer.ClientApi.StopGetServerListRepeat(); From d06ee6a21d8ad227cd8193fdeb8cf11fe6484207 Mon Sep 17 00:00:00 2001 From: Kyle Date: Fri, 26 Jun 2020 06:18:56 -0500 Subject: [PATCH 31/57] Kr/issue 2039 (#2040) * Update NetworkClient.cs * Update NetworkServer.cs * Missed a call --- Assets/Mirror/Runtime/NetworkClient.cs | 8 ++++---- Assets/Mirror/Runtime/NetworkServer.cs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Assets/Mirror/Runtime/NetworkClient.cs b/Assets/Mirror/Runtime/NetworkClient.cs index ae785bfd..7ffd904d 100644 --- a/Assets/Mirror/Runtime/NetworkClient.cs +++ b/Assets/Mirror/Runtime/NetworkClient.cs @@ -96,7 +96,7 @@ public static void Connect(Uri uri) connection.SetHandlers(handlers); } - internal static void ConnectHost() + public static void ConnectHost() { logger.Log("Client Connect Host to Server"); @@ -120,7 +120,7 @@ internal static void ConnectHost() /// /// connect host mode /// - internal static void ConnectLocalServer() + public static void ConnectLocalServer() { NetworkServer.OnConnected(NetworkServer.localConnection); NetworkServer.localConnection.Send(new ConnectMessage()); @@ -130,7 +130,7 @@ internal static void ConnectLocalServer() /// disconnect host mode. this is needed to call DisconnectMessage for /// the host client too. /// - internal static void DisconnectLocalServer() + public static void DisconnectLocalServer() { // only if host connection is running if (NetworkServer.localConnection != null) @@ -253,7 +253,7 @@ public static bool Send(T message, int channelId = Channels.DefaultReliable) return false; } - internal static void Update() + public static void Update() { // local connection? if (connection is ULocalConnectionToServer localConnection) diff --git a/Assets/Mirror/Runtime/NetworkServer.cs b/Assets/Mirror/Runtime/NetworkServer.cs index d52d1436..ab576cba 100644 --- a/Assets/Mirror/Runtime/NetworkServer.cs +++ b/Assets/Mirror/Runtime/NetworkServer.cs @@ -238,7 +238,7 @@ internal static void RemoveLocalConnection() RemoveConnection(0); } - internal static void ActivateHostScene() + public static void ActivateHostScene() { foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values) { @@ -472,7 +472,7 @@ public static void DisconnectAllConnections() } // The user should never need to pump the update loop manually - internal static void Update() + public static void Update() { if (!active) return; From 350ce47db3ffaae6243ad241f2f7aa99ea81706a Mon Sep 17 00:00:00 2001 From: Eunseop Shim Date: Fri, 26 Jun 2020 20:21:54 +0900 Subject: [PATCH 32/57] Implement IReadOnlyDictionary for SyncDictionaries (#2032) --- Assets/Mirror/Runtime/SyncDictionary.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Assets/Mirror/Runtime/SyncDictionary.cs b/Assets/Mirror/Runtime/SyncDictionary.cs index 2040e9c2..32f46396 100644 --- a/Assets/Mirror/Runtime/SyncDictionary.cs +++ b/Assets/Mirror/Runtime/SyncDictionary.cs @@ -6,7 +6,7 @@ namespace Mirror { [EditorBrowsable(EditorBrowsableState.Never)] - public abstract class SyncIDictionary : IDictionary, SyncObject + public abstract class SyncIDictionary : IDictionary, SyncObject, IReadOnlyDictionary { public delegate void SyncDictionaryChanged(Operation op, TKey key, TValue item); @@ -57,6 +57,10 @@ protected virtual void SerializeItem(NetworkWriter writer, TValue item) { } public ICollection Values => objects.Values; + IEnumerable IReadOnlyDictionary.Keys => objects.Keys; + + IEnumerable IReadOnlyDictionary.Values => objects.Values; + // throw away all the changes // this should be called after a successfull sync public void Flush() => changes.Clear(); From ba29119aa1fa8bbfcd85d5300301b8a52ea1f381 Mon Sep 17 00:00:00 2001 From: Kyle Date: Fri, 26 Jun 2020 18:35:58 -0500 Subject: [PATCH 33/57] Missed one internal call that the NetworkManager uses (#2044) --- Assets/Mirror/Runtime/ClientScene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Mirror/Runtime/ClientScene.cs b/Assets/Mirror/Runtime/ClientScene.cs index 01fd792e..afeffd73 100644 --- a/Assets/Mirror/Runtime/ClientScene.cs +++ b/Assets/Mirror/Runtime/ClientScene.cs @@ -50,7 +50,7 @@ private set /// This is read-only. To change the ready state of a client, use ClientScene.Ready(). The server is able to set the ready state of clients using NetworkServer.SetClientReady(), NetworkServer.SetClientNotReady() and NetworkServer.SetAllClientsNotReady(). /// This is done when changing scenes so that clients don't receive state update messages during scene loading. /// - public static bool ready { get; internal set; } + public static bool ready { get; set; } /// /// The NetworkConnection object that is currently "ready". This is the connection to the server where objects are spawned from. From 25285b1574c4e025373e86735ec3eb9734272fd2 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sat, 27 Jun 2020 00:38:50 +0100 Subject: [PATCH 34/57] feat: Experimental NetworkRigidbody (#1822) * NetworkRigidBody --- .../Experimental/NetworkRigidbody.cs | 302 ++++++++++++++++++ .../Experimental/NetworkRigidbody.cs.meta | 11 + 2 files changed, 313 insertions(+) create mode 100644 Assets/Mirror/Components/Experimental/NetworkRigidbody.cs create mode 100644 Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs new file mode 100644 index 00000000..012355f5 --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs @@ -0,0 +1,302 @@ +using UnityEngine; + +namespace Mirror.Experimental +{ + public class NetworkRigidbody : NetworkBehaviour + { + static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkRigidbody)); + + [Header("Settings")] + [SerializeField] internal Rigidbody target = null; + + [Tooltip("Set to true if moves come from owner client, set to false if moves always come from server")] + [SerializeField] bool clientAuthority = false; + + [Header("Velocity")] + + [Tooltip("Syncs Velocity every SyncInterval")] + [SerializeField] bool syncVelocity = true; + + [Tooltip("Set velocity to 0 each frame (only works if syncVelocity is false")] + [SerializeField] bool clearVelocity = false; + + [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")] + [SerializeField] float velocitySensitivity = 0.1f; + + + [Header("Angular Velocity")] + + [Tooltip("Syncs AngularVelocity every SyncInterval")] + [SerializeField] bool syncAngularVelocity = true; + + [Tooltip("Set angularVelocity to 0 each frame (only works if syncAngularVelocity is false")] + [SerializeField] bool clearAngularVelocity = false; + + [Tooltip("Only Syncs Value if distance between previous and current is great than sensitivity")] + [SerializeField] float angularVelocitySensitivity = 0.1f; + + /// + /// Values sent on client with authoirty after they are sent to the server + /// + readonly ClientSyncState previousValue = new ClientSyncState(); + + void OnValidate() + { + if (target == null) + { + target = GetComponent(); + } + } + + + #region Sync vars + [SyncVar(hook = nameof(OnVelocityChanged))] + Vector3 velocity; + + [SyncVar(hook = nameof(OnAngularVelocityChanged))] + Vector3 angularVelocity; + + [SyncVar(hook = nameof(OnIsKinematicChanged))] + bool isKinematic; + + [SyncVar(hook = nameof(OnUseGravityChanged))] + bool useGravity; + + [SyncVar(hook = nameof(OnuDragChanged))] + float drag; + + [SyncVar(hook = nameof(OnAngularDragChanged))] + float angularDrag; + + /// + /// Ignore value if is host or client with Authority + /// + /// + bool IgnoreSync => isServer || ClientWithAuthority; + + bool ClientWithAuthority => clientAuthority && hasAuthority; + + void OnVelocityChanged(Vector3 _, Vector3 newValue) + { + if (IgnoreSync) + return; + + target.velocity = newValue; + } + + + void OnAngularVelocityChanged(Vector3 _, Vector3 newValue) + { + if (IgnoreSync) + return; + + target.angularVelocity = newValue; + } + + void OnIsKinematicChanged(bool _, bool newValue) + { + if (IgnoreSync) + return; + + target.isKinematic = newValue; + } + + void OnUseGravityChanged(bool _, bool newValue) + { + if (IgnoreSync) + return; + + target.useGravity = newValue; + } + + void OnuDragChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.drag = newValue; + } + + void OnAngularDragChanged(float _, float newValue) + { + if (IgnoreSync) + return; + + target.angularDrag = newValue; + } + #endregion + + + internal void Update() + { + if (isServer) + { + SyncToClients(); + } + else if (ClientWithAuthority) + { + SendToServer(); + } + } + + internal void FixedUpdate() + { + if (clearAngularVelocity && !syncAngularVelocity) + { + target.angularVelocity = Vector3.zero; + } + + if (clearVelocity && !syncVelocity) + { + target.velocity = Vector3.zero; + } + } + + /// + /// Updates sync var values on server so that they sync to the client + /// + [Server] + void SyncToClients() + { + if (syncVelocity) + { + velocity = target.velocity; + } + + if (syncAngularVelocity) + { + angularVelocity = target.angularVelocity; + } + + isKinematic = target.isKinematic; + useGravity = target.useGravity; + drag = target.drag; + angularDrag = target.angularDrag; + } + + /// + /// Uses Command to send values to server + /// + [Client] + void SendToServer() + { + if (!hasAuthority) + { + logger.LogWarning("SendToServer called without authority"); + return; + } + + SendVelocity(); + SendRigidBodySettings(); + } + + [Client] + void SendVelocity() + { + Vector3 currentVelocity = syncVelocity ? target.velocity : default; + Vector3 currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default; + + bool velocityChanged = (previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity; + bool angularVelocityChanged = (previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity; + + // if angularVelocity has changed it is likely that velocity has also changed so just sync both values + // however if only velocity has changed just send velocity + if (angularVelocityChanged) + { + CmdSendVelocityAndAngular(currentVelocity, currentAngularVelocity); + previousValue.velocity = currentVelocity; + previousValue.angularVelocity = currentAngularVelocity; + } + else if (velocityChanged) + { + CmdSendVelocity(currentVelocity); + previousValue.velocity = currentVelocity; + } + } + + [Client] + void SendRigidBodySettings() + { + // These shouldn't change often so it is ok to send in their own Command + if (previousValue.isKinematic != target.isKinematic) + { + CmdSendIsKinematic(target.isKinematic); + previousValue.isKinematic = target.isKinematic; + } + if (previousValue.useGravity != target.useGravity) + { + CmdSendUseGravity(target.useGravity); + previousValue.useGravity = target.useGravity; + } + if (previousValue.drag != target.drag) + { + CmdSendDrag(target.drag); + previousValue.drag = target.drag; + } + if (previousValue.angularDrag != target.angularDrag) + { + CmdSendAngularDrag(target.angularDrag); + previousValue.angularDrag = target.angularDrag; + } + } + + /// + /// Called when only Velocity has changed on the client + /// + [Command] + void CmdSendVelocity(Vector3 velocity) + { + this.velocity = velocity; + } + + /// + /// Called when angularVelocity has changed on the client + /// + [Command] + void CmdSendVelocityAndAngular(Vector3 velocity, Vector3 angularVelocity) + { + if (syncVelocity) + { + this.velocity = velocity; + } + this.angularVelocity = angularVelocity; + } + + [Command] + void CmdSendIsKinematic(bool isKinematic) + { + this.isKinematic = isKinematic; + } + + [Command] + void CmdSendUseGravity(bool useGravity) + { + this.useGravity = useGravity; + } + + [Command] + void CmdSendDrag(float drag) + { + this.drag = drag; + } + + [Command] + void CmdSendAngularDrag(float angularDrag) + { + this.angularDrag = angularDrag; + } + + /// + /// holds previously synced values + /// + public class ClientSyncState + { + public Vector3 velocity; + public Vector3 angularVelocity; + public bool isKinematic; + public bool useGravity; + public float drag; + public float angularDrag; + } + } +} diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta new file mode 100644 index 00000000..359ab8c9 --- /dev/null +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 83392ae5c1b731446909f252fd494ae4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 0c30d3398aaabcbf094a88a9c9c77ab4d5062acf Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 28 Jun 2020 23:46:43 +0100 Subject: [PATCH 35/57] fix: Network rigidbody fixes (#2050) * using syncInterval for client auth * only set sync var if change is greater than Sensitivity * fixing client auth sync * using currentVelocity --- .../Experimental/NetworkRigidbody.cs | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs index 012355f5..8abeeb1e 100644 --- a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs @@ -158,16 +158,27 @@ internal void FixedUpdate() [Server] void SyncToClients() { - if (syncVelocity) + // only update if they have changed more than Sensitivity + + Vector3 currentVelocity = syncVelocity ? target.velocity : default; + Vector3 currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default; + + bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity); + bool angularVelocityChanged = syncAngularVelocity && ((previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity); + + if (velocityChanged) { - velocity = target.velocity; + velocity = currentVelocity; + previousValue.velocity = currentVelocity; } - if (syncAngularVelocity) + if (angularVelocityChanged) { - angularVelocity = target.angularVelocity; + angularVelocity = currentVelocity; + previousValue.angularVelocity = currentAngularVelocity; } + // other rigidbody settings isKinematic = target.isKinematic; useGravity = target.useGravity; drag = target.drag; @@ -193,11 +204,15 @@ void SendToServer() [Client] void SendVelocity() { + float now = Time.time; + if (now < previousValue.nextSyncTime) + return; + Vector3 currentVelocity = syncVelocity ? target.velocity : default; Vector3 currentAngularVelocity = syncAngularVelocity ? target.angularVelocity : default; - bool velocityChanged = (previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity; - bool angularVelocityChanged = (previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity; + bool velocityChanged = syncVelocity && ((previousValue.velocity - currentVelocity).sqrMagnitude > velocitySensitivity * velocitySensitivity); + bool angularVelocityChanged = syncAngularVelocity && ((previousValue.angularVelocity - currentAngularVelocity).sqrMagnitude > angularVelocitySensitivity * angularVelocitySensitivity); // if angularVelocity has changed it is likely that velocity has also changed so just sync both values // however if only velocity has changed just send velocity @@ -212,6 +227,13 @@ void SendVelocity() CmdSendVelocity(currentVelocity); previousValue.velocity = currentVelocity; } + + + // only update syncTime if either has changed + if (angularVelocityChanged || velocityChanged) + { + previousValue.nextSyncTime = now + syncInterval; + } } [Client] @@ -247,6 +269,7 @@ void SendRigidBodySettings() void CmdSendVelocity(Vector3 velocity) { this.velocity = velocity; + target.velocity = velocity; } /// @@ -258,32 +281,40 @@ void CmdSendVelocityAndAngular(Vector3 velocity, Vector3 angularVelocity) if (syncVelocity) { this.velocity = velocity; + + target.velocity = velocity; + } this.angularVelocity = angularVelocity; + target.angularVelocity = angularVelocity; } [Command] void CmdSendIsKinematic(bool isKinematic) { this.isKinematic = isKinematic; + target.isKinematic = isKinematic; } [Command] void CmdSendUseGravity(bool useGravity) { this.useGravity = useGravity; + target.useGravity = useGravity; } [Command] void CmdSendDrag(float drag) { this.drag = drag; + target.drag = drag; } [Command] void CmdSendAngularDrag(float angularDrag) { this.angularDrag = angularDrag; + target.angularDrag = angularDrag; } /// @@ -291,6 +322,10 @@ void CmdSendAngularDrag(float angularDrag) /// public class ClientSyncState { + /// + /// Next sync time that velocity will be synced, based on syncInterval. + /// + public float nextSyncTime; public Vector3 velocity; public Vector3 angularVelocity; public bool isKinematic; From ab1b92f74b56787feb7c6fde87c0b9838b8d9d0f Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 28 Jun 2020 23:47:50 +0100 Subject: [PATCH 36/57] fix: addingNetwork rigidbody icon and AddComponentMenu attribute (#2051) * adding icon * adding attributes * adding docs * adding disclaimer at top of doc --- .../Experimental/NetworkRigidbody.cs | 2 ++ .../Experimental/NetworkRigidbody.cs.meta | 2 +- doc/Components/NetworkRigidbody.md | 21 ++++++++++++++++++ doc/Components/NetworkRigidbody.png | Bin 0 -> 38324 bytes doc/Components/index.md | 2 ++ 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 doc/Components/NetworkRigidbody.md create mode 100644 doc/Components/NetworkRigidbody.png diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs index 8abeeb1e..fabf0bbf 100644 --- a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs @@ -2,6 +2,8 @@ namespace Mirror.Experimental { + [AddComponentMenu("Network/Experimental/NetworkRigidbody")] + [HelpURL("https://mirror-networking.com/docs/Components/NetworkRigidbody.html")] public class NetworkRigidbody : NetworkBehaviour { static readonly ILogger logger = LogFactory.GetLogger(typeof(NetworkRigidbody)); diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta index 359ab8c9..1610f0a7 100644 --- a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs.meta @@ -5,7 +5,7 @@ MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 - icon: {instanceID: 0} + icon: {fileID: 2800000, guid: 7453abfe9e8b2c04a8a47eb536fe21eb, type: 3} userData: assetBundleName: assetBundleVariant: diff --git a/doc/Components/NetworkRigidbody.md b/doc/Components/NetworkRigidbody.md new file mode 100644 index 00000000..fa68471a --- /dev/null +++ b/doc/Components/NetworkRigidbody.md @@ -0,0 +1,21 @@ +# Network Rigidbody + +> The Network Rigidbody classed as "Experimental" for now so please share any problems or bugs you find with it and use at your own risk if production builds. + +The Network Rigidbody component synchronizes velocity and other properties of a rigidbody across the network. This component is useful when you have a non-kinematic rigidbody that have constant forces applied to them, like gravity, but also want to apply forces or change velocity to that rigidbody or server or client with authority. For example, objects that move and jump using rigidbody using gravity. + +A game object with a Network Rigidbody component must also have a Network Identity component. When you add a Network Rigidbody component to a game object, Mirror also adds a Network Identity component on that game object if it does not already have one. + +Network Rigidbody works best when there is also a NetworkTransform for the object to keep position as well as velocity in sync. + +![Network Rigidbody inspector](NetworkRigidbody.png) + +By default, Network Rigidbody is server-authoritative unless you check the box for **Client Authority**. Client Authority applies to player objects as well as non-player objects that have been specifically assigned to a client, but only for this component. With this enabled, value changes are send from the client to the server. + +The **Sensitivity** options allow you to set a minimum thresholds before values are send over network. This helps minimize network traffic for very small changes. + +For some object you may not want them to rotate but don't need to sync the Angular Velocity. The **Clear Angular Velocity** will set the Angular Velocity to zero each frame causing the minimizing when objects rotation. The same can apply to **Clear Velocity**. If **Clear Velocity Velocity** is enabled then clear is ignored. + +Normally, changes are sent to all observers of the object this component is on. Setting **Sync Mode** to Owner Only makes the changes private between the server and the client owner of the object. + +You can use the **Sync Interval** to specify how often it syncs (in seconds). This applies both to Client Authority and Server Authority. diff --git a/doc/Components/NetworkRigidbody.png b/doc/Components/NetworkRigidbody.png new file mode 100644 index 0000000000000000000000000000000000000000..241e9b1b1a3b5aabeb625d698bc4e36d4065e5c8 GIT binary patch literal 38324 zcmagGbzGERyDv;ACEXoTf^>H`NVjx%cgIi?(kTc6(%sV1AYIZON`sWtyZAlN+3(r= zoW0KwO1dkD&WOQ7ipiq0Bf1n2(i_M^*Qe+^r^+})KjcnnC^JNAt8~H8zj-5xE&QraOpQTCjbU&Ni5@8gTT)o% zh2)DG;@Y#1PZDGIyUR60yTcm<9bc-kN61)g*15H7+O3If-d$wMBriqm6(V8 z*RNlyEiUGCss)j=atIU!ENpK3PEnKPJ=btA6?Ng_@6E^Mh1$uLNF7^G|Ip z62?B0F9iV&E-q?&BjsASr02c4-Rao^mS34Z|6Qw4EtJF2r-7iW-gvq6O7LoYE3I!W zh(&JcY)xj?|FO84opnOOgm(RHQFnyY_v$bK&(KfBL?7RT`><9oYV*WiisObpKi4 zanmk??c)9I$vMjT-4*Qlb?^&WS>clY9V?TulLLN_!}!3*TWK!GRl5eSy_piV^Xs+1 zk-L-5s>u%XkyPt$w#90cyPresp;srBu)5X6ae6+#3U!fl4!RSUPNWei6bo93Kkhec z%gQMv%j+2|>Y$7zsP52@4`uqQ@QAyHw-*#xIZ6Z z{+;m>CT6y2Euc*5@bT`XNmnv$GTc4@WpP~iiNVnCEX=gq!?5ezVd-zuj3P75ufX2H zeiUJ=_XeiOP{S!&26We}zE$^U17ve^heVNw$4Uqkd2;FstWiob$uk^ju$yd}4P{#K z0om_|x{i+uWP84;?v;m6?JuXgtVb@fUvR(O%=TP8(_Qty){lyguDd!PXKY$FVT@XK z9w5<0zOoOWM%LZxk0qgX&LvsO4%(o{c!))AyXbWB%wpe}=-1|L^XxcW6nbkIL#X}D ztwiAI{-V};n#Ox046j@>;iU7)Kt9*ZGf)fxQR9Pz<4YSvG zRR-<4<2$=qj&p&e%XWVhC$5$pJ9T_9#AL=InFuMRvEt-yo03$td`-Gsc8{W&?R(r}Frs6bO+8zxk)+#TGqhm&+5X6%uX%g{MMFU$ zCYeD;^;IfL&YiblMK}tPoSR#H!!F!`l_w0`7sbm8Ch^qcZ~Jb%89AGL%9#g|zY=p& zX{?8A-9NX%;lVSb{6tBlO`>_1_&MOO?B74X^4T2@$v$w?DCLwpzlX3H`uw6UyL9{J z_Um;h97>}7QsdCusy35`4@{Kd0$!&^-hU>g%{RV>o&PSY(tYpW85oVrSRfh-R~z^g z!0B)>SCQm@cO?ssUtm4`bpfQ@9P#D?aM|$DJYujYJ2?tiaD9fesTZ& zqwr%f=jrw1N~`Dm-x21{oMnx=5#dHPHi(5Kr%6ug%_53)7%KPxw3j#Km&KLrW zJ^H>vttOtRz!N1|car7LwAc(6d*kzatLVp}oSxr5MXdN=h9RcG)pjn-zlVoY=pq&7B>Yk^=GqmNa+u?Ajx(n~x>}l_XL84s~!S*>tM(EW?GK zS_PGK`Gn1eNr{nhfyDYk5Rz(cL5WP>zY2BisLj3fiRF4Inz=(;x5A8v@=R%unl^%YB789M}yHZUDDjfP=S=Ggs^M@*}!N*N|YCc|_-pk2v zTt=9yIGFBU4N#yMcZO4vq+$t&LSDZ5Q{o1pI9h^kbo^N@dfhFI{sESUOko#l^(tZj zo*NGh?h8~M$z9KW{ya4E?~qqa6Ez&{k_|d_7MY^vbLBcV^-hXUx8s3qK1`3RWOfU+ zlA7h(dB*P`YSt476fND$PmlD}(P;^xcTXwo!&(V5$yC`dTn@dylnE7LRMd0K|J`^{ zEt30Wx03ZnOK)P(=kiyVar0sANWD?B&Eyx!MT`L_x%o={o%@UNd3%}I{a0?=&W8QO zsBL@Rd)Y-&7}xLY#6_u)4akTib5#vDUUxot$NKpde{w5xR%I&HdZ&ahg$~~pgYTul zld(1MaU>_@ZQ=d^*~o^&O2I9T7LSkrEn+3~me$ACHfe>9F0+L12xD07iC|Th<+c6# znpMsSP!2JF;{)Z0R(Y!Vfrnh}fdLkl#`hh>mKZ4o=lKVIsSha(N4jyTu)dA*TlChd zWt#3SyP3A-T6cTXO2V^ad=_47UR$x6w(IMU5imyFhmEj3oYlP5?4o-vy`t!F>|6Ga zL0a%tg)I2&e$5E7n||o$p?Spy?cW+2oPtSFXZ4z>X|dHSWUa6A|Qi#$ck|t+D`w$uNna#X^t= zVF9$rS#}*4)Sb>vh=;CIJ&Vax`^zaNV+Oqxh8?lX%0S40$<~!?e6C2Ip^reZfo3r- zt`Pav8H23|5hgMOS1s(2kW%nyTmXy3rsgk{3wf(b!~ap}tyO~za_NwEqj=-&o#pRYSU)95K7wM6oc+D57zw>7 z^Co8m5+_JX~P*-CkW}+uCuZzUr>ys*8 z;gi-Ap$8W%vDayO89N9l^;I2zMZaQiIHH**-$SBibAQ}tJ__r;N1#ZM$q|TvgWaZ!MI+(BF9MzPJ>wYt zToSEPDrn0iMV|xcd%{tYz+>?0A+x8)2h|!AN&QOolElNMCZ#k)iUipl{QB3DAGGB& zmcd#r&9FEvG#~GJ1DND;*s(WP4}@%G72wle2EFZA-q7 zkC#_RJRNcav%1h73h#c~6%0$TN=QM)HpCg4nweQTJVoaJCqW^DO|mDtqbnaqk$w(^ zh)ey_mMR5qmJ= zqzUcHefL>Nzg-A(;k4UEEHXP@r99koE>9fZ`=Fv}#*`AwE5Gg;Eh;k>QbL?EL<;qC z8VVHTfBy6UQvyt%!*#V1@T%`HK2}s_xh9-oZ9TsTzJKER|EygeDm9r9DvMOg=eLtH zV3#FiK7C!ilN|3W79iCkS?f{Up1V7QS{WMfIvvWGBu)LtqfL1 z_nFLt!)X#vI((yfw}kiC{|d}t!RKXPfMs2pD`c;g19uwm^#~|p|sJN--Uiy$`kd#E_*mys<&24$^SK7^wDmuW5tFV0>Km|s@Evf zlm%mcNfS&r+nfL}`QqYlI8(Jk`LsDAI0uICW#z9|g?=akDYdY{;85b=P}x_Kdpm%L zC564hlLHWTXNdN5eIvS6L8*YT3Mk;LA@MN&J7P~5cZ=}>)8q| z3f)6K%~4!WfTi6zI27qSn&|m#(%|3trOKZ|sorz|^&yagW3|>?{&^uLBMj#n8W z-;bZ}!#$=^O2_@{g2c{@IK`ry&mywe+?x%wM7!a^MDRF2?Ed`;vvPPweHkFz`>+;b z*+C-#j^{G;TxtmM|M~M!8PpyznV%}_rdH1-&Os#fUnNTv%uGyNC*)WN_TbA8ZPEA$ zSCW9ISk#K5DuSLR61w}+4ApqJ^gH4?gv)M4bXcRT=%7e1P*N|jI9MmZ*osW2(Jb%J z@ydH}z4wTG+mTtFw5y9DJKzfE)z#+pTw{O7PzX+1e)hMpAJsqXXJD=j+a~t1pr)To zC`jgDq@$x{w@Kcfans>({7T5~Wi4YVi4cV>W`b-FrUIKuFG33_?`Btr3v7<70>8lG zY~&b|xrt9cWHTyZg59MbDmgZvd6UKM5YJ76JpT~iG-;>^PW>i+4-Q3Y5A>cC+p2cW z%O2#xZce`&r_1K&ZsEVU6y>?>|?^_`S(OM1!n^Gvbc}JOw6%+y)EUU^TCg2`n!n z=5rEBWxAIL&=W8;G1)4(j>pqqvqLJ!#I$~4KOvVwPknZFHkUb=Kq*}y7KSvJX{C+M z?T--r-HE^m{qTD(C`}a&J8roxa9hUJz6u?uh4d(BC~#a`r9MAOd-t7a z@W!|GkXPjuuh}hr#6Oci9s=wJ5OMBjIcv3HsXRa*uVxa3n z@_nOSO(S3E0ESX-KIVZy}OK)c1&Y@jR9=4oI zd1!5twUJBYaGaMNb6k>bGS!Pk$J7D0z{oD(b_eg*LS0cRC}Jgx_0UsS>FKO)`^w(i z3DV`7ljdGhph~s+IMBSW<*o*oZlDM18%KTQ5E(x6MVK(Bt-_PA*J3X+I z4+^(7qeGZ!OjEaV(mi}X5<8Kpd~!-_cn4id>3qtE+3`f%6F&yiD@r5^s@nC?SzahC zo!lPrjj?-pEI&mJD+)U2*@{#(7lFrWs_e)#Bn?|r93?GzyD3sS7pDfLlPq*hgNa;o zECt12+7IxpL|k@O4T<-!CuX!J-q|kJm#CMj4*@I+;pcd+7(inTM2$rkLl{D{0@MQn zdHJuWVF>>L!O$oG5ye*r)e+0ebX(s+&}oqxM8(fHL|nLVUxeK*egtx!Y-qb=I}h$1ICm zva-5hg*}%FY)}2p0RK({VhXA@gvHzpBHwCmuVUqVts`b(N(xz77F{~s#F_XOTgE6R zam(4~*`h=f##5rse+HU^Rmc_)j=-%wG{8tL0&Q-18nihz+!g}E-}7E81+qzhIQ74| zB>(|In?@l$_u!2OtMdB0jm1y!Hg~lfK; zKnpi2TewK{R;yASF%76612)cZq?*5`3N<=j)~z5v&Qy&a0AgQ}1n;D%9pRAm;O|GL zcL(F+!~KMo^VL^9`>sY#+qr!SOyV^GO3CwZvuvouUn%B{ z7Vkeaa8ppJ8hu5_R5kjpXsQ)asQS_q4t*TH3s|!>lu-~MgX)+mE{tLq8IVs zQ?_XL8N9#x&(k?BFCl(odnl>ac}vQl;l=nD3;^+(n|a>xMw;Q%)VxFi%z(@8=d;va z8Uf%k?*QE$1pCDeQ{p;H=PwZv8!;==*IP;6SLuM!AsYrhG*~2yCfbN05ph^`C-vp# zef}U>)`_%XK)G%kG&KxnMF9}|zmc-Sp=2nunGe(E^?+7M(-VQxlijnjeilYsV6=h9 z>cti~kt6Jg6??|vB?A|@70Yd-HUT%9b54&Qs-hfDJ+U=)ieq3jK@M%^pIxV1;$oh0 zc{bqEhohy<_!{S}Mj|X1=S#73%*?v=A(Jk>KKzE7t$u5I$vcmppEahgbf-(xubGKLoC72`!dOaLv2{-6Xr-YC&~GRV$*ezGr_W@CkNm|C8(XmQEepqSoV|r26(76Kj{_mh;;^ zL$mt2YMzw(di7ND=m*zcN1{u}+16!~fWtk{!FAk&-ko+sw!qm$HEL)`Z*}L>V{03j zf%GRPjSJWQK)~DvlH!c=R-r#f9IXXPS6Ki7 zK9^nkOqHQwEY3_m#h<8a_?&^4kpqvH^M=2N#gtIY_U>gKVbG2qp|9WD>Xf{%spW_NrMC~A3zhxaC`Ob{@o6UfGE1%%+!|#>WCYzgJBEA)J z@d)Hu#5W&NebjLS>$H~;o%`AGrD{L!czE~O)d_Ie-d@sG?b#1bcA%oY>hCJ|J$}WD zy9_~253#=9KfHtSCBmE$qa)NcTL+vyX`#+iekhT8=jLq7=4Xs@(Sv(@rZ<56<_~`_ z`7W`>Id-<6&pLFjNy*Tb@nF7HG(Y@&{xi{JISHDVaaG%2IjNEgd+anY`$#A{Dp!VD}tyjJ^ z_}z57U8Ajr9nh9t^sM?FRJ5V+E}p4}UA^E=6q)(j4(*8rlc&h@E`KzR&7EaW+J(%M z2PQAFysv$-7FVLq6JM-1;U{0SB)`DcC2ZK`D zs=L;@sdKDD!0yJ0K-f9t;Au_Q;rA48es)-2NqP-Q>LcNxwTU=N2z_td|iAlT&iIpp2Oq&bbu{GLY9GA62D7<6i>+}Oh=awVBg+s^PMFD|lV^_-hjC?OEq zA_5NE1$+U8McsCf*f9wUCTUC;@+F~uZqMW8A-g+>1W)9QQ7vA0Zo2(vKufd}PU?uC z4bHY8H~=2e zya_tZrO$6&bv<6I=E!cFC6%1UZA>6V)bscHZ-Yei=+RRs096b)k+U7!Epdx1`nQ+dO zKyUs=5dL#CEj^2itX@UqjWVipYQ}0*X%eH`L8sZ1E?S42mkW61Z+v*TdPo|Jg|eH}l@IcqxZkwHkJ@}H`>uB@)m~>N&z{T9 zqHR?Q5N8%`M!$WmGBpx*L|W{KjE$Wo;Ap0}I$1MZ{YMq5`_RBkHe<1nws{$aMQipQ zg6N}oz3lpNHL|@uqD0ie(6Trfc}elZY;iPBw5xkLQ>rZUyF|LD>%hfu7*o?!;rmlc z>&5bn8QueimM{KyF;{B=Px^e{gtY1n1Nv|Xj=YW*8#;%0V~GyFadX-p!YXH(s$BBb zeo)c181k+OjN?@)M_tS{-X%azX9m6x)w?XN6z_}OA)sBP<*|^w!J<{1Vfb5TIi6ZK zF0^Db`k~X*=ry#%mD77;NL|lPnqlRJdJizVzVw@RhrB#L?Lj-Zh2GN0;~G)CgZTs> zLo?Gb5JQl^cYGvxxV_^Z4pSPO>OB|ooC^SF2A>jVz{s;8s8BCm$CBTy`FHTLA$SPTBZK>=fKCI+Rr*y4P^3OxObjO z)RujZyo7@F4lAwlD?XQc?%ehle|8T6-I>5LXmKfQz{Ow4UPWTwE-kA}1ae8S3c`yb z(;KykD>wn_R_!;)Ub*yhk5`;%FLslc+s2f;9?ZuMak4g7Q)vKQTvWm5FsojkZoRf% zQgJwR%l~n6O6fhkBN$60ER;`@lp*x~G=r*$%CbK1r(yJFfkkXw@7K|+`{M!3%D&3B zABlCKisMF_T*9IWkUwjYKmqza`odI7`02i`kqAa3(E|qNlf9mxS&ZnB2fiEH6@E^x zWsqt2N}nq#zBK!dYRy>OCg)7!S&JwfG)2W;j<4d9;98I3^Ni1HXFFs)LtR^c8*r$tJWKs^EeE*y34e*}pg2ID9kDl1o ze@gB>#Ivve&Eo`?*7*0ROEr{-GnVglhm z44}n-5-9&Be*Y@h|5lYEWkM}#g8^AYB&$_el18F2Bv?!^LA-?*M3k!Gquth$D{_)2 zkp$+40xntw&_W25%zZ;V?5=y?Xo{1*lyyyD!81u2l$HTRa~n?wS+_*B@XwH~Bgirc z21lB)e3(5A`J|rOPN$LOL}7F1;^Xs;=1-V0=d#C={kOPlgLPTbu%|mGuoc7xpB$_HBw!_sM`ah zCZ5A)MrI9m^*#BGnm6jM-}8kt0+XB#FAF_iFsX+7Tos&a$zs}8I;|cR zir;RIn%3L|(LD}-=3()(G=>dP!L^YlDLOQ7z?JQ|p9nW6Wo)oB?M(GBD6D z(RNJ#q5Weu65t^fB==v+;lw`<$bTVG|9NVR14;$c!gb~(R6BO_1-K`f=tP78EusY^ zY4OSsxC*Es;#hsUuDB|D33Wl}1*i=10Yr$H$v3v$Z5()pYg%wZU=4im28eC5w9crlUv5N_lm)B1-WtWx3Qf~CBwYGP{g z_I3;*HE*9jrFA2B6&&4S?pM?Y0oYUuxw}~{LmkEPUM9(5%;l2!rDrqRC@#9~3rqS^ljFSm40;j@6|EJ^z{{LYR$?pzGI033 zPuL-=`9(0CwKr&FLVAuegB~Bzqr2z1iVRAs=6Qmhk@j;zmSfcBtfK#@z{!5B$H2D{ z+VCXy;Zt%)Pqx`SiU2RK>??=kuO7^;jyJ{GL4U@d;}25iAnx$({`1p4urm}`24bV5 zlZ<=9haiYpGd&^LlaUyd#O`oMFI@GM0v;~4QhbrNeGm~jk(P5avRWRbPz7*`4ZU}8 zRxCkR^$`#8sRySt{k9Jczkg)?fK!o*ifZuBujyy&xJlQq%=u2Ox!*fukzr}5WXiL7 z3$-;PMEO&RbG|2Yz6Xrdi~enJt2Mec@iWuY@omf4yGfhCYMClgqx}V_4bloIezS|4 zSw@)*2Leb)8iSK@MKG62!Vgp+T~h92$0FjvJT%W$4H8S7@d$VL z_wD^y_`(qD>NV4kf))*bHMdYTH~5O=);8k!4|kay(E9X!aRWu(qHQVC(a~u}JGyK& zpEl-wjeF9`-R^guBoHqq?r$|4O4NKyu^~C=HqBCY0L-aTmVhhttSb9v<8JxyXavS& zp;hx?eu*-oSimZ+Jp7M0Eg(RA8pIWnF5Ez&P_4froj*gH3I6SSeNe>yPonIh5k( zmI*R$!pjSy(|bmAOeP?(V5+W*ZuM7=Nf#m=$KdCn5fY&i^N}BL+YQdbf1>==41v7n zu%ar6tjAV=>8>XxhVkzjK_>N_bHx3h%7`UzVtmN-ReKN66(@3WY~n|ud8uS+6221a zD-TdpVbe{-=UdW~CV!9QR-$|l{7MgK?>mQ2nIY>BVu)<6%Ylh=uGR@Bh z2+dME-Sc7wu4jplrg}M(c6`iyb`Q%P(wKVrR})S|L!_Mo^gpDp@=Z7;$U)Mun0~;6 zWh^)gQdC>do3mGwfQ&c)vcXzr3d-?r(QwNRIq2cFZ2KZ(p;+HyWtl_C;>X02Bbz6G&A#GPZs)`D{5gsZ*;I%nYWF2* zz+!o=UcURn5;Fk1G(JE3d$Bgki5+kO&U>+xv@0C$>ExG!%|^lWWCSUSG5ayuyv?zw2!2J+&HJQj2ohnwL zysS1dbNw*Q`dYMo@qe4V&u`3u#E8B{{xGY2?|(i->rPC?$T(_qS;25rA`>f3l?nRK zYB!qjy-~xrJRf%>v+xx~W_&}o1}s3(s00uRLc^ob!$fNc*|$MTjgrjoG=KM2MBOciPMQ*mhu^^)(8;=2G<27O=)8ko>AMA=obq*NLs4hc!=>l0veeFqgh~ z3lsChzbD8I3(`M2^M8UH|G5=?P{`!?H3QNH6&lZtiesbR{~w_8uc$0=R{@MM14XZ3+^8rfdgq#&NTOlcIZP}`dgKCBe_{W6)uJz4fUaq@1SpPkda3X&60 zR|b(-%&B+5PXAjTwnrtGOADDWhJZ@NDLzTZ^{a()edJ)&4OXqy&}%xwytaQ5yt&qa z{@gm}JvQD4p}eYLQ2j{+=J+`)n+p7-(l^i6V`C@qH`q-3ky}6(r~s7S%<`r6*&iE0 z3#={^S0Suf0(X%TD0kfX$$oF@ke~K*lX>zX*l#zM&ZP;xsdq4jF)0RFKDtIED;mSA zitx<;6A1t=^DjC&OcK1evQbekQ6uvFW!=20rF!NIt~@#&54TDg0!QowTvz(uhhZh9 zwP+uQ@SgS2d61{=EVjf&V6j3sFle;X31@}XmLh8OE>-m6v>H4`3EOo)n0v{fga%hR zgiYXA;r*$;LQ{R$&3PV6>#Od23E}uOR!%?hhfGhVu!F{B&LK3ieU^1NW#?)qa(Eb^cr_xux-KjZVC?a+(qSK?Fl#31nD0 zkPA)!{HPg)WIBoag5d3Q99K6NJ%*^RyKN63s-4Q#W7UN~C8Oj#O+n-DFUqK$;z$Kc z_nu{|f2DX8{Pg)*_PE`DtN&VTD5E#cXE$vm_z|$0it^R}^7pLnR{G6UUJ}FrXEFC| zCl;u&w)TO-Pz?@2ryjt}{sbofIRNxFL|q?Wd?p&Z8-80gliu3>>EoWI<06WMKag>4 z3XVJO92Oew-}iHc?j0;P*cM%a0+-84ktgLgiO-wqq^GKeNlnMAA*9``h)O1(IJ_f2 z996)}Rs zhFWx?z;Z8N9?ZXIH0Y|%s$f`fRt;yCO{jD?>ATD@L*Mz0vi%Z-eM*st!`eTV` zOG+|~6{gJH4q0Tsiw_AP!-G@0xOHJ~CG|g^W951*0<-5};Yh0qFts2^ouxykV}hxL?1-6RLHkK@uX^Rjknn4wk_r^tL+$+q`Dg10QxG-evpS5Lwmd=PW7?P9)H@A)xmr0M zL`KK5rzlg5p;cP{Nk$=oYTjRnQ*d;r1}7!adD6wYPPf+eL`7EqUDC`pN7^(xh(Zu2 zs0D<^>2y0{k=W0$STVPqhOAopIfIZ*X%f`LWd8%~%Mqxh>W|q$D47{UKbxIR%cxoA zhz00i)6C;4cBp|nt3ml3jJgH5b@qMT1(5WuAJ#+B$_h@XJsdj0oCB6l7&)Mt!$Z=VfWrP}ReRsVpw^Pa6I>j>DzbE{qWgh8|xmVfpq z2`$PEJ3D+j5Kd6Ygq9aGe=WElFE2RDRXyLg0H-uPmnbH9%jsfKp^3%<40Kfq&c53DtgSjx}01h}3huKx|7&F0C;=S7b^?XD9qBI+t}{+kVB z*P~5zyanertb+VA{O&Xe8n(c3twZ;ouzr8v%6g_aK{25m#3N^Qy@Dg)^5M3&yxBv# zp-u}Fn3o{4pR8s}Q|6i}dg_8i2Vx0M+`C`m?Q`+pNZ*``l&P0&-h6}{#IRT@vaA*- zvHloqxcmFX91n6mG09SwI3dacw?@>DPYJPwCn*J@=dZ4Fptly;dxY9mj?cH;{XG<9 z{cK4N`;#!lSp{qm0MR1OQ>e?h&Zbu6IaXe`{dnR4tQ7)(J0ck3( z-Zs`l$Agh46!kGWv2R#{@O@#Mg^gG2T)!_%Gj{+l2zU%0Rw&w1?}3aq>m7^*t<3-U z4MS1fk%YSdBqm?FQKnBU-VQwJwsu)IzK{cy)bp)aYT0cGM}LDWB@fV;O@P7viPv^ua$G7 z`kEn#RRBWIl4~32(2IrDA#OE+`W*)#|EYq`~@L%iM2J z5|Hp1{s~iXhVRq$L(0v{nOO>KiaGV|X@60d18q~KiDZE45Cj5Z z1|s9g>oBZLXI)3mi8m$-KhEVWTCV4K+9!L-;>I=5x)7KBjAqt#2+>2@K(E`$|0tAr zP}!MYC^UB6kbF%ub%9%i zc}c+pA=$t%iWxyPO%L+F6@I$?7`}D7-QHBgA2@%E=J+|5R`D)2?a}Wf?tBCXWh+zSFc8x zf*PP}dL>lRr`UUX!JA%(s&y!6qfCQE%+$1zFH7T5inc!*KV{H8Q z!8rS;!E>B4^M!BOiHCnj`z5-qu#<|@H!(>_DEs76Js71&f(4ffol`hUG|Ik>y+Fkl za0z8){sARj#L>DgWb&HXDe_Pe;~0mf8J~3Ia=SOjl+5FY>_oaGYPxgeg2HJ!D;+F% zK%fyZhO^6`Z|i5fc)YAu>9Zex@TLEN9S5wFcEhTzmn%a z?P0d2`D>*jG#rMt=?jYynTb*3Kj2w(70m*e2=v7{~K(bF@A%K>oS_VA<7*%zD_L9 zLlY$%HK(f?&y7y-GvQ_)&ufq%gURKb0T$r?Y487I6WY=H$lG1th>@Q5%Er0c0pKZf zsPK?(h`x>#>6*C*0mB2fS`=RDy+NE%IMeXnKAu6@2x3FY=*Ulz!W7Y|42kDBihwuURZ3J}mgu*CnW@y#u=%7TJDf~UGdrA;Y&GBB zX8Li!d?rY7uB;9|XGwyKI>_vWBDwI}DJP0qayAJ5>~FA{On;UmUJ&6I!BNSdwoG1P z7Jezzj7j4kG~+_AReByr-%yhcGxP}ay`dg^L(wPa)pURQLr%S%QkKqIS5;NfV&=_I z$*)?cRRvCq)2X&!QDLvW(&ux&(_@P!8g1)B{vb~U;&4a}prQ%ld5}khx^l|B08xei zh0!bTPN|ugkILcpWJ+98%*Qv(Zm;%)&Clz{&3^v$+^NC)YU5&j*YjhQWhg=rK=gY| zWtW#wq2Z8S89RpXvr$NGv`Y!v^j^iv34`!g-|8u_~;Do>>c^nnKB@?I96duE9 zVR9Y|-X5f+VvhVkM{|Z4m6*BvO{q0T741-;miy2kgCqQAzW?7ph%%k@>Y}tg*r830_q#ygpCTM8 zf0g<26>jmF*twA}sZ7C|m=G@&et0Tj{p|n3@MkTQdGs!u6z0TZ(eWXnL;*)n8#C{PU&np?FxKM z?UfJ-L@+^vl$+CW{qsw6(?3%fggv99RyGU1V_#|Q#k2rrnf7=?ki~GkuVb2ph_ew6 zLB5jdh=Sq8U)Dz172F&D%MzcF5&SbR zSjzQVHEkgS7`5T5Fl@hxPAPl#;;yClXY|NUJuBhrgluNsaH@K)`Fn4$TMiRZY5WLB`zgb!xW?kPQ=G z>mT%fIA9;@l7+(Rw>>K&8;+sNH@`O(+?fc5t##X=J>S~A#l#|_ZI5W%=QFi*M60EX z?+_JR0tSeABnM%x2cPX6!#k>1QMeHGXUB5sP|$w*0x-uyR35P>q$e4xNQ&~PGa-C2 zu!#~%l@p=Kco}Z%^(#E4KlEE6r^J8S$eTE=Y06F8%^}Gb|_P{dopf{J{^r|J;NEi)RrQ~BcGm>wI!G8GXJpOX3w zzZXJK>&1*iU*F{`CXYgb>nFAQ_mC&MjCTJfm-d5e_a4+IAzCB1nIA1!iEF(n^o+Ea zYE(n+pOxMzxq9147MkhR>n)b29xnT;PpRgaWbe8VnyAmCt6kN?2E50<u}?0x_F? z|9-p)6^SDJ+|cMd&VTO|geKx(Pr~pqS}-2%PGWP?+5MTxoT#QGxAlroCWY{FdyVA% zb|0xP zZmBAmRiwpgyY1`PrcmTFj~XSVcxO_8<@2De^17|Q|6KGX=k2@TdER)+ECK{|_T?Mc zO4LwVmg48#Y)qyMvqoQsfC8r{NI+TpOQQNS{8&ENQ#qIEOXB0$6=0BKgpAUKRTp~r zfWW>fxK8)FEy9)+f4mZSz6A5Xqo!MYLdY2Y9Ep%qI9-rzUgQ?!{-@1}tJ42vbK(Iv z7BgbyiRDz(mcbtV4J?L`mq+>!==B+%hcPIyIT7XB8J2JQ4V+z%KYnJ|#2bk-+lgFO z*bFFze}Vc;?k?@V-fW6%fwQmbLUomgYwe>uFtoB49@*RXjoEJe{j+}1Xed%B{R0;k zCKkP2u3hgC`?PM5@HNcd;F}(z!jTwDwavf8)5~2tTqoPu4h{iMG|waD1|Q{*3?eU5 zcq!!hSY^UCbwe+H;XlRbHoa67e`?o*Ux=}Mj<9U?_o>9%)saympmZBVx9IEo^A7>I z8jHDg;K_b<>Ry?XzAr)!yDkNtUMp9S+XXwr|G0Y0rahp(bu!Tb>%z8^UT@>~^^=@z zawzdn!LP+G?yP*-mmt4YqU|A$6oP` zLN#nvVR57V`M_$R4Dz=@0fSh&{7+tnwtG(zD5hZH^_}(Ik2t6x}Y<5 zg@l3aED+CHUi|&&SK0aK^Wd<~H@f}#Q_w*#1nUnI1}dx9T>!Le<B~<8PeWTI_kB_vdQ`Q3+|CXJ!=-pg#9_dWSwCpg zmv^wR;UT{0A9Mz|uzz5OdxrDPs~VCBx~PBoz#EY&@_pk4oxhZ|{uOf7i_E`B{m4>q zQfcT)r=h{DVuOymKQeT_9`A9|z^psQjG}($2NM1~8BHzCjXasOj6t>Ol5nkGpN&qV zLlG7Dc7pUb_^~FKIBI%d@=Xi0ho&lbtaz&}TRAEdX&P)a<}=!YL!>QOcEg7Bd1c=t zSPn`kuA?txzrLR{c48GsJs64-9AG+3Pg>W89+GE4jpE_=u|Gw>i2j7n@dHNEf>Z%6 z#8O5^G|7p>VDn?|2!@tUgF~I&({*GoEtPD@h%bMwW7(hMIZ^T8^!F!c(#6W5%Ew0uqan-ar{Ps=mB7X)kH#VQFn z1on4N2r~brwBNZ}1PeukM|?`yp`;yW15P?`Hm$TmvRYx8T&w)zVEkRH{O#0gSUL*# z8owUtv3o;9s$hHxLR5$8e|!-|Xvr-ITFjdd4)B;)4*yS7;3v*F>i?ArXjB{npAr{b zclYGuUx(W5h}rWwc-I2G1-8tEeAPlE)m9(L68*Z;8J@btWI7Fn(v-J!la;>S1Ee2E zilMX1wJgyDJfjXpp@v?35(&^K*bplfHA7%6odqcITd6Vm9oiK8qHEjkFg_t$R!{o7 z9Dj)~;SX6Vaze>E;el?-a-UShKBSyF+-_u~6l+UQzt1bsUbHG!NmQFQ-)PIQ`LSN; zJ&pBB@|300o4ko-(>tKWzoX?WK&lB9jSdh1LqGudd?46xQ);SId`y~&deT|{qNvE z^tLSrVq}uq%1E&am*Xqcn0ZU~v@d{E**TF0!CTPFNVQV`!7(0%;7b%d-vnS%R ziIGSq(TAOM1Cfw@=ekm)-(Tu+i8NK^`j+5ldp3u)w$|@Yv&w|oORA{E&e5EA)9ux? zw2gS%2`Ca^uL=k~p<{oDU9-Bmb$K!ZB?#GQ+gkhS0 z0W>hNYvOG#>5>|fr4P%^-`>h338qRs9}<4}^P7PAZ90avDyx5q{WN>2GfIu-sK4~z z&S^MRG1J-|)v+4w#?QE_<)+1J_VA>k8S>!$?o1;^lJ+c3I5E;BgaJL|LFY!FoV}D^ zAjTphb%|Bu8i_>K<3wf`a8EyGC6=wav*Fv_>FjTLuC2;i>FI(u7?;i zxHOlt{FtHkxUa7EfHykzbQVkKEYtIf9=oQ0X#r|J_Yq+>xgbm4r`LXZ6z6MW#Xkgm zGNWoTbA8c0AF+3SFL~r~Y?rdgOAcRt)haNTT$D13FWXyWTnP*RRng{wbHc?*nK=}x zvR*Mlt;*%4KDwQ+$_e&U<53c}`*DxxByArEX0VK>N7pd4iD()T25ZGy4x|e_a0$pK>fz!Wd?@l}liwGW zm#*@yKxPvUy8?X}C{seYe>_Hf*0(Xq<#C`{(7dmK`kBS!n95<2!JeO#9o)sw*dQUf z&UT@7Ip>5&MKRnb;rT1=U(R z+fshARm1PGX&Rx<5+C+1i4sY>K*hR9Ogm(^z9+Wt>8E%glZ_EHFdkn&83CQ&b528N zJ%pbzjmeT_HORRx93lfPRgVa{yNd&Msl_=V9ndRluAcJyPFi|qP+HFM`}JKP0rZ5R z^Uq)^A;)ax_OK=@B`4SI{|OQN7uKW zN2{cY-&(`x)Ikl0_^iNC5M8=enx;eQ!q?ULB8bCmx}>96*pM|REx!4@OY}wIrM6F3 z%3GhRZ^!G}SMcWAyyVFC9;mY3PRZ3PdpjwSasTuiYXC^@GR3ldU z&e_L8VU;9)hqE`VN?U#(ZK)RoeCn#7I+Rz&lVR+0|0L`ifuns zboH=0BxP@n`ed8fl~Cw>9P*8=e#b{u+;QBIB$&7RAjBfHlgt0+?Dj{T;gI6X<1NGv ziW-Q<&nJYR!TEm|ejt1mq3%D;5@(B8SSPN}#09*5W` zTaJlHM`6P{`5?`pjg9KcBx?S3MwKFJK{Ib-?Fh%9M>+odSH~?k49@F21lYX~@(Yf` zKkePN-{>WmBuGX^(&)uB9%}HEvYF*flOp!)z+WJf>n)4U0AwLp%P_fb&YvMab7OH7 zeNBCY+1tVkm<2dJYc+dm^Y zG0v+G&qIPb2 z2E#bfYEn0?l%hmR1R1mWC+cdYx!E8bzWaQZob3G;iR&M{Sj- zgi75VS zsA^%q&IDsUU9bqu=(A1C%#)8#Tzjsaw~8Qp{E07LIyNp&Q0mNKndhNY07O^rE*~wh zQcw^S^8~%`+o@4emdNPxUHvy*Lg-&zLVubxhz0V}d$yfIqr&kYgJ1Xz{$(_c#rrfsC z*upAyK{b+I>S9Y2N5#)drILpy#!Ai;V;KagDJd5Tuan{l-RO~ePfij;SY+}TYuP-R z*C?Ot&uF2E`>)Z0Sh$+-lKu@J*X>r#u!}!vt#JrLDYLezvt367$0;nAE};d{)WPSJ zrqcxjHZG0#8#ftCoM91F->!9An=FV^<2%!Hem|fN%`_+C{G)^G=H3=&cH@x7 zNi*Sw{MCeDnPy?aHXFAGhu0H|bhz6GSL02G?D^PFD`X}?os_t+fWC0Mq|`=Ck7Q+p zCn7IP30!!t=Jx5+|;~&myz30Bw8Zlp3&=`ZhVi)=fNB*HWO0P(>VSbMK;-Diu zL*`)CnPa9oeEFHKWgbqxSuz6-i3ciQ>LR8X&=0Tb)71#Mha6l}Bf^;bF^ipIKdBRB z&3YH}|L!>+A5o#gGjKY}0glGXwJzNkgcyoXEr6T!)N^g{4hOZl#oz4)$jS`hAjHF% zqaA^=GJ_YTYAko&oc#wo_{~iHWgAxpW$1sg2U8jF36cwrIgh2EeakNtm-&>;Fv;qp zJ2K3EFQR%OM2jd}r#WBmy&or)#Dk>*$!LlN8=qB+sdF8b!#C_|NN?=NS2Hg>3>kY& zbsEuXsK2b7fQ;uVeY5!MdN&YY`u#WfA{OD_c{)y-=&9pPKm^V8hsK z0+&8adfs?>=e_#QwY!YCRfYxuvzanCttYEJMjOk5@GEebx{nDi5HUIv)~;2oWj0q) z0uX`iMuO!}$*fBaIGL>pX*Yuu6y5wo&z+^a)c#vJ@u9D30_hNI8^4gQjW8&2+|&7A#Qsa`>`0(-X1W6S(28aEVQcrZ0wuNy^7s`b+2 z$8*fD`nXZWJHh?eQBBG*Bea{e?s~M;j9B^Ho^4R#w~R{ia?PI7cK3bvrS+ZBsH*MM z%d7N?5jb~uKFM1-aV^F(K65M3Vivwhnf_^z-y#CAk5Dnd~P&7RTK-=BBB|k$uB+R81(H?;*$%xI&_uLN= z0`Gf?MSCfN7HSHGy>RrpOR_Ve=1e}Xl>s26DiX77xu*c{-6}ph>1@q4Q=h#KD(uYQ zIDZWm0hVE}X2sDbaY1~qM7rZb=JAV2Ul`N{vuWaEUa`)!Ul?L=`kMVZyFGH&%1L5i z;G2NcBF~kO(Ysm>tsfX~J`s6ye!MP*g|hNuj7<-#&ShiqesgN8awE}hldH;z=jsMA zrXd~WGE7!46KiI=wx|8I*(TcI>@Nqm!6L&VrKnZHXT*wIK|+q*ozB=+os4gSX639~ z`)&vi?` zQ%_r1$+1Hft+=DIR-a~mYPEl4KR{^;o9jElPUotErl%C@Uoi;d(75j3Bg;Xo6#Ebi z=%lTwS8H+Rz3xgtif8Wg&>SegjEAF8_f&DI%BEMB22mBnfG zCdv$AV5GQ>A-^8Pdk`ffqtl#RevWD1{A^5IA+OVmyp(vCM2?cJVWnG&4;_@L+%+LC z9FJUAx1Z9u3#@a6bD*;AIgGj;wn8+Uyy{JYv?C_u+XRC>&|CXp1%fJa^5U!Tx zAX6ir6A3!Te(rj1;Sg-rVP1Hi!wb0SBv-|PuJW)~TZUt-DMPlAOQ=TY2&+f%Gbs_k zgSyVi_!DPb^KP4|H{*!8)R4$t9q1^I<5{;~AJ>X%#!pT4w76Qy@%XBl+8L>j58`bO zm0l_k>z+oe?KWSDYb`7r_o!#(cGoV|K6K;7LlL9MW96`3mADs7q%%1MXh`_dVMKbZx=$GVqB zaOFNh{Q@_|H{6D$^(FEHc~fk-{~K0iX@tDnHq1h)ni0#pw0qnmT1FgkQ~>`ijEU`j z3I6H1HU0~@w?_&|h}FrMQyF~sGX~_C$yM5-qST|$S)6}nS8)G(dBW$pgmavZz1#Vm zN{^+Pdw5vpP5b!HP#D`@A)xzq7_uff$FnkZ=fT|yhm58CQ;Xg5 zhf##AxyAGZd}L^8d5caOJ{`1|voby^RU9pJ6p)|U6A%k>uEbik1!X6LrUR)PODLy_m6$c?<%U1HTqBYfwuTab;#wvtGZ3 z`Z;-XTbt|&*OGwwXD;$OqsGaM)73iRw=((`)$j6r@-GewAnLD(TgM@fe%D1Mr|2fb z`$?x*M=aCj!iBp(!nv};^XhIsF*OMxK+!ie_n$P}moPHor^YwFF6Tt^!-oX85w(M4H#R~c%bnYqvAvfR1W5l>huz}t3Zx{;y#@qV$toq+$ z7JvOSGMDn>;9y*jt*;_xpP!tiU|`@y;vkS;RRX;`U((xoF+0)v7dC}4>BX!;OU_@NR&2em5>yAKl$;Yz3w}sfUKOHcHo|HA*`!%1_^f! z1NRxc1Bjr^<-hNYji3>E`=!|97;u=Tn{#cOFc)9+1Otv~b2xRC3Y`7h0C^y$m-q{j z!gKR=xV}>xTW^j!gD}}NlAK1ef_X)?7lC-y`^nGGsyjUZBSvQF-qZGn$wd4e3{Ki< zew`^|qf&sA(FNWq5v`~Oq7ql`j@pz>RR0FgW(*kS+aPx^P=Od4Yy(Nez=NpQ7`|R@ zq(kOLE9G5Lc54p2jD5fA@foyDP~{IsUb)(70kx^1+mT?eVXV!lKVbPa9yU&T}#QT9+#l%WQIGPR(q&l<&Y#eGSt?N$UHp~|0 z%aBD2p`-47bX(L(%+RlN(z72eRkE2b;Qoj%S_N&q-^5c3h-N#T;3v#kZpK31r)nU* z{2?SJU5Qp9G7=5AUnOuzeXl+I87J5&D*wSmi$Fre-3*_Ew!7Oj`LgXCST%cB`CO8A zqim57BG>|YZIb)YFZzB>`JHeB7b68T^5biAo-qu-A%{8vOsWqS!JPadA<+u}12nJspE z1TMtp*;|!==nY2Qe3dPCeiD?aNU5(5z#qOmUV53z8?}S8zSmDvh%?1L1+LmFD-`LrG1oTu)KAkd zJ5o`YWi?#0ZWTL)xYS1H)aWBD16_!4r-=IMe2b#j4l;Lo?1}iXTLIe348o8mPKjw7 zMdiVdsB`(%@wzNJNyN5sf{Me7eeUg2XL7=+2Rj}Fp&BhDJGkFhBRN1S5@cUlwnVj z^m1$aNjIhV6r&VdF`J(M>-(9JO6Sm_qZGuH9P$h2=}_qRzd^i%6R4bBcMAEp6fB4Tt}rdJ;t3{ zcaQ$syd@EBLp5bnJ()Jv@2-q8Y-wmgwxj){PQQG~2<*U=ILRyF_=|||4VKoe^9Jr2gV8|(`=09KPp7kS z`uRHC9KKe#X{|HjF>m6@-@;2rVuvw6mI5_*bgW(#ON8=Dg=U?@^P?wZ<5$^9IgLnZ zE_1aLFG6CthgaA$Vt?k9$QhNWgfwH*z~CV-w_~n?7x}T5BQn`mhY3eM+EhN!|D^xH zBQR2fahAoy}bF~LlMa>4b2rt`}>q9>rTE+5JyI>4}ty6E~U)$gEv?pSv(9Fv5; z*Q#41VNDjA;J;&wJ!c^KQ|@m`S?W2P~yw#jN>2_5Q3|jT?N;NZ%-TTGkzN$=>~9 zZR5?Rd^Pv8wRR=7k&kGkI;qo)Adsc)B0}acG08qX{XTFA@2or8k;8X?27mS4w+cQA zwdwJ%zEGT&>IuSEPbT#f2#t1)Cxm+hK}CDP7Gb7~`%@V>{u?*0RB)`0SN7?#;1Sk} z>`P+LzJqG`Fg^!G9JIPnb3eb1zT6QT2Tr|W@XM`#51J2oD%WPKDomj_eTYT6varE= z;A#`^y>slSTkR56Dj|K1$2x)MY$QV*>mB^lhr=y>NZxFt5o=O{YMdaW+JF7!&3yW+ z*UWr`>YV99DCq;mn&G=F;Qq<*me7lOnq1uDY6VHo6l&d-Yubtv=hWLRf*r5Gz0g1u z75DTTv6tr$s#*Ik3Jz)DE#68nCKlYrFxTwr_H$; zmyH$e=ibOR&SDYZrSCnNd?Agw{D2cu=#{?}S48OiyBku(oP|dCOwGb0sdM!!OO6ia zUk+lzaC>`uO}9Sbo3+JIZ0-aolsL&#AN+2ivKq`W~Vu%mG z*Tj#$CX1+((1~Y>+zTFDnZ6QIeBPa--X&$a-Uq4{D3XfOXxM$xKWp|3fRGW6;rE_` z6ZsDDa}RU1I#P7n4=8jBOnlV##m^apl3gft1tW;K8~)qd1xtO)LH&IQSG+9W$eY~w z>Q$qamqm0E_fKU8D2bcv)YB|TOn--Wt_A0^F3A681Y5WMW!J!=z8Rr4=1#V(jxXTk-}fT3?y#HB%I%NqpqAR z`P5+~=JEY&$%I)_>$Xht!R>svpYjWIxHMf2gZpxEuYG;kB+81Ej50cq`bNDd zpIvj3KQ@l}&{$&=j<-EH@ZX47rQrBp5@o=NALiH0f`S7hM++03GPaw9lheyO1lO1) zLLDR6^n%|{*c%i>S+>ak7p97apje?u-5PmRQy!vuBud(Z&E%fFzT zz~R1M7OU9u+sO4*UQ6xl)G@_*no9$h?sTsb2%e%$5P#?OA**UPPdo2+LZ_yve>5`@ zGto7JfNq-b-;h43iOj}(LKxc67|7^gj1_WDklmPS6|zEVf)e}pKR?keVEs@(AKrOC z!}Fauum8i45xs?-8T=cMMV@>l(moy)&bqyGakQ^_|EvTS0HzDxwnq=-8cMH(Q#U+K zinZIjxP`3}xd2Z8kaNzbs|8iG>sOT3XEinI>h6cU{@}o3uJ%pBszZ+QbuBZ}LGU>? zSdE8}X;sKtP@25=n8|=*B>EKUs}*es8HJva02PwAC;RqDP6T1j2G8OCy$LXZjOFkr zzfVUXk4W9*Ii*4`t2G9EK3(qMXa^2MB1~Gd$ea9?_6!-jH2d6pUdFh(y&L(j+JXbZ zsat0(1T3f=k5iqFjg|QXu1!Bz0Mc0WC8p~Vj#2SKif4nh1r=#byS!~VMC=wOdk5Tc z)Q>VvLuIC}a10ko@ zU|GKO0UP%VBiE42KGYjGX3zU#}Jqq z{Yh$gu^;e_8pNvkkUKNwkJkyg?*MPeGKQ zteOtr#1U~hTr8om5NHg~IUk<${Ka43M8^43l@HOSK)YBFlq35dJX#>_{YK-kAyH1a z!Ic;z)ZKOg#nl+sblCwo72I7MMx9p3*hf)9E4g23gtW*`U zA0d}rhV(Y|Wbv|xa32q#Ra3d4kZj+XX$eb4kFU~p}XOJ5Vgp?rW z2F}<)YjR-6M>I7ze|dD?z_M(P0lKmp#IzD~T?0idu*ZG3JRTxT@>(}@3Pdd)V|dv%}Yo~ICwh-z&x!0 z6PSCQY!?gs9WA?0$8I(^Zbx+_=ahTySQj|*hz>#2uMPNcuWX}t0M1QOg)13?fIH!D z#Xvl;6#}4aEl~_Zmm7hEX9{(#fYY3!2hhL=rX#2Yn@2sxk@T83bjJe!ZGpwLh*<=c z_hG^<8Hwb}r%b-{vTk;^>3Q`?$g*1o2uDTD#PcQgQ&O-yC+tt%oeWGVPKr|5k8`m% zpy_*sal2YU-VShuvhpY1&_wD<1GF3w5$^4N&nSSPmrXDipo;$y^D+WHsvdx=bfcc# zt9rOrxC4#Qg{S9v2fst?z#3sVyFhCWiz(Egu*z>H`VJWQfy+1zo>&Hn8}WS4n;7_R z!xo7_J@y~RPWLo;LB%lq4n4DPN-&$BXFa~G0>S?}3^?G-Fl`7PrSMG^tFNr*$%gbe~99=)0pitvaf z!bC|C?w7mVf5#Im-VLcv4hsvr{q$k95KWgP(5oVD19W&i%rYosett!a;r)$wMI0mZ z$@aA|Aq7_yE3J22j^me$9xsy$^R@F5t+KQyaK%s7c-g>pF6jWn8rf-qcCmOb`}PiWU9DV&qlKEUGktNV0H%1V8)u}%WW$)=k4Xv_R9 ze^6qGwgn(Y87+e@gShln`ve4yb|@EUa@6QRi+~qMQwn#XrTI}T+l{vdc| zOVpeK*K8Hh^ngn8W!0Uw=;Fq-(&0icH_%^Nfg6_3{ai+I``c6A&dn-hg!GGhyR#ly zjRTtGlH??eTwgf%(x8(OHm%UWxg~&9=-f@|`s{ADJIZxfWk*4Kfrpn%3owSL$8N$OqX(?2Jae;J-giyK}1w1;3R=bFG8`rH>$@bzQ!z_C4!uxY3z~C z;2eG9mRvtonbge!;K;QqrOtp2xg^J#@xAYLzkRAwRxaM;h=`szd5~Z&ysWf$Dl@+Z z2=j8Ft-(v!ga;--Z~&7jk2JJp1GWz7#;B3=rrj-7bk(&ki@h(dF&M<2QotHZe{v7D zTd7*F5ObQdJUbgK?sx>#B2y*bBY-O`+GN-f2SLYq8J=j2K0#bZY|8P`(6Yb5%4O15c%=8Quq* zTJOzO58zuW<$>)6Wo(xwOS`apBpRjQu~Hd=(c~kn`z?-+2Vp{}(d+cpr^N2cUrg`# zad$7Xk8u2tl;p;VwuRAor3;2-g&0Yw-JsG4y4nszKrY~IU1Y#nTS;;5EH1CAujpSc z`jl2+T8B6|5KJu?2?n-2fj*tjofAX`-zsNX8fcpZrl6VvG(UazK5UbEUv8QW$BO`@ z6jHB+67uMX;5zX{zd3*t0fNv$7Rd4LB)B zwlE}QQEq5uSli}*TeJ>S9c8&jQrIaV`_GSk_esVPlX_S6b8S-23ytV z5urp<8IY>j^5D<>0t?W|IHK3#Zs}hfmkI(wgQXE9%z2(p3at(mn1@MFuS}qN*%_nB~JabaCejD=7 z#8}ztEwe3^wB&yjma$e5rQZ4r&WmZ{#V10iPmWMqq%c9;voEWf&uMZ!htX%u_QM;; ztIX42@zyP{E8>upyw@B_mp3LEmhI` z67!PIvcmQ0eGbnC%eMIU@u7ugZaK~(`t6-iX`mBdAdq|^ZbK0JSFOm0wnxq3)F%cC znHr?|{<2z}tobN`Y#C_?oo=SF-@Xv9w6oM&M`!MG{=@Yjg}`q5(>oZi`@l;ceBtMC z^PyHW{Xbw^lFaTVBafB_Vge@oM)eJf@aaPRQWwWi49Np zx_hU?ph5iH9!xTH3PysK24>X%PB6ywzj_I@=bAQT+ucj@7XoHaF6w$U!pm(4Px6ck zV@g9YX~2j4n{^pCTBV2!_&QpD9$naikLD<~i#qA}jB|_gShU^*Ucn(~Xx;s91mjX~ z|D}OS{F{d4aw-3)GohYB`amkw-z&{O7-Pt_l_kKbN;x+Gv~E^YnMsW-noGCd#t*>i z3sa+y(bEkQH&udQX$e|LLevlt_{gQ(#u$LozIpnQto#qJxELu8+{0gi4MQIIo~jw1 ztMx`idd~&SkUa^kLE2Bd~8Gwm?Lv9?*MloKxo6oTe3un$hTL1*EqbjY%j3%Ts)IM{e7&Pj-&^cO1cV>-GhDf6Vja9=nz?FVp!^d1{xyi?{Q0 z+gnEnjPF2;0`=$_{AZTcdx*$1A7SG!62g~IKP5c9gTNre(Br1WWLv<*{h&Qo@P`yR zU3d2peOmUO!sAhQ8>nPh?^J!rD5M~EwGG}* zuZWn(Os9@~md2?;sgu<<&7s3T)<4||`LISU@6xc=37iO^c$fJzPTsogEJ+s znUPmP3rzwWN969YVMH1LIAb_a?wH0$LU09x4ZnwP1b1l+eYerey>ZNAY;m|a(~~JT zmEgyy{B!uS+W?zYM)}C1|J_gA@MM06T{AhweX_yla?HAH;Szg zeNo?H|A0BRD3y$&5+1t$*xNG^KEDA?4`GNl*`td>m9&IyBz%_cE?^-dN>Wt(Q(Wc~ zjQx2w$G}twc~t*{IQ#D&)c+&${%_-2f-^yG$bj|21FFF-X3$(%hluoG@VfoO2Wm4N z?u@Un1t4!o5J)C@*N_S4Xt~RxRvz2Qx=>^q%*H4d=bp&I1TOh>K>*ZC%bvN;|C{b^ z63Y8sFw5BZ4C-1~)mZj07Z5im`+w*IOT52h>TM|kLBiplLj^Bb+lK5n$ zU;byeIA~LD_|eL+#{#k}FE;S1wX4b#?i7%>j!x4w+qb(J`rk8YMhiS!UTIhY_-5JltEmGaKTJIHwUp z%8Sdk)~nDQ!tIG#g?k|p82C#Olmf%BXfGC$U3ctr(-35}{6!iO101_LWWiw~)ci|M zeAC|3ggYxEH|ZhRYkS3E+W!w}gnPEh-E(gfu7sF*(tG^5;p5@|_8_@QY{e~f**~YieRpDL!Fis6fCw@W5 z+u+Ysy#w5+r7DZzp6OKuTM2=1-GheYp?P97zq=d(>|Szu1!AHU@pagfkp;0;>kbWs z)@Uo3v{hdmo?}XyEgoQ^0M8qn=Sh3*Vf;7*sW7F!mB4-X^}Hqk~Ix<{Bdjqv+{Xe~hrTB7o1!=*Dnn5V2k3 zJ0N{>W>xBb764@a*b}D(o%-DW+nH*H-A@P!136*!oKfNDh;W;`$O20R9j0X@QQ`ZD zsnu95+)ON>o0UB(92h?AYAKv|41LPVsU0Q>K7KpqdyZ#frDlY!47Xf1oI_4Pd(tal z2FpfY6^!$HYkj<+3yfAwZw0ESI^47!dfYnG&x}$CL(YVpio2#bJ-zjDHu8!oe47H6 z-HfT+@X5x=Y0&H01zN4Fb1Fp9a|2g40gfiUyNc;X%mm@o)i*y5L9q}cld*}|Poh(_ zEG3ZYlokEoiwA6K^XOy&e*PZo4HEjpy7vJH*azwc!iSdKPFQKG&dQ0;UgCPuKl(0S zg7d#!4OAWWukCiK8$)YjS0!<;{>b~jQ0&%{K-SM`jAM$vXv`tM%3xdriNt$~v&)KF z$}eD7a2&O;vXgZcSBl8Z2;CZ@y6!yMGepTZ>07F?-@JjVG&?LJ zhFV%%=9Nj-R^TuHQ|;aHCL{_Lv9b41Tmxox`fOqYHQ^Yut!CoQ=HQvCDP#$l>r#IY za@+v4S>EoNX;dhGfErrBo3SkJ)C|4p9DXi%)D7;T)=wk*u`mW{7%MkhzFeasy|OQ( zPT~aeOt+}!tRy1d6q(RUdTIleJ&a5I0ZKjUb0U5a)h*G>k;c+e1~^tPAV0C>rp|cI z6U;OgVmU~U{)9X3*O_@yWJ8f}#sq41l{lQ6>4IRdRYrN<8Bw2vA1_wQba!|BE?H{n z8|XMaxxiy$KCrRT@;y6-R8iR}R^R*9`CI;saPWd~;CuYbN=-f(lQH%ExjtIt8x#^t z0wr}O6KYVr^-nVjKEB67+}?Ty9+D~pXpkk+p#4X2~V#Rb!Xpo6>kQ8FdOQu z&BdITU)~uv9LseWO75`%{(N#-``EbkZ{v z=lr)(y}|W2o9A7SZe9wyc?&DKsNAn5pHA+|V$VL}n{B9EYY#X+bP*f5^;!+X^zmeb zYruLi?kA3dt{0Tyk3e96^+$8i9p3ID0#rLY!m+o>I}9OCpgw0V1^)nN7sGb2sW#L3s)m&Tkmg=bfXb zARcQB#d^Q;C4t+fAeBVBIHvIQ{gnNqbP^+Vhj8bnvc|@sKSwcqG|?YqUmsJjDJ#M= zti&4?;G5ufbUbyM0$ud^r7x%8>+pn)sGWFu9($L?2KBj?&s%Klm(@H;J$iP&MwabD zHFO#V3K|)5cyw19iT9w2?Y+-wSX+&ub-$RKYWH(;yB@m-PyR6}b_%;b>iK#184?CX%IF)ug@ZvN+A5oh$85?%2;Ds7PHnypSJxd=Yfiw@F4c_ zr?a?iZ#c3y@aVFXBRn_PBDpueQA(N((%7*~{6{wauk}eN>NuFR>VCh^Sd6{av5-v7 zSGWZykHsb9pOEclL{$GwoG!dxfwXC{OhoFhoH3!+GwHV8x(@V*@6huPJ$GjBH}`MB zUn3X_-gCi@k`S_=)bA9X4JV3tzY_RwR0OEh>SC-8mp0Dc5#Hd4wp1ocw^+7^ZK}5U0L1D z&!9NChlAqql5Lk-!u_4+Xh_P@)Fux4QpbaEZq3_2F~44GzcsjX@wW7h!kVq(@R2A^ zxN$qE_X)#|27GfaDqwTQYzD|L@W-=8}9HFkt3kUX&;Zs>@2O{DGITc`L7$9V18JC zCh*i5D!iFr8ha-?1Zis5-hkeDx8RTfbGn;)CJlA?hr-i(muMr%`JtYMGwhw@*wDB7;Ylc4`mG@vfIl3N_< zHoYu~UE}r-&A<-P41TG|5no^e^YA`2^^FlvF81K%QB1(rM`}@r^bm|iM^Xm$!Rr1; zRL%+MZli^`*X{$c!I_z+vV@emlaK zw)Dq4dV-P4-IXWLD3Eq)4W%8ntLB?`^-ivaY)hxnJH7-{2KCe17>N_zSUa?pEK^xrAU3&@QUIdnfph#|5%SYPvw4=;JWdqEbC-N zs(;LN^w*)4W(PJzIf!*mYL5vfYL?Ht`@ybx>j6AFapfrLf=`%g}as>QF z%=CXr1+VJ<__w3S|9{a8{ys4d>@0r?TWalV4_+g34M1IQ6}^SNv^Vb#uT9hu%dm4L zG9dm9=U*8rpd9AW7jy!5yVE>=P#-{H^F08cJ{pjRa-ikY3v=Sh`lg;CqK=>jiI4|= zOx$gS6PfeE)Ik|q^=!o$=D~C1LtcOU+2ELsg?&)V<#+9CZh3}Lh* zn{a#k`gVl>__$w+I?5UN9lPq5KX^VZ0ek4UVEtmZZQ8#0d4F5`PsioR;@G9H1F#Q^ z-e+6$&7C5HW{-WGkd8k2t%t;LImLtFQ5NjMA_y?m6vhiq;QkIDlCMDi`yVcF+M*cn zpFf0`-U%{sfiW5})l!2$bh1tsa>rR97?t>)_zK&BRCm)PM1wK>c`BkVNalky&<>kF z&C8zffG5Sm36$!#SJ$3;PcHbRo=F06w&R8H4TVVB3t%oSN$X1DH*raxm~AMzfa-F! z7roaAhU7U&Ovg(3{K_qU#Q$Cp#(M`awb(hT{r$@ZBM2KEPC=;+a;J?Y=_E-teekak zQU*KQvxqD`2+{UzE`w^FM6cbIH)W~N(wVhdHez8Ccnu3(=Q~rgEj6cdme=&bX?>*t zQVp_;Q=dNZ*u#eRCO-L>fO|K!ZShR56Lt}mK1 z-ZbWciQ-~sSFlkhi@aJP#Kv~5rsq$q2n7SKGK|vT{we`14c)Rp+BML6N>MPl7Pkx8 z$O8teBCM5AqZ!-${D)R!x1E+Du6~sIlzKT(HfUqG%qB6?l^UkRIXlR9H`L^4$@ggsc+J#}xq&Fn73iEFo@wWEhL6JT`gBAOTq2E6@|R znyRhg!T%ypDw&m01tN^1xXVI1bkF-&5(9AXzkrwi&6+EaX4*iL$(!{?bwoC0#nt*8 zekmI=SRPKe=Rk}|EeMg{0QMQ!zW1_0R&g58G^F$Ss!Q&~mw}aBF&$U3y@z4_G6HTM zsqy+i1V~3a;0f5=m<#B-4_&&osj(uzE|||1f0C7k{vcJs4d9nw;K`v^6YYjA20Lo} zj@fV~(Q>c^N9(h9{aFsrD&6Xg47C5-)=Wg7KlT1<48AiA%75vzFtIv?!FmSJ9~M|N z*)#qa)uWrJ!(M)b)zk0IV-E007n6zjf~iKvG(WB2&$$7jr- zFw%OhLY?<0x&en+4>nO*F67+rSt?3%IzH=ooN*axO5>_nTp814x3CtAkIV)*@Njxx z5;I&TdPwpxsO9`5gIW8tXDp#nIyS*`mrwbUhmrov;=$Ja;1vxRbeBI|GZ?rePx866 zRLBaHryqtw=LCxaPRZ3@qefikx)lz_kwlcldNX*a)#4WVKHf@^KWoT5w=L;R@^s(7 zmJqhqPFOSkto&@wUllJPdOY|CmwO4C?+(9$?Mj8?i|~fp39RSu^aU*y3B11w54FMo zprE(|23UD%LxA)yklZ|nW_)bUtj>%gAf*#$l@B56F>MgCoWUa+O}~y`S=;@ysPy=Z zwEb^ykG<4~r6xGUQY!Qwz2Cnw;aenjrWSwH&NH~TyE0kO9y}+t&yH+wwB)Lk4{yK2 zm3Y^#^4bq?f$O8Cwwbn1Tyc{2zcmpBo!c(;*$x5Vu-w2wLq6pkXDN+fuBd!9MS3kH zIb5mh+>v3tUG0JS*A2@=C)s9i%b*N8jKw-uYTaiTquxxM|C*c=hgy+IUWvI*ubKJu z7vxq4&uQXeZU5?t3&qNzYqE&JV?Z5(Wjz*5I*p@pr=R@G8bo!lWhg}XDuB6!xu=J} zH><63Gu(#mK%kfoZyT2BVJ=(GExCN{usm6BjLNclZ?4rcz+d%eBiA!nongyctMeko ztI+%R!FlRczHpnN-|X{3c3f+9p0{^(HPD`P8=j!5TSTV3Gj+E!D2P97BhCJf<*XI4^G?5` zU28vS;|G|(-%3EatE&k3^9MZ)?b!R_I*i|pd10sVq51F=43nxN=A_rVe=<0HDoc3Q ztcq!0x|LUU(@arCCH{87-8P03=Z9C92Jn1r@B0@`^#snq^nvWd`esjkZO{y2B{ zf0vvFhjniFof885R0J+ zS-BD}*xBuRxXdVxV`5!LeCY$8tkQH{`p#aXwKkngd7Lu14v^H&9*m--;&hFU`EN$d% zYip|tKRFJO9$YT*U}!vJ(xQC!&h>(%_N1SqWj8~J=wGb{)J`t$vzGqnN=KHrNOr_h zYmZbq>F4kIk9B?GNer7m?%IEcPedEaP5a+u?ZG6}PZ0NmxC|*y;3!%U*jRh4WY4VS zLGS5zcPnqc;cfiV;7o=(2b)z#E>hDB)Ma!hot60MfGbC?+wOCGm={~GcPDgdc*CT` zZB@_1dbA8Tlo68Sxw|iIH`1OjzVOt<7|sX>Cl^dcPEoJ{YrlB zO%3cncQZ=Rw0r0}E%p4$^&ikNG`E)G|MJY4eIKl+WIKpmy*Io6*Lwus{DI)9A z?AH}%cCXoTSO%d^bs)NlB(=MAl9f5VlVIK5MwQl;))sw-dOY!)bHy1;UtJd*p4nZO#eZ{1_o4l942w{|?Wp}yukMS#?I0Uo zpAqo=hC8&EUiQ;uGywKr&TV$`F~RyQWxy_e4&RkATyybG=)P$FAe3z$w!6Jv95#Jh zYB?!)C7+-zlbd_uo(sbrTaJZjmgX*_ZUkj=LGx8`>4OoiXBjhP)a$>=4uT!udCBjt z)4wZfl({d%um&k1D`FE*O8gyf(x4hT6#31A7%OZP5v8QV)+w}lkem?FAZV-E>S@VC z#tp4-f#m<>Auxb>F6aURwDjc!XNXt34+)Ueug~f;b6Pd z(tT76CZUlk*F40I20h;h{&Ts)2UAie-$MD#sr%dsFUTYXa=Ujl_U)R@lRO|-Qc;eF z%4yEkl=63RVCN9GiFB%Ck9v3mqNy>#1~r;SCecSeQ9 zpC(n(Dzyf5lFN-SUZSgv?GA{nhen3p_+;@t%dejH~yxC?Bpc;-`TgU_)z3F zr0cAP^&Mi?h(LqRR*vvV*A#YJ(K$=>NdFY;aZE8bGD9cs)@!U4b@RozeM1=xL;sNN z_sO?+`)Dg$=K=qnFjsDoXTCm%i}qv2_{mHVL@m3!_j-QbAEJ&b=t$6amIW!?$U~lETv- z`msJ_lgOssviByNl^&b$q|LiLxifUnzRdLd(-Yr}sS${>ELXKrCenze-jvlu7jcVp zh2f&KH5eZ~8VOHJQetWiC15PTb0yDxC6k6HVDQ*&{~OfTm-re{p-oa3SnrsNoy)o} zye@REc5=ws(C}^lWOz5ss=o)3N=5UVH0N3j!CVQ!=i7}z4O|WFc~#d;W9Y!yhvGbK zQu~nyr|qX-pHcViZ`IU#bN^bN@TEgi+UT6?(giaVlln?o{tMLN-_qO#E%%9Mq|n8v zuOz6m#@&paR%i%U=(~-Wl|YP77#C#-31s3?Q#I>eH}4wKcST-yA7PsdEO}f+Ru|;4 zQFi$d6R1iZ%*A1zq=>t|9k}Q@u}bYd(6d;z7k5}rajJS6KmKyoc zzI+_G5pXN?m!O>EZhaH9tqP64PzY2^4il$|cpQq$1uSsO%%c=2(z;-X;F8QyJBdF$ zWMBFH9PvF&(P=@Um}2U0snIMl733Lm(+5(hU>$Ph71;98{G51w*CADdSAmma&DLOT z+kn-9PwmV-$&SKJ6cI*T^=qg7YsnjVJv-bFsd+A$?ruSBadc|v3rr?xcTwCT^68a3 zy5E0@eLweTW7KKuBVi5}rNnwi0tfPLI9!?!w-+<_^si2>$V*O!-_fBK8XrHSS3Ejx zDzUP>P~Z3-o3FN3`;FvO%Q`?1mJT}7B(KOHV2sSkntx$QNC)etc7~ZUYzwp}@~-V1 zQ2NuHCZZRoNwu$TJAG%i*`G$0eDz(&$%9(oCg+wvIKNZaD;_Q7e2!S+045TJIHrx>4*LdbGLB zJ9@JQDihiWW~P|n9N9C%62y9G7N_g`cLDahRO&9bi9uiNkoi2za&kE9C$Jo+s|UQ# z2bugVtP*YKNh6|)WHl`Odls-*=ujuZ? z#niKMW@A;)^ujYe6V@D9uyC>XsRft4AS)-Jr@}L$ESv~PxwOP{dD*)=nQMWom=zat lf_La5j)n(c6v*uIPd?B*+0pcF#B>HA@O1TaS?83{1OS2j)>;4n literal 0 HcmV?d00001 diff --git a/doc/Components/index.md b/doc/Components/index.md index beff4872..32007440 100644 --- a/doc/Components/index.md +++ b/doc/Components/index.md @@ -24,6 +24,8 @@ These core components are included in Mirror: The Network Match Checker component controls visibility of networked objects based on match id. - [Network Proximity Checker](NetworkProximityChecker.md) The Network Proximity Checker component controls the visibility of game objects for network clients, based on proximity to players. +- [Network Rigidbody](NetworkRigidbody.md) + The Network Rigidbody synchronizes velocity and other properties of a rigidbody across the network. - [Network Room Manager](NetworkRoomManager.md) The Network Room Manager is an extension component of Network Manager that provides a basic functional room. - [Network Room Player](NetworkRoomPlayer.md) From 61d44b2d80c9616f784e855131ba6d1ee8a30136 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sun, 28 Jun 2020 23:49:36 +0100 Subject: [PATCH 37/57] fix: Fallback and Multiplex now disable their transports when they are disabled (#2048) * test to check if fallbacks disables other transport * using ondisable to disable other transport * fixing teardown * adding test for Multiplex * using ondisable to disable other transport * fixing NSubstitute for 2019 --- .../Runtime/Transport/FallbackTransport.cs | 10 ++ .../Runtime/Transport/MultiplexTransport.cs | 16 +++ .../Runtime/FallbackTransportEnableTest.cs | 105 ++++++++++++++++++ .../FallbackTransportEnableTest.cs.meta | 11 ++ .../Tests/Runtime/Mirror.Tests.Runtime.asmdef | 8 +- 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs create mode 100644 Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs.meta diff --git a/Assets/Mirror/Runtime/Transport/FallbackTransport.cs b/Assets/Mirror/Runtime/Transport/FallbackTransport.cs index a5194876..bfdf1aa9 100644 --- a/Assets/Mirror/Runtime/Transport/FallbackTransport.cs +++ b/Assets/Mirror/Runtime/Transport/FallbackTransport.cs @@ -27,6 +27,16 @@ public void Awake() Debug.Log("FallbackTransport available: " + available.GetType()); } + void OnEnable() + { + available.enabled = true; + } + + void OnDisable() + { + available.enabled = false; + } + // The client just uses the first transport available Transport GetAvailableTransport() { diff --git a/Assets/Mirror/Runtime/Transport/MultiplexTransport.cs b/Assets/Mirror/Runtime/Transport/MultiplexTransport.cs index e8a0bdf5..47ccccda 100644 --- a/Assets/Mirror/Runtime/Transport/MultiplexTransport.cs +++ b/Assets/Mirror/Runtime/Transport/MultiplexTransport.cs @@ -26,6 +26,22 @@ public void Awake() InitServer(); } + void OnEnable() + { + foreach (Transport transport in transports) + { + transport.enabled = true; + } + } + + void OnDisable() + { + foreach (Transport transport in transports) + { + transport.enabled = false; + } + } + public override bool Available() { // available if any of the transports is available diff --git a/Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs b/Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs new file mode 100644 index 00000000..633e1129 --- /dev/null +++ b/Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs @@ -0,0 +1,105 @@ +using NSubstitute; +using NUnit.Framework; +using UnityEngine; + +namespace Mirror.Tests.Runtime.TransportEnableTest +{ + public class FallbackTransportEnableTest + { + Transport transport1; + MemoryTransport transport2; + FallbackTransport transport; + + [SetUp] + public void Setup() + { + GameObject gameObject = new GameObject(); + // set inactive so that awake isnt called + gameObject.SetActive(false); + + transport1 = Substitute.For(); + transport2 = gameObject.AddComponent(); + + transport = gameObject.AddComponent(); + transport.transports = new[] { transport1, transport2 }; + + gameObject.SetActive(true); + } + + [TearDown] + public void TearDown() + { + GameObject.DestroyImmediate(transport.gameObject); + } + + [Test] + public void DisableShouldDisableAvailableTransport() + { + // make transport2 the active transport + transport1.Available().Returns(false); + transport.Awake(); + + // starts enabled + Assert.That(transport2.enabled, Is.True); + + // disabling FallbackTransport + transport.enabled = false; + Assert.That(transport2.enabled, Is.False); + + // enabling FallbackTransport + transport.enabled = true; + Assert.That(transport2.enabled, Is.True); + } + } + + + public class MultiplexTransportEnableTest + { + MemoryTransport transport1; + MemoryTransport transport2; + MultiplexTransport transport; + + [SetUp] + public void Setup() + { + GameObject gameObject = new GameObject(); + // set inactive so that awake isnt called + gameObject.SetActive(false); + + transport1 = gameObject.AddComponent(); + transport2 = gameObject.AddComponent(); + + transport = gameObject.AddComponent(); + transport.transports = new[] { transport1, transport2 }; + + gameObject.SetActive(true); + } + + [TearDown] + public void TearDown() + { + GameObject.DestroyImmediate(transport.gameObject); + } + + [Test] + public void DisableShouldDisableAllTransports() + { + transport.Awake(); + + // starts enabled + Assert.That(transport1.enabled, Is.True); + Assert.That(transport2.enabled, Is.True); + + // disabling MultiplexTransport + transport.enabled = false; + Assert.That(transport1.enabled, Is.False); + Assert.That(transport2.enabled, Is.False); + + // enabling MultiplexTransport + transport.enabled = true; + Assert.That(transport1.enabled, Is.True); + Assert.That(transport2.enabled, Is.True); + } + } + +} diff --git a/Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs.meta b/Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs.meta new file mode 100644 index 00000000..efdf81e4 --- /dev/null +++ b/Assets/Mirror/Tests/Runtime/FallbackTransportEnableTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fcb8a073738084f45822dc5e559a792d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Tests/Runtime/Mirror.Tests.Runtime.asmdef b/Assets/Mirror/Tests/Runtime/Mirror.Tests.Runtime.asmdef index ea7326ed..f852e83f 100644 --- a/Assets/Mirror/Tests/Runtime/Mirror.Tests.Runtime.asmdef +++ b/Assets/Mirror/Tests/Runtime/Mirror.Tests.Runtime.asmdef @@ -11,8 +11,12 @@ "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], + "overrideReferences": true, + "precompiledReferences": [ + "NSubstitute.dll", + "Castle.Core.dll", + "System.Threading.Tasks.Extensions.dll" + ], "autoReferenced": true, "defineConstraints": [] } \ No newline at end of file From 4ffff192a69108b993cf963cfdece47b14ffdbf2 Mon Sep 17 00:00:00 2001 From: MaZy Date: Mon, 29 Jun 2020 01:10:17 +0200 Subject: [PATCH 38/57] fix: If socket is undefined it will return false. See #1486 (#2017) --- .../Runtime/Transport/Websocket/Plugins/WebSocket.jslib | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Assets/Mirror/Runtime/Transport/Websocket/Plugins/WebSocket.jslib b/Assets/Mirror/Runtime/Transport/Websocket/Plugins/WebSocket.jslib index ff1e6220..b6a6deeb 100644 --- a/Assets/Mirror/Runtime/Transport/Websocket/Plugins/WebSocket.jslib +++ b/Assets/Mirror/Runtime/Transport/Websocket/Plugins/WebSocket.jslib @@ -88,7 +88,11 @@ var LibraryWebSockets = { SocketState: function (socketInstance) { var socket = webSocketInstances[socketInstance]; - return socket.readyState; + + if(socket) + return socket.readyState; + + return false; }, SocketSend: function (socketInstance, ptr, length) From af230ce9887c91ef2ff52c8ada26541c8add0473 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Mon, 29 Jun 2020 00:52:23 +0100 Subject: [PATCH 39/57] docs: fixing order and table of contents (#2052) * fixing order * adding to table of contents --- doc/Components/index.md | 8 ++++---- doc/Components/toc.yml | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/Components/index.md b/doc/Components/index.md index 32007440..20997c96 100644 --- a/doc/Components/index.md +++ b/doc/Components/index.md @@ -8,20 +8,20 @@ These core components are included in Mirror: Network Authenticators facilitate integration of user accounts and credentials into your application. - [Network Discovery](NetworkDiscovery.md) Network Discovery uses a UDP broadcast on the LAN enabling clients to find the running server and connect to it. -- [Network Ping Display](NetworkPingDisplay.md) - Network Ping Display shows the Ping time for clients using OnGUI - [Network Identity](NetworkIdentity.md) The Network Identity component is at the heart of the Mirror networking high-level API. It controls a game object’s unique identity on the network, and it uses that identity to make the networking system aware of the game object. It offers two different options for configuration and they are mutually exclusive, which means either one of the options or none can be checked. -- [Network Log Settings](NetworkLogSettings.md) - The Network Log Settings component allows you to configure logging levels and load the settings in a build. - [Network Headless Logger](NetworkHeadlessLogger.md) Network Headless Logger adds color to log when running in headless mode +- [Network Log Settings](NetworkLogSettings.md) + The Network Log Settings component allows you to configure logging levels and load the settings in a build. - [Network Manager](NetworkManager.md) The Network Manager is a component for managing the networking aspects of a multiplayer game. - [Network Manager HUD](NetworkManagerHUD.md) The Network Manager HUD is a quick-start tool to help you start building your multiplayer game straight away, without first having to build a user interface for game creation/connection/joining. It allows you to jump straight into your gameplay programming, and means you can build your own version of these controls later in your development schedule. - [Network Match Checker](NetworkMatchChecker.md) The Network Match Checker component controls visibility of networked objects based on match id. +- [Network Ping Display](NetworkPingDisplay.md) + Network Ping Display shows the Ping time for clients using OnGUI - [Network Proximity Checker](NetworkProximityChecker.md) The Network Proximity Checker component controls the visibility of game objects for network clients, based on proximity to players. - [Network Rigidbody](NetworkRigidbody.md) diff --git a/doc/Components/toc.yml b/doc/Components/toc.yml index c115a14d..9b9ee355 100644 --- a/doc/Components/toc.yml +++ b/doc/Components/toc.yml @@ -9,6 +9,8 @@ href: NetworkDiscovery.md - name: Network Identity href: NetworkIdentity.md +- name: Network Headless Logger + href: NetworkHeadlessLogger.md - name: Network Log Settings href: NetworkLogSettings.md - name: Network Manager @@ -17,8 +19,12 @@ href: NetworkManagerHUD.md - name: Network Match Checker href: NetworkMatchChecker.md +- name: Network Ping Display + href: NetworkPingDisplay.md - name: Network Proximity Checker href: NetworkProximityChecker.md +- name: Network Rigidbody + href: NetworkRigidbody.md - name: Network Room Manager href: NetworkRoomManager.md - name: Network Room Player From d0bb9d57b0f96aae780ebc5c45b7563e442e3dd4 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Tue, 30 Jun 2020 08:56:13 +0100 Subject: [PATCH 40/57] sending if syncInterval is greater or equal to 0 (#2053) --- Assets/Mirror/Components/NetworkAnimator.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Assets/Mirror/Components/NetworkAnimator.cs b/Assets/Mirror/Components/NetworkAnimator.cs index 439746b5..23905d80 100644 --- a/Assets/Mirror/Components/NetworkAnimator.cs +++ b/Assets/Mirror/Components/NetworkAnimator.cs @@ -41,7 +41,7 @@ public class NetworkAnimator : NetworkBehaviour // multiple layers int[] animationHash; int[] transitionHash; - float sendTimer; + float nextSendTime; bool SendMessagesAllowed { @@ -144,9 +144,10 @@ bool CheckAnimStateChanged(out int stateHash, out float normalizedTime, int laye void CheckSendRate() { - if (SendMessagesAllowed && syncInterval > 0 && sendTimer < Time.time) + float now = Time.time; + if (SendMessagesAllowed && syncInterval >= 0 && now > nextSendTime) { - sendTimer = Time.time + syncInterval; + nextSendTime = now + syncInterval; using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { From c91308fb0461e54292940ce6fa42bb6cd9800d89 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Tue, 30 Jun 2020 08:58:50 +0100 Subject: [PATCH 41/57] fix: sync events can not have the same name if they are in different classes (#2054) * test for sync event with same name * using full name instead of name * fix test --- .../Processors/PropertySiteProcessor.cs | 7 +- .../Weaver/Processors/SyncEventProcessor.cs | 2 +- .../Tests/Editor/SyncEventSameNameTest.cs | 68 +++++++++++++++++++ .../Editor/SyncEventSameNameTest.cs.meta | 11 +++ 4 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs create mode 100644 Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs.meta diff --git a/Assets/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs index 208d09b4..61098424 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/PropertySiteProcessor.cs @@ -188,8 +188,7 @@ static void ProcessInstructionMethod(MethodDefinition md, Instruction instr, Met // so the earlier instruction that loads the event field is replaced with a Noop. // go backwards until find a ldfld instruction that matches ANY event - bool found = false; - while (iCount > 0 && !found) + while (iCount > 0) { iCount -= 1; Instruction inst = md.Body.Instructions[iCount]; @@ -200,11 +199,11 @@ static void ProcessInstructionMethod(MethodDefinition md, Instruction instr, Met // find replaceEvent with matching name // NOTE: original weaver compared .Name, not just the MethodDefinition, // that's why we use dict. - if (Weaver.WeaveLists.replaceEvents.TryGetValue(opField.Name, out MethodDefinition replacement)) + if (Weaver.WeaveLists.replaceEvents.TryGetValue(opField.FullName, out MethodDefinition replacement)) { instr.Operand = replacement; inst.OpCode = OpCodes.Nop; - found = true; + return; } } } diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs index 1325c17a..92b5f57c 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs @@ -146,7 +146,7 @@ public static void ProcessEvents(TypeDefinition td, List events td.Methods.Add(eventCallFunc); // original weaver compares .Name, not EventDefinition. - Weaver.WeaveLists.replaceEvents[ed.Name] = eventCallFunc; + Weaver.WeaveLists.replaceEvents[ed.FullName] = eventCallFunc; Weaver.DLog(td, " Event: " + ed.Name); break; diff --git a/Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs b/Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs new file mode 100644 index 00000000..b8308fce --- /dev/null +++ b/Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs @@ -0,0 +1,68 @@ +using NUnit.Framework; + + +namespace Mirror.Tests.RemoteAttrributeTest +{ + public delegate void SomeEventDelegate(int someNumber); + + class EventBehaviour1 : NetworkBehaviour + { + [SyncEvent] + public event SomeEventDelegate EventWithName; + + public void CallEvent(int i) + { + EventWithName.Invoke(i); + } + } + + class EventBehaviour2 : NetworkBehaviour + { + [SyncEvent] + public event SomeEventDelegate EventWithName; + + [SyncEvent] + public event SomeEventDelegate EventSecond; + + public void CallEvent(int i) + { + EventWithName.Invoke(i); + } + } + + public class SyncEventSameNameTest : RemoteTestBase + { + [Test] + public void EventsWithSameNameCanBothBeCalled() + { + EventBehaviour1 behaviour1 = CreateHostObject(true); + EventBehaviour2 behaviour2 = CreateHostObject(true); + + const int someInt1 = 20; + const int someInt2 = 21; + + int callCount1 = 0; + int callCount2 = 0; + behaviour1.EventWithName += incomingInt => + { + callCount1++; + Assert.That(incomingInt, Is.EqualTo(someInt1)); + }; + behaviour2.EventWithName += incomingInt => + { + callCount2++; + Assert.That(incomingInt, Is.EqualTo(someInt2)); + }; + + behaviour1.CallEvent(someInt1); + ProcessMessages(); + Assert.That(callCount1, Is.EqualTo(1)); + Assert.That(callCount2, Is.EqualTo(0)); + + behaviour2.CallEvent(someInt2); + ProcessMessages(); + Assert.That(callCount1, Is.EqualTo(1)); + Assert.That(callCount2, Is.EqualTo(1)); + } + } +} diff --git a/Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs.meta b/Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs.meta new file mode 100644 index 00000000..2c7e6c2b --- /dev/null +++ b/Assets/Mirror/Tests/Editor/SyncEventSameNameTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 730736e5ebe5ce149804eb62c0893732 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From b316b35d46868a7e11c7b2005570efeec843efe1 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Tue, 30 Jun 2020 08:59:18 +0100 Subject: [PATCH 42/57] fix: weaver now processes multiple SyncEvent per class (#2055) * weaver test for mutlitple events * tests for multiple sync events in 1 class * removing break so that multiple events will be proccessed It seems like this break was here because unet used foreach CustomAttributes but mirror uses GetCustomAttribute --- .../Weaver/Processors/SyncEventProcessor.cs | 1 - Assets/Mirror/Tests/Editor/SyncEventTest.cs | 103 ++++++++++++++++++ .../Mirror/Tests/Editor/SyncEventTest.cs.meta | 11 ++ .../Tests/Editor/Weaver/.WeaverTests.csproj | 1 + .../Editor/Weaver/WeaverSyncEventTests.cs | 6 + .../MultipleSyncEvent.cs | 16 +++ 6 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 Assets/Mirror/Tests/Editor/SyncEventTest.cs create mode 100644 Assets/Mirror/Tests/Editor/SyncEventTest.cs.meta create mode 100644 Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests~/MultipleSyncEvent.cs diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs index 92b5f57c..2a345f2c 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncEventProcessor.cs @@ -149,7 +149,6 @@ public static void ProcessEvents(TypeDefinition td, List events Weaver.WeaveLists.replaceEvents[ed.FullName] = eventCallFunc; Weaver.DLog(td, " Event: " + ed.Name); - break; } } } diff --git a/Assets/Mirror/Tests/Editor/SyncEventTest.cs b/Assets/Mirror/Tests/Editor/SyncEventTest.cs new file mode 100644 index 00000000..25f08e54 --- /dev/null +++ b/Assets/Mirror/Tests/Editor/SyncEventTest.cs @@ -0,0 +1,103 @@ +using NUnit.Framework; +using UnityEngine; + +namespace Mirror.Tests.RemoteAttrributeTest +{ + public delegate void MySyncEventDelegate(int someNumber); + public delegate void MySyncEventDelegate2(int someNumber, Vector3 somePosition); + + class SyncEventBehaviour : NetworkBehaviour + { + [SyncEvent] + public event MySyncEventDelegate EventOnly; + + public void CallEvent(int i) + { + EventOnly.Invoke(i); + } + } + + class MultipleSyncEventBehaviour : NetworkBehaviour + { + [SyncEvent] + public event MySyncEventDelegate EventFirst; + + [SyncEvent] + public event MySyncEventDelegate2 EventSecond; + + public void CallEvent1(int i) + { + EventFirst?.Invoke(i); + } + + public void CallEvent2(int i, Vector3 v) + { + EventSecond?.Invoke(i, v); + } + } + + public class SyncEventTest : RemoteTestBase + { + [Test] + public void FirstEventIsCalled() + { + SyncEventBehaviour serverBehaviour = CreateHostObject(true); + SyncEventBehaviour clientBehaviour = CreateHostObject(true); + + // set the clientBehaviour has the serverBehaviour's Id + clientBehaviour.netIdentity.netId = serverBehaviour.netId; + NetworkIdentity.spawned[serverBehaviour.netId] = clientBehaviour.netIdentity; + + const int someInt = 20; + + int callCount = 0; + clientBehaviour.EventOnly += incomingInt => + { + callCount++; + Assert.That(incomingInt, Is.EqualTo(someInt)); + }; + serverBehaviour.CallEvent(someInt); + ProcessMessages(); + Assert.That(callCount, Is.EqualTo(1)); + } + + [Test] + public void SecondEventIsCalled() + { + MultipleSyncEventBehaviour serverBehaviour = CreateHostObject(true); + MultipleSyncEventBehaviour clientBehaviour = CreateHostObject(true); + + // set the clientBehaviour has the serverBehaviour's Id + clientBehaviour.netIdentity.netId = serverBehaviour.netId; + NetworkIdentity.spawned[serverBehaviour.netId] = clientBehaviour.netIdentity; + + const int someInt1 = 20; + const int someInt2 = 25; + Vector3 someVector = Vector3.left; + + int callCount1 = 0; + int callCount2 = 0; + clientBehaviour.EventFirst += incomingInt => + { + callCount1++; + Assert.That(incomingInt, Is.EqualTo(someInt1)); + }; + clientBehaviour.EventSecond += (incomingInt, incomingVector) => + { + callCount2++; + Assert.That(incomingInt, Is.EqualTo(someInt2)); + Assert.That(incomingVector, Is.EqualTo(someVector)); + }; + + serverBehaviour.CallEvent1(someInt1); + ProcessMessages(); + Assert.That(callCount1, Is.EqualTo(1)); + Assert.That(callCount2, Is.EqualTo(0)); + + serverBehaviour.CallEvent2(someInt2, someVector); + ProcessMessages(); + Assert.That(callCount1, Is.EqualTo(1)); + Assert.That(callCount2, Is.EqualTo(1)); + } + } +} diff --git a/Assets/Mirror/Tests/Editor/SyncEventTest.cs.meta b/Assets/Mirror/Tests/Editor/SyncEventTest.cs.meta new file mode 100644 index 00000000..110b5951 --- /dev/null +++ b/Assets/Mirror/Tests/Editor/SyncEventTest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4620d11d843e7844889bc7d0a4400523 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj b/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj index e207b889..4f41f31e 100644 --- a/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj +++ b/Assets/Mirror/Tests/Editor/Weaver/.WeaverTests.csproj @@ -178,6 +178,7 @@ + diff --git a/Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests.cs b/Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests.cs index 46e494e1..280e1a3e 100644 --- a/Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests.cs +++ b/Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests.cs @@ -10,6 +10,12 @@ public void SyncEventValid() Assert.That(weaverErrors, Is.Empty); } + [Test] + public void MultipleSyncEvent() + { + Assert.That(weaverErrors, Is.Empty); + } + [Test] public void ErrorWhenSyncEventDoesntStartWithEvent() { diff --git a/Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests~/MultipleSyncEvent.cs b/Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests~/MultipleSyncEvent.cs new file mode 100644 index 00000000..591023c8 --- /dev/null +++ b/Assets/Mirror/Tests/Editor/Weaver/WeaverSyncEventTests~/MultipleSyncEvent.cs @@ -0,0 +1,16 @@ +using Mirror; + +namespace WeaverSyncEventTests.MultipleSyncEvent +{ + class MultipleSyncEvent : NetworkBehaviour + { + public delegate void MySyncEventDelegate(); + public delegate void MySyncEventDelegate2(int someNumber); + + [SyncEvent] + public event MySyncEventDelegate EventDoCoolThingsWithExcitingPeople; + + [SyncEvent] + public event MySyncEventDelegate2 EventDoMoreCoolThingsWithExcitingPeople; + } +} From c278c004f63e8092841c6af8c1369282be85f3bb Mon Sep 17 00:00:00 2001 From: James Frowen Date: Wed, 1 Jul 2020 16:20:24 +0100 Subject: [PATCH 43/57] updating readme for cloud list server (#2058) --- Assets/Mirror/Cloud/README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Assets/Mirror/Cloud/README.md b/Assets/Mirror/Cloud/README.md index 4b08f603..00128ce5 100644 --- a/Assets/Mirror/Cloud/README.md +++ b/Assets/Mirror/Cloud/README.md @@ -1,12 +1,19 @@ # Mirror Cloud Services -Example has api key that can be used for as a demo. +## Mirror List Server -To get a api key to use within your game buy here... +Example has API key that can be used for as a demo. +To get an API key to use within your game you can subscribe on the [Mirror Networking Website](https://mirror-networking.com/list-server/) -## Example +### Key features -An example for this can be found in Mirror/Examples/PongWithListServer/ +- The Cloud Service works via https so is secure and can be used from any platform. +- It runs on Google Cloud so there is no worry about server down time. +- It scales really well. Default quota is 1000 API requests per minute. If you have high demands, contact us and we can increase that limit. + +## List Server Examples + +An example for this can be found in Mirror/Examples/Cloud/ *Note: you can not connect to your own public ip address, you will need at least people to test this* \ No newline at end of file From 57bc80c9cd3588ef454bdd72b3ad3dd98ddbf038 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 16:31:42 +0100 Subject: [PATCH 44/57] adding clientAuthority to commands (#2064) --- .../Experimental/NetworkRigidbody.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs index fabf0bbf..0766d1e5 100644 --- a/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs +++ b/Assets/Mirror/Components/Experimental/NetworkRigidbody.cs @@ -270,6 +270,10 @@ void SendRigidBodySettings() [Command] void CmdSendVelocity(Vector3 velocity) { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + this.velocity = velocity; target.velocity = velocity; } @@ -280,6 +284,10 @@ void CmdSendVelocity(Vector3 velocity) [Command] void CmdSendVelocityAndAngular(Vector3 velocity, Vector3 angularVelocity) { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + if (syncVelocity) { this.velocity = velocity; @@ -294,6 +302,10 @@ void CmdSendVelocityAndAngular(Vector3 velocity, Vector3 angularVelocity) [Command] void CmdSendIsKinematic(bool isKinematic) { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + this.isKinematic = isKinematic; target.isKinematic = isKinematic; } @@ -301,6 +313,10 @@ void CmdSendIsKinematic(bool isKinematic) [Command] void CmdSendUseGravity(bool useGravity) { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + this.useGravity = useGravity; target.useGravity = useGravity; } @@ -308,6 +324,10 @@ void CmdSendUseGravity(bool useGravity) [Command] void CmdSendDrag(float drag) { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + this.drag = drag; target.drag = drag; } @@ -315,6 +335,10 @@ void CmdSendDrag(float drag) [Command] void CmdSendAngularDrag(float angularDrag) { + // Ignore messages from client if not in client authority mode + if (!clientAuthority) + return; + this.angularDrag = angularDrag; target.angularDrag = angularDrag; } From 999c8b1c3230e01c40c4d11ee52b511812465128 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 22:53:30 +0100 Subject: [PATCH 45/57] fixing doc comment --- Assets/Mirror/Runtime/NetworkServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Mirror/Runtime/NetworkServer.cs b/Assets/Mirror/Runtime/NetworkServer.cs index ab576cba..974aa61e 100644 --- a/Assets/Mirror/Runtime/NetworkServer.cs +++ b/Assets/Mirror/Runtime/NetworkServer.cs @@ -292,7 +292,7 @@ static void SendToObservers(NetworkIdentity identity, T msg, int channelId = } /// - /// Send a message to all connected clients, both ready and not-ready. + /// Send a message to all connected clients, both ready and not-ready. /// See NetworkConnection.isReady /// /// Message type From 7bab3b9d7c882e56d6f6f45e06f4b98f88e6e93d Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:02:20 +0100 Subject: [PATCH 46/57] Update Deprecations.md --- doc/General/Deprecations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/General/Deprecations.md b/doc/General/Deprecations.md index 30f1be41..bdf39a59 100644 --- a/doc/General/Deprecations.md +++ b/doc/General/Deprecations.md @@ -49,7 +49,7 @@ Use `SyncList` instead. In classic UNet, QoS Flags were used to determine how packets got to the remote end. For example, if you needed a packet to be prioritized in the queue, you would specify a high priority flag which the Unity LLAPI would then receive and deal with appropriately. Unfortunately, this caused a lot of extra work for the transport layer and some of the QoS flags did not work as intended due to buggy code that relied on too much magic. -In Mirror, QoS flags were replaced with a "Channels" system. While the default transport, [Telepathy](../Transports/Telepathy.md), does not use channels at all because it's TCP-based, other transports, such as [Ignorance](../Transports/Ignorance.md) and [LiteNetLib4Mirror](../Transports/LiteNetLib4Mirror.mb), do support them. +In Mirror, QoS flags were replaced with a "Channels" system. While the default transport, [Telepathy](../Transports/Telepathy.md), does not use channels at all because it's TCP-based, other transports, such as [Ignorance](../Transports/Ignorance.md) and [LiteNetLib4Mirror](../Transports/LiteNetLib4Mirror.md), do support them. The currently defined channels are: - `Channels.DefaultReliable = 0` From de2882cb977cae72045632b6568b5a92bcc7a368 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:08:31 +0100 Subject: [PATCH 47/57] Update ChangeLog.md Discord transport was removed, removing link to old page --- doc/General/ChangeLog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/General/ChangeLog.md b/doc/General/ChangeLog.md index ddae5eb1..7efca8cb 100644 --- a/doc/General/ChangeLog.md +++ b/doc/General/ChangeLog.md @@ -77,7 +77,7 @@ Mirror uses semantic versioning, and the versions shown here are those that were - Added: `NetworkReader.ReadMessage`. - Added: Network Discovery now handles headless server mode. - Added: SyncVar, Cmd's and Rpc's now support Scriptable Objects via CreateInstance on the receiving side. -- Added: [Discord Transport](../Transports/Discord.md). +- Added: Discord Transport *Removed in v16.1.1* - Fixed: `isClient` now returns true on clients in OnDestroy for networked objects. - Fixed: Host Player race condition for Ready message. - Fixed: Network Animator and Network Transform now correctly check for client authority in their respective Command methods. @@ -170,7 +170,7 @@ Mirror uses semantic versioning, and the versions shown here are those that were - Removed: Network Identity: Local Player Authority has been removed as no longer necessary. ## Version 4.0.7 - 2019-Oct-03 -- Added: [Authenticators](Components/Authenticators/index.md) support to authenticate clients in the Connect phase. +- Added: [Authenticators](/Components/Authenticators/index.md) support to authenticate clients in the Connect phase. - Added: Profiler events. These events can be subscribed to by the [Network Profiler](../Guides/Profiler.md) to provide visual information. - Added: Transports now include channel in profiler events. - Added: Transport abstract class now supports sending a message to a list of connection id's. From 076203e967aadcfa8a87934ff0b46701b62f085f Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:09:40 +0100 Subject: [PATCH 48/57] Update NetworkDiscovery.md --- doc/Components/NetworkDiscovery.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Components/NetworkDiscovery.md b/doc/Components/NetworkDiscovery.md index c7821496..2097327f 100644 --- a/doc/Components/NetworkDiscovery.md +++ b/doc/Components/NetworkDiscovery.md @@ -53,7 +53,7 @@ To do this, we've provided a [Template](../General/ScriptTemplates.md), so from This will create a script in your project with 2 empty message classes and a custom NetworkDiscovery class that inherits from NetworkDiscoveryBase and has all the override methods included and documented for you. -The message classes define what is sent between the client and server. As long as you keep your messages simple using the [data types](DataTypes.md) that Mirror can serialize, you won't need to write custom serializers for them. + The message classes define what is sent between the client and server. As long as you keep your messages simple using the [data types](/Guides/DataTypes.md) that Mirror can serialize, you won't need to write custom serializers for them. ```cs public class DiscoveryRequest : MessageBase From c4f071336a70052482e22fe5a43d43e61b9fbea6 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:15:45 +0100 Subject: [PATCH 49/57] Update index.md Updating transport list --- doc/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/index.md b/doc/index.md index ac23591e..0289c289 100644 --- a/doc/index.md +++ b/doc/index.md @@ -17,9 +17,9 @@ uMMORPG was possible with \<6000 lines of code. We needed a networking library t - **TCP** ([Telepathy](Transports/Telepathy.md) and [Apathy](https://mirror-networking.com/apathy/) and [Booster](https://mirror-networking.com/booster/)) - **UDP** ([ENet](Transports/Ignorance.md) and [LiteNetLib](Transports/LiteNetLib4Mirror.md)) - **WebGL** ([Secure Web Sockets](Transports/WebSockets.md)) -- **Steam** ([Steamworks.Net or FacePunch](Transports/Fizzy.md)) +- **Steam** ([Steamworks.Net](Transports/FizzySteamworks.md)) and ([FacePunch](Transports/FizzyFacepunch.md)) - **Multiplexer** ([Multiplexer](Transports/Multiplexer.md)) -- **Fallback** ([Fallback](Fallback.md)) +- **Fallback** ([Fallback](Transports/Fallback.md)) **List Server** From dabea79699cacea8fdd031e61e4c4d57db0faf37 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:17:04 +0100 Subject: [PATCH 50/57] Update index.md --- doc/Components/Authenticators/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Components/Authenticators/index.md b/doc/Components/Authenticators/index.md index f8f4a23b..30bce76d 100644 --- a/doc/Components/Authenticators/index.md +++ b/doc/Components/Authenticators/index.md @@ -22,7 +22,7 @@ By default Mirror uses Telepathy, which is not encrypted, so if you want to do a Authenticators are derived from an `Authenticator` abstract class that allows you to implement any authentication scheme you need. -From the Assets menu, click Create > Mirror > Network Authenticator to make your own custom Authenticator from our [Script Templates](../General/ScriptTemplates.md), and just fill in the messages and validation code to suit your needs. When a client is successfully authenticated, call `base.OnServerAuthenticated.Invoke(conn)` on the server and `base.OnClientAuthenticated.Invoke(conn)` on the client. Mirror is listening for these events to proceed with the connection sequence. Subscribe to OnServerAuthenticated and OnClientAuthenticated events if you wish to perform additional steps after authentication. +From the Assets menu, click Create > Mirror > Network Authenticator to make your own custom Authenticator from our [Script Templates](/General/ScriptTemplates.md), and just fill in the messages and validation code to suit your needs. When a client is successfully authenticated, call `base.OnServerAuthenticated.Invoke(conn)` on the server and `base.OnClientAuthenticated.Invoke(conn)` on the client. Mirror is listening for these events to proceed with the connection sequence. Subscribe to OnServerAuthenticated and OnClientAuthenticated events if you wish to perform additional steps after authentication. ## Message Registration From 3e54a970c3f45ae1f695d1fce8d6ad019ef774da Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:18:24 +0100 Subject: [PATCH 51/57] Update index.md --- doc/Components/Authenticators/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Components/Authenticators/index.md b/doc/Components/Authenticators/index.md index 30bce76d..e54f7abc 100644 --- a/doc/Components/Authenticators/index.md +++ b/doc/Components/Authenticators/index.md @@ -22,7 +22,7 @@ By default Mirror uses Telepathy, which is not encrypted, so if you want to do a Authenticators are derived from an `Authenticator` abstract class that allows you to implement any authentication scheme you need. -From the Assets menu, click Create > Mirror > Network Authenticator to make your own custom Authenticator from our [Script Templates](/General/ScriptTemplates.md), and just fill in the messages and validation code to suit your needs. When a client is successfully authenticated, call `base.OnServerAuthenticated.Invoke(conn)` on the server and `base.OnClientAuthenticated.Invoke(conn)` on the client. Mirror is listening for these events to proceed with the connection sequence. Subscribe to OnServerAuthenticated and OnClientAuthenticated events if you wish to perform additional steps after authentication. +From the Assets menu, click Create > Mirror > Network Authenticator to make your own custom Authenticator from our [Script Templates](../../General/ScriptTemplates.md), and just fill in the messages and validation code to suit your needs. When a client is successfully authenticated, call `base.OnServerAuthenticated.Invoke(conn)` on the server and `base.OnClientAuthenticated.Invoke(conn)` on the client. Mirror is listening for these events to proceed with the connection sequence. Subscribe to OnServerAuthenticated and OnClientAuthenticated events if you wish to perform additional steps after authentication. ## Message Registration From 99d1b6d860af51efdb9b184e593fa40500b5f6d0 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:19:06 +0100 Subject: [PATCH 52/57] Update index.md --- doc/Examples/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Examples/index.md b/doc/Examples/index.md index 73b03a04..9c12bef2 100644 --- a/doc/Examples/index.md +++ b/doc/Examples/index.md @@ -10,6 +10,6 @@ Mirror includes several small examples to help you learn how to use various feat - [Additive Scenes](AdditiveScenes/index.md) The Additive Scenes example demonstrates a server additively loading a sub-scene into a main scene at startup, and having a server-only trigger that generates a message to any client whose player enters the trigger zone to also load the sub-scene, and subsequently unload it when they leave the trigger zone. Only players inside the trigger zone can see the objects in the sub-scene. Network Proximity Checker components are key to making this scenario work. - [Multiple Concurrent Additive Scenes](MultipleAdditiveScenes/index.md) - The Multiple Concurrent Additive Scenes example demonstrates a server additively loading multiple instances of a sub-scene into a main scene at startup, with physics separation, and assigning players to the instances to play matches independently. [NetworkSceneChecker](..Components/NetworkSceneChecker.md) is the key component that makes this example work. + The Multiple Concurrent Additive Scenes example demonstrates a server additively loading multiple instances of a sub-scene into a main scene at startup, with physics separation, and assigning players to the instances to play matches independently. [NetworkSceneChecker](../Components/NetworkSceneChecker.md) is the key component that makes this example work. - [Room System](Room/index.md) The Room System example demonstrates how to set up a "staging" scene where players assemble before starting a match. When all players are ready, the server sends them all a message to change scenes (along with the server itself) to the actual game play scene so they all come in at once. Includes fully playable game with a character controller where players collect server-spawned prizes for score. From ebe4d2c5c85a9b5111b57aa50a855e21f383f94f Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:56:37 +0100 Subject: [PATCH 53/57] Update NetworkDiscovery.md --- doc/Components/NetworkDiscovery.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Components/NetworkDiscovery.md b/doc/Components/NetworkDiscovery.md index 2097327f..13c17a81 100644 --- a/doc/Components/NetworkDiscovery.md +++ b/doc/Components/NetworkDiscovery.md @@ -53,7 +53,7 @@ To do this, we've provided a [Template](../General/ScriptTemplates.md), so from This will create a script in your project with 2 empty message classes and a custom NetworkDiscovery class that inherits from NetworkDiscoveryBase and has all the override methods included and documented for you. - The message classes define what is sent between the client and server. As long as you keep your messages simple using the [data types](/Guides/DataTypes.md) that Mirror can serialize, you won't need to write custom serializers for them. +The message classes define what is sent between the client and server. As long as you keep your messages simple using the [data types](../Guides/DataTypes.md) that Mirror can serialize, you won't need to write custom serializers for them. ```cs public class DiscoveryRequest : MessageBase From 3c100740abb03c0db9cba67a5f473a035381e794 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Fri, 3 Jul 2020 23:59:18 +0100 Subject: [PATCH 54/57] Update ChangeLog.md --- doc/General/ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/General/ChangeLog.md b/doc/General/ChangeLog.md index 7efca8cb..0acfaeb3 100644 --- a/doc/General/ChangeLog.md +++ b/doc/General/ChangeLog.md @@ -170,7 +170,7 @@ Mirror uses semantic versioning, and the versions shown here are those that were - Removed: Network Identity: Local Player Authority has been removed as no longer necessary. ## Version 4.0.7 - 2019-Oct-03 -- Added: [Authenticators](/Components/Authenticators/index.md) support to authenticate clients in the Connect phase. +- Added: [Authenticators](../Components/Authenticators/index.md) support to authenticate clients in the Connect phase. - Added: Profiler events. These events can be subscribed to by the [Network Profiler](../Guides/Profiler.md) to provide visual information. - Added: Transports now include channel in profiler events. - Added: Transport abstract class now supports sending a message to a list of connection id's. From ed366c53a707ec5e39663c2cd659273d152a164a Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sat, 4 Jul 2020 00:31:01 +0100 Subject: [PATCH 55/57] Update toc.yml --- doc/Transports/toc.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/Transports/toc.yml b/doc/Transports/toc.yml index 5bd9b3fb..22c40473 100644 --- a/doc/Transports/toc.yml +++ b/doc/Transports/toc.yml @@ -12,5 +12,7 @@ href: Ignorance.md - name: UDP - LiteNetLib4Mirror href: LiteNetLib4Mirror.md -- name: Steam - Fizzy - href: Fizzy.md +- name: Steam - FizzySteamworks + href: FizzySteamworks.md +- name: Steam - FizzyFacepunch + href: FizzyFacepunch.md From a69880a65bff912df6d769b5daa6e5bff13f2044 Mon Sep 17 00:00:00 2001 From: James Frowen Date: Sat, 4 Jul 2020 00:39:14 +0100 Subject: [PATCH 56/57] Update LiteNetLib4Mirror.md --- doc/Transports/LiteNetLib4Mirror.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/Transports/LiteNetLib4Mirror.md b/doc/Transports/LiteNetLib4Mirror.md index b45e30bd..a9884c94 100644 --- a/doc/Transports/LiteNetLib4Mirror.md +++ b/doc/Transports/LiteNetLib4Mirror.md @@ -29,7 +29,11 @@ ## IL2CPP Warning! With IL2CPP, IPv6 is only supported on Unity 2018.3.6f1 and later because of this: -![Unity ChangeLog](unity2018.3.6f1il2cpp.png) +[Unity ChangeLog](https://unity3d.com/unity/whats-new/2018.3.6) +> IL2CPP: Added protocol support for IPv6 on Windows. (1099133) +> +> IL2CPP: Correctly indicate that IPv6 is not supported on non-IPv6 platforms. (1108823) + Also, socket Reuse Address option isn't available in IL2CPP. ## Credits From d9442911ff1112ce6731595c9847e44c5880fee3 Mon Sep 17 00:00:00 2001 From: Paul Pacheco Date: Sat, 4 Jul 2020 06:49:02 -0500 Subject: [PATCH 57/57] ci: if docs have errors, fail the PR (#2065) Co-authored-by: Paul Pacheco --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c1b6edea..04881c48 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,8 +26,8 @@ install: skip_tags: true build_script: - - docfx metadata doc\docfx.json - - docfx build doc\docfx.json + - docfx metadata --logLevel Warning --warningsAsErrors doc\docfx.json + - docfx build --logLevel Warning --warningsAsErrors doc\docfx.json image: Visual Studio 2017