From b80c2377696e927267c4710b35479e8ba3dd59e0 Mon Sep 17 00:00:00 2001 From: Cristian Fleita Date: Sun, 1 Dec 2024 14:04:17 -0300 Subject: [PATCH 1/4] chore: wip add sdk and config --- .DS_Store | Bin 10244 -> 8196 bytes Assets/.DS_Store | Bin 12292 -> 12292 bytes Assets/Dojo.meta | 8 + Assets/Dojo/Editor.meta | 8 + Assets/Dojo/Editor/DojoEditor.asmdef | 14 + Assets/Dojo/Editor/DojoEditor.asmdef.meta | 7 + Assets/Dojo/Prefabs.meta | 8 + Assets/Dojo/Prefabs/WorldManager.prefab | 74 + Assets/Dojo/Prefabs/WorldManager.prefab.meta | 7 + Assets/Dojo/Runtime.meta | 8 + Assets/Dojo/Runtime/Config.meta | 8 + .../Dojo/Runtime/Config/WorldManagerData.cs | 21 + .../Runtime/Config/WorldManagerData.cs.meta | 11 + .../Config/WorldManagerLocalConfig.asset | 24 + .../Config/WorldManagerLocalConfig.asset.meta | 8 + Assets/Dojo/Runtime/DojoRuntime.asmdef | 14 + Assets/Dojo/Runtime/DojoRuntime.asmdef.meta | 7 + Assets/Dojo/Runtime/ModelInstance.cs | 153 + Assets/Dojo/Runtime/ModelInstance.cs.meta | 11 + Assets/Dojo/Runtime/Starknet.meta | 8 + Assets/Dojo/Runtime/Starknet/Account.cs | 153 + Assets/Dojo/Runtime/Starknet/Account.cs.meta | 3 + Assets/Dojo/Runtime/Starknet/BurnerManager.cs | 110 + .../Runtime/Starknet/BurnerManager.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/ByteArray.cs | 76 + .../Dojo/Runtime/Starknet/ByteArray.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/Enum.cs | 36 + Assets/Dojo/Runtime/Starknet/Enum.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/FieldElement.cs | 129 + .../Runtime/Starknet/FieldElement.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/Helpers.meta | 8 + .../Starknet/Helpers/ExecutionHelper.cs | 49 + .../Starknet/Helpers/ExecutionHelper.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs | 98 + .../Runtime/Starknet/JsonRpcClient.cs.meta | 3 + Assets/Dojo/Runtime/Starknet/Signature.cs | 88 + .../Dojo/Runtime/Starknet/Signature.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/SigningKey.cs | 73 + .../Dojo/Runtime/Starknet/SigningKey.cs.meta | 3 + .../Dojo/Runtime/Starknet/StarknetInterop.cs | 240 ++ .../Runtime/Starknet/StarknetInterop.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/TypedData.cs | 290 ++ .../Dojo/Runtime/Starknet/TypedData.cs.meta | 11 + Assets/Dojo/Runtime/Starknet/VerifyingKey.cs | 50 + .../Runtime/Starknet/VerifyingKey.cs.meta | 3 + Assets/Dojo/Runtime/SynchronizationMaster.cs | 178 + .../Runtime/SynchronizationMaster.cs.meta | 11 + Assets/Dojo/Runtime/Torii.meta | 8 + Assets/Dojo/Runtime/Torii/Entity.cs | 36 + Assets/Dojo/Runtime/Torii/Entity.cs.meta | 3 + Assets/Dojo/Runtime/Torii/Model.cs | 223 ++ Assets/Dojo/Runtime/Torii/Model.cs.meta | 11 + Assets/Dojo/Runtime/Torii/Query.cs | 303 ++ Assets/Dojo/Runtime/Torii/Query.cs.meta | 11 + Assets/Dojo/Runtime/Torii/ToriiClient.cs | 256 ++ Assets/Dojo/Runtime/Torii/ToriiClient.cs.meta | 11 + Assets/Dojo/Runtime/Torii/ToriiEvents.cs | 48 + Assets/Dojo/Runtime/Torii/ToriiEvents.cs.meta | 3 + Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs | 183 + .../Runtime/Torii/ToriiWasmClient.cs.meta | 11 + Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs | 83 + .../Runtime/Torii/ToriiWasmInterop.cs.meta | 11 + .../Dojo/Runtime/UnityMainThreadDispatcher.cs | 121 + .../Runtime/UnityMainThreadDispatcher.cs.meta | 11 + .../Runtime/UnityMainThreadDispatcher.prefab | 50 + .../UnityMainThreadDispatcher.prefab.meta | 7 + Assets/Dojo/Runtime/WorldManager.cs | 126 + Assets/Dojo/Runtime/WorldManager.cs.meta | 11 + Assets/Dojo/Runtime/bindings.meta | 8 + Assets/Dojo/Runtime/bindings/client.meta | 8 + .../bindings/client/AssemblyAttributes.gen.cs | 27 + .../client/AssemblyAttributes.gen.cs.meta | 11 + .../Runtime/bindings/client/Runtime.gen.cs | 790 +++++ .../bindings/client/Runtime.gen.cs.meta | 11 + .../Dojo/Runtime/bindings/client/dojo.gen.cs | 3131 +++++++++++++++++ .../Runtime/bindings/client/dojo.gen.cs.meta | 11 + Assets/Dojo/Tests.meta | 8 + Assets/Dojo/Tests/Runtime.meta | 8 + .../Tests/Runtime/DojoRuntimeTests.asmdef | 22 + .../Runtime/DojoRuntimeTests.asmdef.meta | 7 + Assets/Dojo/Tests/Runtime/DojoTests.cs | 223 ++ Assets/Dojo/Tests/Runtime/DojoTests.cs.meta | 3 + Assets/Spawn And Move.meta | 8 + Assets/Spawn And Move/CameraFollow.cs | 54 + Assets/Spawn And Move/CameraFollow.cs.meta | 11 + Assets/Spawn And Move/ChatManager.cs | 92 + Assets/Spawn And Move/ChatManager.cs.meta | 11 + Assets/Spawn And Move/Contracts.meta | 8 + .../Contracts/ns-actions.gen.cs | 177 + .../Contracts/ns-actions.gen.cs.meta | 11 + .../Contracts/ns-dungeon.gen.cs | 51 + .../Contracts/ns-dungeon.gen.cs.meta | 11 + .../Contracts/ns-mock_token.gen.cs | 34 + .../Contracts/ns-mock_token.gen.cs.meta | 11 + .../Spawn And Move/Contracts/ns-others.gen.cs | 34 + .../Contracts/ns-others.gen.cs.meta | 11 + Assets/Spawn And Move/GameManager.cs | 145 + Assets/Spawn And Move/GameManager.cs.meta | 11 + Assets/Spawn And Move/GameManagerData.asset | 16 + .../Spawn And Move/GameManagerData.asset.meta | 8 + Assets/Spawn And Move/GameManagerData.cs | 8 + Assets/Spawn And Move/GameManagerData.cs.meta | 11 + Assets/Spawn And Move/Models.meta | 8 + .../Spawn And Move/Models/ns-Message.gen.cs | 39 + .../Models/ns-Message.gen.cs.meta | 11 + .../Spawn And Move/Models/ns-MockToken.gen.cs | 28 + .../Models/ns-MockToken.gen.cs.meta | 11 + Assets/Spawn And Move/Models/ns-Moves.gen.cs | 47 + .../Models/ns-Moves.gen.cs.meta | 11 + .../Models/ns-PlayerConfig.gen.cs | 50 + .../Models/ns-PlayerConfig.gen.cs.meta | 11 + .../Spawn And Move/Models/ns-Position.gen.cs | 61 + .../Models/ns-Position.gen.cs.meta | 11 + .../Models/ns-ServerProfile.gen.cs | 37 + .../Models/ns-ServerProfile.gen.cs.meta | 11 + Assets/Spawn And Move/Models/ns-Test.gen.cs | 52 + .../Spawn And Move/Models/ns-Test.gen.cs.meta | 11 + Assets/Spawn And Move/Scenes.meta | 8 + Assets/Spawn And Move/Scenes/SampleScene.meta | 8 + .../Spawn And Move/Scenes/SampleScene.unity | 2080 +++++++++++ .../Scenes/SampleScene.unity.meta | 7 + .../Scenes/SampleScene/LightingData.asset | Bin 0 -> 18232 bytes .../SampleScene/LightingData.asset.meta | 8 + .../Scenes/SampleScene/ReflectionProbe-0.exr | Bin 0 -> 133546 bytes .../SampleScene/ReflectionProbe-0.exr.meta | 140 + Packages/packages-lock.json | 2 +- ProjectSettings/ProjectVersion.txt | 4 +- 127 files changed, 11259 insertions(+), 3 deletions(-) create mode 100644 Assets/Dojo.meta create mode 100644 Assets/Dojo/Editor.meta create mode 100644 Assets/Dojo/Editor/DojoEditor.asmdef create mode 100644 Assets/Dojo/Editor/DojoEditor.asmdef.meta create mode 100644 Assets/Dojo/Prefabs.meta create mode 100644 Assets/Dojo/Prefabs/WorldManager.prefab create mode 100644 Assets/Dojo/Prefabs/WorldManager.prefab.meta create mode 100644 Assets/Dojo/Runtime.meta create mode 100644 Assets/Dojo/Runtime/Config.meta create mode 100644 Assets/Dojo/Runtime/Config/WorldManagerData.cs create mode 100644 Assets/Dojo/Runtime/Config/WorldManagerData.cs.meta create mode 100644 Assets/Dojo/Runtime/Config/WorldManagerLocalConfig.asset create mode 100644 Assets/Dojo/Runtime/Config/WorldManagerLocalConfig.asset.meta create mode 100644 Assets/Dojo/Runtime/DojoRuntime.asmdef create mode 100644 Assets/Dojo/Runtime/DojoRuntime.asmdef.meta create mode 100644 Assets/Dojo/Runtime/ModelInstance.cs create mode 100644 Assets/Dojo/Runtime/ModelInstance.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet.meta create mode 100644 Assets/Dojo/Runtime/Starknet/Account.cs create mode 100644 Assets/Dojo/Runtime/Starknet/Account.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/BurnerManager.cs create mode 100644 Assets/Dojo/Runtime/Starknet/BurnerManager.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/ByteArray.cs create mode 100644 Assets/Dojo/Runtime/Starknet/ByteArray.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/Enum.cs create mode 100644 Assets/Dojo/Runtime/Starknet/Enum.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/FieldElement.cs create mode 100644 Assets/Dojo/Runtime/Starknet/FieldElement.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/Helpers.meta create mode 100644 Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs create mode 100644 Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs create mode 100644 Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/Signature.cs create mode 100644 Assets/Dojo/Runtime/Starknet/Signature.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/SigningKey.cs create mode 100644 Assets/Dojo/Runtime/Starknet/SigningKey.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/StarknetInterop.cs create mode 100644 Assets/Dojo/Runtime/Starknet/StarknetInterop.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/TypedData.cs create mode 100644 Assets/Dojo/Runtime/Starknet/TypedData.cs.meta create mode 100644 Assets/Dojo/Runtime/Starknet/VerifyingKey.cs create mode 100644 Assets/Dojo/Runtime/Starknet/VerifyingKey.cs.meta create mode 100644 Assets/Dojo/Runtime/SynchronizationMaster.cs create mode 100644 Assets/Dojo/Runtime/SynchronizationMaster.cs.meta create mode 100644 Assets/Dojo/Runtime/Torii.meta create mode 100644 Assets/Dojo/Runtime/Torii/Entity.cs create mode 100644 Assets/Dojo/Runtime/Torii/Entity.cs.meta create mode 100644 Assets/Dojo/Runtime/Torii/Model.cs create mode 100644 Assets/Dojo/Runtime/Torii/Model.cs.meta create mode 100644 Assets/Dojo/Runtime/Torii/Query.cs create mode 100644 Assets/Dojo/Runtime/Torii/Query.cs.meta create mode 100644 Assets/Dojo/Runtime/Torii/ToriiClient.cs create mode 100644 Assets/Dojo/Runtime/Torii/ToriiClient.cs.meta create mode 100644 Assets/Dojo/Runtime/Torii/ToriiEvents.cs create mode 100644 Assets/Dojo/Runtime/Torii/ToriiEvents.cs.meta create mode 100644 Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs create mode 100644 Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs.meta create mode 100644 Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs create mode 100644 Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs.meta create mode 100644 Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs create mode 100644 Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs.meta create mode 100644 Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab create mode 100644 Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab.meta create mode 100644 Assets/Dojo/Runtime/WorldManager.cs create mode 100644 Assets/Dojo/Runtime/WorldManager.cs.meta create mode 100644 Assets/Dojo/Runtime/bindings.meta create mode 100644 Assets/Dojo/Runtime/bindings/client.meta create mode 100644 Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs create mode 100644 Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs.meta create mode 100644 Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs create mode 100644 Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs.meta create mode 100644 Assets/Dojo/Runtime/bindings/client/dojo.gen.cs create mode 100644 Assets/Dojo/Runtime/bindings/client/dojo.gen.cs.meta create mode 100644 Assets/Dojo/Tests.meta create mode 100644 Assets/Dojo/Tests/Runtime.meta create mode 100644 Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef create mode 100644 Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef.meta create mode 100644 Assets/Dojo/Tests/Runtime/DojoTests.cs create mode 100644 Assets/Dojo/Tests/Runtime/DojoTests.cs.meta create mode 100644 Assets/Spawn And Move.meta create mode 100644 Assets/Spawn And Move/CameraFollow.cs create mode 100644 Assets/Spawn And Move/CameraFollow.cs.meta create mode 100644 Assets/Spawn And Move/ChatManager.cs create mode 100644 Assets/Spawn And Move/ChatManager.cs.meta create mode 100644 Assets/Spawn And Move/Contracts.meta create mode 100644 Assets/Spawn And Move/Contracts/ns-actions.gen.cs create mode 100644 Assets/Spawn And Move/Contracts/ns-actions.gen.cs.meta create mode 100644 Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs create mode 100644 Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs.meta create mode 100644 Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs create mode 100644 Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs.meta create mode 100644 Assets/Spawn And Move/Contracts/ns-others.gen.cs create mode 100644 Assets/Spawn And Move/Contracts/ns-others.gen.cs.meta create mode 100644 Assets/Spawn And Move/GameManager.cs create mode 100644 Assets/Spawn And Move/GameManager.cs.meta create mode 100644 Assets/Spawn And Move/GameManagerData.asset create mode 100644 Assets/Spawn And Move/GameManagerData.asset.meta create mode 100644 Assets/Spawn And Move/GameManagerData.cs create mode 100644 Assets/Spawn And Move/GameManagerData.cs.meta create mode 100644 Assets/Spawn And Move/Models.meta create mode 100644 Assets/Spawn And Move/Models/ns-Message.gen.cs create mode 100644 Assets/Spawn And Move/Models/ns-Message.gen.cs.meta create mode 100644 Assets/Spawn And Move/Models/ns-MockToken.gen.cs create mode 100644 Assets/Spawn And Move/Models/ns-MockToken.gen.cs.meta create mode 100644 Assets/Spawn And Move/Models/ns-Moves.gen.cs create mode 100644 Assets/Spawn And Move/Models/ns-Moves.gen.cs.meta create mode 100644 Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs create mode 100644 Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs.meta create mode 100644 Assets/Spawn And Move/Models/ns-Position.gen.cs create mode 100644 Assets/Spawn And Move/Models/ns-Position.gen.cs.meta create mode 100644 Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs create mode 100644 Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs.meta create mode 100644 Assets/Spawn And Move/Models/ns-Test.gen.cs create mode 100644 Assets/Spawn And Move/Models/ns-Test.gen.cs.meta create mode 100644 Assets/Spawn And Move/Scenes.meta create mode 100644 Assets/Spawn And Move/Scenes/SampleScene.meta create mode 100644 Assets/Spawn And Move/Scenes/SampleScene.unity create mode 100644 Assets/Spawn And Move/Scenes/SampleScene.unity.meta create mode 100644 Assets/Spawn And Move/Scenes/SampleScene/LightingData.asset create mode 100644 Assets/Spawn And Move/Scenes/SampleScene/LightingData.asset.meta create mode 100644 Assets/Spawn And Move/Scenes/SampleScene/ReflectionProbe-0.exr create mode 100644 Assets/Spawn And Move/Scenes/SampleScene/ReflectionProbe-0.exr.meta diff --git a/.DS_Store b/.DS_Store index 92b7b76cab368cab4856d1c2187de30a23e218c0..3da779623981d7810658cba0ac806c9239dbc35a 100644 GIT binary patch literal 8196 zcmeHMU2GIp6u#fIlo>kEDJ)P|$_`W|!U{zwPyyNgq2;&fwzRa!c6Vol3DcRfGrL7A zTJ;GH@h=)<)WjzxDi6kgjXoF@eegl?2V;CNYK-wO(fH(p=gyrab_;LDD9ml2F9377pGb+b?0e(oL|$L6iTXzg7g{lnU@>)#&Wisn>ITV zL=lK05Je!0Koo%}0{?{w(3#Dfe1UUcj7EJFfhYo(WCZyBpwq=^Dx{Nw23rSpK?y*V zmjFSdd#VEh9X+I}kWLC3sFF=lJs?y?SYkk^)40y36HSG5Qc$7JAk-PcCnKy-5Imjq z^k6zeO3leNDY+;yleXeWg%J876Y=P zC>d?x#KhW`)}-Frd^D*~tZ!{e>KoRy96hSY^P5&}?9CjqM;-T=@B-mZz-Cu?bx);B zwpZ#9pCqbU$}W9Tc1f94tIm%1_3s%NR5RM#621HGG2e0>Z;x5T5{#`Rcl)}w{P9H>r9O^AUm?rGT;5SIsTX2(S^R26%gTKoIVwyf)s>3o zDSd}%#f9o>b&aeUO23`WnYIwEQ#Z)kc4eR>Vl9L*b(5?N=H1azdTCF{w#3_H?XJD#E>wXBovU?Z%+ zCfITID0_;%$WF0$*(dBP_8t3?{Q*G24Ah_&F*G6p9ZRqrD{u`~Vk0`yg{|ntF!o_T zGB7X-2V*#l67Ikx?!w(Th6nKw9>ybh5>Mk9oWKis18?Fjyp0d>89v8Ze1o6xGk%dE z&5~l$d})D{kaTIO)FiEw)=Md=Tk4etq!IDzQaPc9%C3d-EYT@@1SM4XjZZpx{)9^0 zaAWtj?f;*IIy;A_(7f3E1q*eaR~t6Bodcl2YZ;<{hkk(eDLE3LJwQYyQYq0cU(~23 z`Y9dEBb5nSPF!s!Pfz&_pS@(Mn$TuY!U*=NWyID{vIurXGLg_E%2B~KuTH316=k3j z=(Z$@MaZ;Xr>a^t<)Rq7zL8iKGVL8?hG&-iPhtEl`?YvA>N z*M-0TU(6whe2XG*$wvUyo$1bY3d4oAKwfL>bdAu(8=p5RXrMw}P>vG~%5kFS{$WV> hI!)y|sgORNMdn literal 10244 zcmeHMZ)_Ar6rZ;(bdQy?)I!Uj<*rs}EvH;dTd63$Uax^dOG~e%f8o5lUD}oH?s0o} zZEafXCl%DhFB%m!evl|1K%)p6zp1E+F@_*fVj{-GPkhk`elS7b?Ch1hgZd3aaHpAh z`{unjJM(+*&E8B2ArMH(wS;&GAv{(}#k;V%NuhFDZz!DIQ;rnSo{%IlH8b5B)r{y3 z+D?aqfP;X8fP;X8fP=v8fB=58Y2gJ%oz_9XLBK&^9s#;Pc(79Hx9J?C*4BZIbp$|K zh}~AfXFLa3HXfV$Z92!OWr}06(*xM1U>`AnnWNl8)sgybI>#t8C&0`J*lz~=gaX#v z(avM36Yw+Yv+siu`+B&nETahW-0Oti-gy*r_#Rb`?-W@xE#9VN?S5iOQNWu-;a zLh9p8JC-mst=llwq-yAc14(5vNo91P9MQm#X(W=Z)?foFj?c78=sUXN)Y#msBuu0( z*NNgX_r2Bk*FE^KzpcG<&-rEI@)Ds`SlOReO*N`1eG{sj92<<7F-4bEeRN2b6+NjQ zP?dyhIe1;YdSqNVUsAqm^_sPkl&_r`Wgrz*52e)Plvv60>>U+SrAs`;kI1;lPD7?6 z%9cc`kg9lonD)0O6l__yP$PL=VubHCamj3mO+u|pG+n(1RoynN7aDm{cJ*nIsG_ma znuM*qxXaa_W-Df$r9w0B8i*O=3^doxQ*O4u9@4x?cs*FFgM0lz}a6ZvM+aK+!XTp=@w_#W!#CI zr<;5Gj`p3qI&Rx^`=OX7*xjWoR+f3z*KDfa@<_{k7_z9%1Zs8ySTUcIDOSu|agiUd zEE5HHA0~w|xllriMKpQ&^HjUy9>Fax!n9%RhALziW6Cggqu1>gIm}eX`fA;RSb%xx zvTPf?$b!u@JtPQXA!a0#ZIh5CHWO&YVQ7Bww<^-VBIn5W;2SU&b`ydPvh+?d3phFxEK?0^>2A+U9coHN1S$GbfhnL`GjP|1# z@5kV6cn6Nd`)~?Q!x{L_N6cV{dE%S z1Akk^vYOY6PMCJIlQWrUzhHk{ii(PaqJ1I!ez5H$5J?PEuGcWMXy!Q*-HSVZSS)Qd z^khWEeakYy9UN6g`Y}L^iGY#PWz(_^F@Xz9SS+8OZm4hYdNw!K&3HZ2O?5u6r@pCf zX2!*@sNA%*Cwx#F*Nwy0j0t2icq!xO+avfizaH6)X;GXXmCko+qqQO2hvT$!&4BxI zwrt!825q4DC4RY(L~^T=&AwHL`usUwn!BAj>|_161l12LT5G2LT5GLJAlN9(w=Z zw($S|9jF`x90cxQ1fVb&3I=e2nKMuRTIpT82kWC)X`y;^j9MnxSl97Lt?PJX=yiNG mR;p{?@>tJ)yKjzB%N%tqbENDx|CawVz&Zar=l}ot`TrlVsdB0S diff --git a/Assets/.DS_Store b/Assets/.DS_Store index e21ded53b2bd479d25965cc905c350402f9fb764..95f80706090251c22ca54c9c81790c3148dc09da 100644 GIT binary patch delta 317 zcmZokXi1ph&uG6fU^hRb#%3OYFeXNZ&B;PbSY-Jaf*A@J5*f-F@)#5t9D!sCkoINB zXDDMxoy;vF%g8a=K{{HBlQUjGyt>-N)KW*m(x6sHq1xQiR7b(W*mUwd5o2Av#*_sY w<>ln(r86)vFaj~pWCwAH%?jdo*f(=42(WXKZk;4f>ozlMNRVTq6iyQv0PUYbjQ{`u delta 59 zcmZokXi1ph&uF_bU^hRb+GZYsFeXOE&B;PbSQvRG`%6e{)|a@$zOjLyaWl7q0Q+Pu MiI)ty; + var instance = Array.CreateInstance(elementType, array.Count); + for (var i = 0; i < array.Count; i++) + { + instance.SetValue(HandleField(elementType, array[i]), i); + } + return instance; + } + // handle tuple (ValueTuple - (T1, T2)) + else if (type.FullName.StartsWith(typeof(ValueTuple).FullName)) + { + var tupleTypes = type.GetGenericArguments(); + var instance = Activator.CreateInstance(type); + var fields = type.GetFields(); + for (var i = 0; i < fields.Length; i++) + { + fields[i].SetValue(instance, HandleField(tupleTypes[i], ((IList)ty)[i])); + } + return instance; + } + // dynamic types + // handle record (rust-like) enums + else if (ty is Model.Enum enumVariant) + { + var variantType = type.GetNestedType(enumVariant.option); + if (variantType == null) + { + throw new Exception($"Could not find variant {enumVariant.option} in enum {type}"); + } + + if (type.GenericTypeArguments.Length > 0) + { + variantType = variantType.MakeGenericType(type.GenericTypeArguments); + } + + List args = new List(); + if (variantType.GetProperty("value") is PropertyInfo prop) + { + args.Add(HandleField(prop.PropertyType, enumVariant.value)); + } + + return Activator.CreateInstance(variantType, args.ToArray()); + + } + // if the field is a struct/class. we check if our member is a dictionary + // and we go through each of its keys and values and set them to the fields + // of the instantiated struct/class + else if (ty is Model.Struct struct_) + { + var instance = Activator.CreateInstance(type); + var fields = type.GetFields(); + + foreach (var field in fields) + { + field.SetValue(instance, HandleField(field.FieldType, struct_.members[field.Name])); + } + + return instance; + } + else + { + throw new Exception($"Could not handle field of type {type}"); + } + } + + // Called when the model is updated + public virtual void OnUpdate(Model model) + { + Initialize(model); + OnUpdated.Invoke(); + } + } +} diff --git a/Assets/Dojo/Runtime/ModelInstance.cs.meta b/Assets/Dojo/Runtime/ModelInstance.cs.meta new file mode 100644 index 00000000..48e53f08 --- /dev/null +++ b/Assets/Dojo/Runtime/ModelInstance.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c88eb655135047b8b5f175b0d77b362 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet.meta b/Assets/Dojo/Runtime/Starknet.meta new file mode 100644 index 00000000..16058ffc --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57353194ecb5d4b72958ef41f789b739 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/Account.cs b/Assets/Dojo/Runtime/Starknet/Account.cs new file mode 100644 index 00000000..d849ad6d --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Account.cs @@ -0,0 +1,153 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using bottlenoselabs.C2CS.Runtime; +using dojo_bindings; +using Debug = UnityEngine.Debug; + +namespace Dojo.Starknet +{ + public class Account + { +#if UNITY_WEBGL && !UNITY_EDITOR + private TaskCompletionSource account = new(); +#else + private unsafe dojo.Account* account; +#endif + + public FieldElement Address { get; } + public SigningKey Signer { get; } + +#if UNITY_WEBGL && !UNITY_EDITOR + private async void createAccount(JsonRpcClient provider, SigningKey privateKey, FieldElement address) + { + account.SetResult(await StarknetInterop.NewAccountAsync(provider.client, privateKey, address)); + } + + public Account(JsonRpcClient provider, SigningKey privateKey, FieldElement address) + { + createAccount(provider, privateKey, address); + Address = address; + Signer = privateKey; + } +#else + public unsafe Account(JsonRpcClient provider, SigningKey privateKey, FieldElement address) + { + var resultAccount = dojo.account_new(provider.client, privateKey.Inner.Inner, + CString.FromString(address.Hex())); + if (resultAccount.tag == dojo.ResultAccount_Tag.ErrAccount) + { + throw new Exception(resultAccount.err.message); + } + + account = resultAccount._ok; + Address = address; + Signer = privateKey; + } +#endif + + +#if UNITY_WEBGL && !UNITY_EDITOR + public Account(IntPtr account, SigningKey signingKey) { + this.account.SetResult(account); + Address = new FieldElement(StarknetInterop.AccountAddress(account)); + Signer = signingKey; + } +#else + private unsafe Account(dojo.Account* account, SigningKey signingKey) + { + this.account = account; + Address = new FieldElement(dojo.account_address(account)); + Signer = signingKey; + } +#endif + + unsafe ~Account() + { +#if UNITY_WEBGL && !UNITY_EDITOR +#else + dojo.account_free(account); +#endif + } + +#if UNITY_WEBGL && !UNITY_EDITOR + public async Task Nonce() + { + return await StarknetInterop.AccountNonceAsync(await account.Task); + } +#else + public unsafe FieldElement NonceSync() + { + var result = dojo.account_nonce(account); + if (result.tag == dojo.ResultFieldElement_Tag.ErrFieldElement) + { + throw new Exception(result.err.message); + } + + return new FieldElement(result.ok); + } + + public async Task Nonce() + { + return await Task.Run(() => Nonce()); + } +#endif + +#if UNITY_WEBGL && !UNITY_EDITOR + // webgl js interop starknet bindings + public async Task ExecuteRaw(dojo.Call[] calls) + { + var res = await StarknetInterop.AccountExecuteRawAsync(await account.Task, calls); + + return res; + } +#else + private unsafe FieldElement ExecuteRawSync(dojo.Call[] calls) + { + dojo.Call* callsPtr; + fixed (dojo.Call* ptr = &calls[0]) + { + callsPtr = ptr; + } + + var result = dojo.account_execute_raw(account, callsPtr, (nuint)calls.Length); + if (result.tag == dojo.ResultFieldElement_Tag.ErrFieldElement) + { + throw new Exception(result.err.message); + } + + return new FieldElement(result.ok); + } + + public async Task ExecuteRaw(dojo.Call[] calls) + { + return await Task.Run(() => ExecuteRawSync(calls)); + } +#endif + +#if !UNITY_WEBGL || UNITY_EDITOR + // This will synchroneously wait for the burner to be deployed. + // Implemented for C bindings that arent async. + private unsafe Account DeployBurnerSync(JsonRpcClient provider, SigningKey signingKey) + { + var result = dojo.account_deploy_burner(provider.client, account, signingKey.Inner.Inner); + if (result.tag == dojo.ResultAccount_Tag.ErrAccount) + { + throw new Exception(result.err.message); + } + + return new Account(result._ok, signingKey); + } +#endif + + // Deploy a burner and return the account once it is deployed. + public async Task DeployBurner(JsonRpcClient provider, SigningKey signingKey) + { +#if UNITY_WEBGL && !UNITY_EDITOR + return new Account(await StarknetInterop.AccountDeployBurnerAsync(await account.Task, signingKey), signingKey); +#else + return await Task.Run(() => DeployBurnerSync(provider, signingKey)); +#endif + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/Account.cs.meta b/Assets/Dojo/Runtime/Starknet/Account.cs.meta new file mode 100644 index 00000000..af93a76a --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Account.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9d6d2695217b4eca995e809d34c4184c +timeCreated: 1701892948 \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/BurnerManager.cs b/Assets/Dojo/Runtime/Starknet/BurnerManager.cs new file mode 100644 index 00000000..fa6765e1 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/BurnerManager.cs @@ -0,0 +1,110 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using dojo_bindings; +using Newtonsoft.Json; +using UnityEngine; +using UnityEngine.UIElements; +using Debug = UnityEngine.Debug; + +namespace Dojo.Starknet +{ + public class BurnerManager + { + private JsonRpcClient provider; + private Account masterAccount; + private int currentBurnerIndex = 0; + public Account CurrentBurner + { + get + { + if (Burners.Count == 0) return null; + return Burners[currentBurnerIndex]; + } + } + public List Burners { get; } = new(); + public bool UseStorage { get; set; } + + public BurnerManager(JsonRpcClient provider, Account masterAccount, bool useStorage = true) + { + this.provider = provider; + this.masterAccount = masterAccount; + UseStorage = useStorage; + + if (UseStorage) + { + TryLoadFromStorage(); + } + } + + public async Task DeployBurner(SigningKey signingKey = null) + { + if (signingKey == null) + { + signingKey = new SigningKey(); + } + + Burners.Add(await masterAccount.DeployBurner(provider, signingKey)); + currentBurnerIndex = Burners.Count - 1; + + + if (UseStorage) + { + Save(); + } + + return CurrentBurner; + } + + + // Load the burners from disk. + // This will be called automatically if useStorage is set to true. + public void TryLoadFromStorage() + { + + // Load all burners + var burnersData = PlayerPrefs.GetString($"burnermanagers.{masterAccount.Address.Hex()}.burners"); + if (!string.IsNullOrEmpty(burnersData)) + { + var burners = JsonConvert.DeserializeObject>>(burnersData); + foreach (var burnerData in burners) + { + var address = new FieldElement(burnerData["address"]); + var privateKey = burnerData["privateKey"]; + Burners.Add(new Account(provider, new SigningKey(privateKey), address)); + } + } + + // Load the current burner + var currentBurnerIndex = PlayerPrefs.GetInt($"burnermanagers.{masterAccount.Address.Hex()}.current", -1); + if (currentBurnerIndex >= 0 && currentBurnerIndex < Burners.Count) + { + this.currentBurnerIndex = currentBurnerIndex; + } + } + + // Save the burners to disk. + // This will be called automatically if useStorage is set to true. + public void Save() + { + // Save the current burner + if (CurrentBurner != null) + { + PlayerPrefs.SetInt($"burnermanagers.{masterAccount.Address.Hex()}.current", currentBurnerIndex); + } + + // Save all burners + var burnersData = JsonConvert.SerializeObject(Burners.Select(burner => new + { + address = burner.Address.Hex(), + privateKey = burner.Signer.Inner.Hex() + })); + + PlayerPrefs.SetString($"burnermanagers.{masterAccount.Address.Hex()}.burners", burnersData); + + PlayerPrefs.Save(); + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/BurnerManager.cs.meta b/Assets/Dojo/Runtime/Starknet/BurnerManager.cs.meta new file mode 100644 index 00000000..10e34268 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/BurnerManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30a9fe3957b9d4eb29e933eaf97b3a51 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/ByteArray.cs b/Assets/Dojo/Runtime/Starknet/ByteArray.cs new file mode 100644 index 00000000..8177c21b --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/ByteArray.cs @@ -0,0 +1,76 @@ +using System; +using System.Linq; +using bottlenoselabs.C2CS.Runtime; +using dojo_bindings; + +namespace Dojo.Starknet +{ + unsafe public class ByteArray + { + public string Inner { get; } + + public ByteArray(string inner) + { + Inner = inner; + } + + public ByteArray(FieldElement[] felts) + { + Inner = Deserialize(felts); + } + + public FieldElement[] Serialize() + { + return Serialize(Inner); + } + + public static string Deserialize(FieldElement[] felts) + { +#if UNITY_WEBGL && !UNITY_EDITOR + return StarknetInterop.DeserializeByteArray(felts); +#else + dojo.FieldElement[] inners = felts.Select(felt => felt.Inner).ToArray(); + fixed (dojo.FieldElement* ptr = inners) + { + var res = dojo.bytearray_deserialize(ptr, (UIntPtr)inners.Length); + if (res.tag == dojo.Resultc_char_Tag.Errc_char) + { + throw new Exception(res.err.message); + } + + return res.ok; + } +#endif + } + + public static FieldElement[] Serialize(string str) + { +#if UNITY_WEBGL && !UNITY_EDITOR + return StarknetInterop.SerializeByteArray(str); +#else + var res = dojo.bytearray_serialize(new CString(str)); + if (res.tag == dojo.ResultCArrayFieldElement_Tag.ErrCArrayFieldElement) + { + throw new Exception(res.err.message); + } + + return res.ok.ToArray().Select(felt => new FieldElement(felt)).ToArray(); +#endif + } + + public static implicit operator string(ByteArray inner) + { + return inner.Inner; + } + + public static implicit operator ByteArray(string inner) + { + return new ByteArray(inner); + } + + public override string ToString() + { + return Inner; + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/ByteArray.cs.meta b/Assets/Dojo/Runtime/Starknet/ByteArray.cs.meta new file mode 100644 index 00000000..9d72c2b3 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/ByteArray.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a5c062d72aa847cf88abc86438ba5ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/Enum.cs b/Assets/Dojo/Runtime/Starknet/Enum.cs new file mode 100644 index 00000000..7d75dc34 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Enum.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Dojo.Starknet +{ + // The interface that all Starknet enums generated from the dojo-bindgen implement + public interface Enum + { + // A static dictionary to keep track of the indices of each Enum implementing the Enum interface + // The first dictionary is indexed by the Enum type, and the second dictionary is indexed by the Enum variant name + // The value is the index of the Enum variant + // This makes getting a Starknet enum variant index O(1) if we already cached the indices + private static Dictionary> TypeIndices = new Dictionary>(); + + // Get the index of the enum variant + // This is needed as Starknet enums are represented as a Record in C# + // Each enum variant is a nested class of the enum type, implementing the Enum itself. + public static int GetIndex(Enum value) + { + var type = value.GetType(); + if (!TypeIndices.ContainsKey(type.BaseType)) + { + TypeIndices[type.BaseType] = type.BaseType + .GetNestedTypes(BindingFlags.Public) + .OrderBy(t => t.MetadataToken) + .Select((type, index) => new { type, index }) + .ToDictionary(t => t.type.Name, t => t.index); + } + + + return TypeIndices[type.BaseType][type.Name]; + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/Enum.cs.meta b/Assets/Dojo/Runtime/Starknet/Enum.cs.meta new file mode 100644 index 00000000..8f9f969f --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Enum.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 70dbed3ddf18042eba185c6104d1ad1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/FieldElement.cs b/Assets/Dojo/Runtime/Starknet/FieldElement.cs new file mode 100644 index 00000000..2daca336 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/FieldElement.cs @@ -0,0 +1,129 @@ +using System; +using System.Globalization; +using System.Linq; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using dojo_bindings; +using Newtonsoft.Json; +using UnityEngine; + +namespace Dojo.Starknet +{ + class FieldElementConverter : JsonConverter { + public override bool CanConvert(Type objectType) + { + return objectType == typeof(FieldElement); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var fieldElement = (FieldElement)value; + writer.WriteValue(fieldElement.Hex()); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + var hex = (string)reader.Value; + return new FieldElement(hex); + } + } + [Serializable] + [JsonConverter(typeof(FieldElementConverter))] + public class FieldElement : ISerializationCallbackReceiver + { + private dojo.FieldElement inner; + public dojo.FieldElement Inner => inner; + // Serialized as a hex string. + [SerializeField] private string hex; + + public static BigInteger StarkField = BigInteger.Parse("3618502788666131213697322783095070105623107215331596699973092056135872020481"); + + // These constructors are pretty slow as they involve a lot of copying. + // TODO: benchmark and optimize + public FieldElement(string input) + { + BigInteger value; + + if (input.StartsWith("0x")) + { + if (!BigInteger.TryParse("0" + input.Substring(2), NumberStyles.HexNumber, null, out value)) + { + throw new ArgumentException("Invalid hex string.", nameof(input)); + } + } + else + { + if (!BigInteger.TryParse(input, out value)) + { + throw new ArgumentException("Invalid decimal string.", nameof(input)); + } + } + + inner = new FieldElement(value).inner; + } + + public FieldElement(dojo.FieldElement fieldElement) + { + // We don't want to refer to the same memory as the original field element. + // As we might want to free it - potentially slower + // TODO: benchmark copies? + fieldElement.data.CopyTo(inner.data); + } + + public FieldElement(Span bytes) + { + if (bytes.Length != 32) + { + throw new ArgumentException("Byte array must be 32 bytes.", nameof(bytes)); + } + + bytes.CopyTo(inner.data); + } + + // This handles BigIntegers as well as primitive types + public FieldElement(BigInteger bigInteger) + { + if (bigInteger.Sign < 0) { + bigInteger = StarkField - bigInteger; + } + + var bytes = bigInteger.ToByteArray(false, true); + if (bytes.Length > 32) + { + throw new ArgumentException("BigInteger must be 32 bytes or less.", nameof(bigInteger)); + } + + unsafe + { + fixed (byte* ptr = &inner._data[0]) + { + // we need to account bytes that are less than 32 bytes + // and add leading zeros + var offset = 32 - bytes.Length; + Marshal.Copy(bytes, 0, (IntPtr)ptr + offset, bytes.Length); + } + } + } + + // This convert the enum to a uint64 and uses the BigInteger constructor + public FieldElement(Enum @enum) : this(Convert.ToUInt64(@enum)) + { + } + + public string Hex() + { + return "0x" + BitConverter.ToString(inner.data.ToArray()).Replace("-", "").ToLower(); + } + + public void OnAfterDeserialize() + { + inner = new FieldElement(hex).inner; + } + + public void OnBeforeSerialize() + { + hex = Hex(); + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/FieldElement.cs.meta b/Assets/Dojo/Runtime/Starknet/FieldElement.cs.meta new file mode 100644 index 00000000..1804577a --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/FieldElement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fec08a0fbfcff4b8ab7c20a0e7766b93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/Helpers.meta b/Assets/Dojo/Runtime/Starknet/Helpers.meta new file mode 100644 index 00000000..216644dc --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Helpers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fca358df00aec498ea038070d7d51212 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs b/Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs new file mode 100644 index 00000000..040627a0 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Dojo.Starknet; +using dojo_bindings; + +namespace Starknet { + public struct Call { + public FieldElement contractAddress; + public string selector; + public FieldElement[] calldata; + + public Call(FieldElement contractAddress, string selector, params FieldElement[] calldata) { + this.contractAddress = contractAddress; + this.selector = selector; + this.calldata = calldata; + } + } + + // A helper class for constructing and executing Starknet transactions. + public class ExecutionHelper { + public Account account { get; } + private List calls; + + public ExecutionHelper(Account account) { + this.account = account; + calls = new List(); + } + + public ExecutionHelper AddCall(Call call) { + calls.Add(call); + return this; + } + + public ExecutionHelper AddCall(FieldElement contractAddress, string selector, params FieldElement[] calldata) { + var call = new Call(contractAddress, selector, calldata); + return AddCall(call); + } + + public async Task Execute() { + return await account.ExecuteRaw(calls.Select(call => new dojo.Call { + to = call.contractAddress.Inner, + selector = call.selector, + calldata = call.calldata.Select(field => field.Inner).ToArray() + }).ToArray()); + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs.meta b/Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs.meta new file mode 100644 index 00000000..b9cb8c9d --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Helpers/ExecutionHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 121bbc4a0d0f648789c913e301225419 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs b/Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs new file mode 100644 index 00000000..c5940652 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs @@ -0,0 +1,98 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using bottlenoselabs.C2CS.Runtime; +using dojo_bindings; + +namespace Dojo.Starknet +{ + public class JsonRpcClient + { +#if UNITY_WEBGL && !UNITY_EDITOR + public IntPtr client; +#else + public unsafe dojo.Provider* client; +#endif + +#if UNITY_WEBGL && !UNITY_EDITOR + public JsonRpcClient(string rpcUrl) { + client = StarknetInterop.NewProvider(new CString(rpcUrl)); + } +#else + public unsafe JsonRpcClient(string rpcUrl) + { + var result = dojo.provider_new(CString.FromString(rpcUrl)); + if (result.tag == dojo.ResultProvider_Tag.ErrProvider) + { + throw new Exception(result.err.message); + } + + client = result._ok; + } +#endif + +#if UNITY_WEBGL && !UNITY_EDITOR +#else + unsafe ~JsonRpcClient() + { + dojo.provider_free(client); + } +#endif +#if UNITY_WEBGL && !UNITY_EDITOR +#else + // Wait for the transaction to be confirmed. Synchronously. + // This doesn't guarantee that the torii client has updated its state + // if an entity is updated. + private unsafe void WaitForTransactionSync(FieldElement transactionHash) + { + var result = dojo.wait_for_transaction(client, transactionHash.Inner); + if (result.tag == dojo.Resultbool_Tag.Errbool) + { + throw new Exception(result.err.message); + } + } +#endif + + // Wait for the transaction to be confirmed. Asynchronously. + // This doesn't guarantee that the torii client has updated its state + // if an entity is updated. + public async Task WaitForTransaction(FieldElement transactionHash) + { +#if UNITY_WEBGL && !UNITY_EDITOR + await StarknetInterop.WaitForTransactionAsync(client, transactionHash); +#else + await Task.Run(() => WaitForTransactionSync(transactionHash)); +#endif + } + + +#if UNITY_WEBGL && !UNITY_EDITOR +#else + private unsafe FieldElement[] CallSync(dojo.Call call, dojo.BlockId blockId) + { + var result = dojo.starknet_call(client, call, blockId); + if (result.tag == dojo.ResultCArrayFieldElement_Tag.ErrCArrayFieldElement) + { + throw new Exception(result.err.message); + } + + var arr = result.ok.ToArray().Select(f => new FieldElement(f)).ToArray(); + dojo.carray_free(result._ok.data, result._ok.data_len); + + return arr; + } +#endif + + // Wait for the transaction to be confirmed. Asynchronously. + // This doesn't guarantee that the torii client has updated its state + // if an entity is updated. + public async Task Call(dojo.Call call, dojo.BlockId blockId) + { +#if UNITY_WEBGL && !UNITY_EDITOR + return await StarknetInterop.CallAsync(client, call, blockId); +#else + return await Task.Run(() => CallSync(call, blockId)); +#endif + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs.meta b/Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs.meta new file mode 100644 index 00000000..3032327a --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/JsonRpcClient.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7eacd5a60b914bd2bf5336616e72f351 +timeCreated: 1702074309 \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/Signature.cs b/Assets/Dojo/Runtime/Starknet/Signature.cs new file mode 100644 index 00000000..5d43ba62 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Signature.cs @@ -0,0 +1,88 @@ +using dojo_bindings; +using bottlenoselabs.C2CS.Runtime; + +namespace Dojo.Starknet +{ + public class Signature + { + public dojo.Signature Inner { get; } + + // Create a signature from a compact hex string. + public Signature(string compactHex) + { + if (compactHex.Length != 128) + { + throw new System.ArgumentException("Compact hex string must be 128 characters.", nameof(compactHex)); + } + + var r = new FieldElement("0x" + compactHex.Substring(0, 64)); + var s = new FieldElement("0x" + compactHex.Substring(64, 64)); + + Inner = new dojo.Signature + { + r = r.Inner, + s = s.Inner + }; + } + + public Signature(FieldElement r, FieldElement s) + { + Inner = new dojo.Signature + { + r = r.Inner, + s = s.Inner + }; + } + + public Signature(dojo.Signature signature) + { + Inner = signature; + } + + public FieldElement R() + { + return new FieldElement(Inner.r); + } + + public FieldElement S() + { + return new FieldElement(Inner.s); + } + +#if UNITY_WEBGL && !UNITY_EDITOR + // webgl js interop starknet bindings + public bool Verify(FieldElement verifying_key, FieldElement hash) { + return StarknetInterop.Verify(new CString(verifying_key.Hex()), new CString(hash.Hex()), new CString(R().Hex()), new CString(S().Hex())); + } +#else + // dojo.c starknet-rs bindings + public bool Verify(FieldElement verifying_key, FieldElement hash) + { + var result = dojo.verifying_key_verify(verifying_key.Inner, hash.Inner, Inner); + if (result.tag == dojo.Resultbool_Tag.Errbool) + { + throw new System.Exception(result.err.message); + } + + return result.ok; + } +#endif + + public bool Verify(VerifyingKey verifying_key, FieldElement hash) + { + return Verify(verifying_key.Inner, hash); + } + + // Return the signature as a compact hex string. + public string ToCompactHex() + { + return (R().Hex() + S().Hex()).Replace("0x", ""); + } + + // Return the felts of the signature. + public FieldElement[] ToFeltArray() + { + return new FieldElement[] { R(), S() }; + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/Signature.cs.meta b/Assets/Dojo/Runtime/Starknet/Signature.cs.meta new file mode 100644 index 00000000..9548525b --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/Signature.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6317a7230ff264528b75cc5ba09477d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/SigningKey.cs b/Assets/Dojo/Runtime/Starknet/SigningKey.cs new file mode 100644 index 00000000..ecac3326 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/SigningKey.cs @@ -0,0 +1,73 @@ +using System; +using bottlenoselabs.C2CS.Runtime; +using dojo_bindings; +using JetBrains.Annotations; + +namespace Dojo.Starknet +{ + public class SigningKey + { + // The inner FieldElement for the private key. + public FieldElement Inner + { + get; + } + // Return the public key corresponding to the private key. + public VerifyingKey PublicKey + { + get + { +#if UNITY_WEBGL && !UNITY_EDITOR + return new VerifyingKey(StarknetInterop.NewVerifyingKey(new CString(Inner.Hex()))); +#else + return new VerifyingKey(dojo.verifying_key_new(Inner.Inner)); +#endif + } + } + + public SigningKey() + { +#if UNITY_WEBGL && !UNITY_EDITOR + Inner = new FieldElement(StarknetInterop.NewSigningKey()); +#else + Inner = new FieldElement(dojo.signing_key_new()); +#endif + } + + public SigningKey(string privateKey) + { + Inner = new FieldElement(privateKey); + } + + public SigningKey(dojo.FieldElement privateKey) + { + Inner = new FieldElement(privateKey); + } + + public SigningKey(FieldElement privateKey) + { + Inner = privateKey; + } + + // Sign a message. +#if UNITY_WEBGL && !UNITY_EDITOR + // webgl js interop starknet bindings + public Signature Sign(FieldElement message) + { + var signature = StarknetInterop.Sign(new CString(Inner.Hex()), new CString(message.Hex())); + return new Signature(signature); + } +#else + public Signature Sign(FieldElement message) + { + var result = dojo.signing_key_sign(Inner.Inner, message.Inner); + if (result.tag == dojo.ResultSignature_Tag.ErrSignature) + { + throw new Exception(result.err.message); + } + + return new Signature(result.ok); + } +#endif + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/SigningKey.cs.meta b/Assets/Dojo/Runtime/Starknet/SigningKey.cs.meta new file mode 100644 index 00000000..a4cacb55 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/SigningKey.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 88058aa4528240fd9e7b71055a5abd7d +timeCreated: 1702074662 \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/StarknetInterop.cs b/Assets/Dojo/Runtime/Starknet/StarknetInterop.cs new file mode 100644 index 00000000..ba4fdd33 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/StarknetInterop.cs @@ -0,0 +1,240 @@ +using System; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using AOT; +using bottlenoselabs.C2CS.Runtime; +using Newtonsoft.Json; +using Debug = UnityEngine.Debug; +using dojo_bindings; +using System.Text.RegularExpressions; + +namespace Dojo.Starknet +{ + public class StarknetInterop + { + [DllImport("__Internal")] + public static extern IntPtr NewProvider(CString nodeUrl); + + [DllImport("__Internal")] + public static extern IntPtr NewAccount(IntPtr provider, CString privateKey, CString address, Action cb); + + public class NewAccountHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(IntPtr result) + { + Tcs.SetResult(result); + } + } + + public static Task NewAccountAsync(IntPtr provider, SigningKey privateKey, FieldElement address) + { + NewAccountHelper.Tcs = new TaskCompletionSource(); + NewAccount(provider, new CString(privateKey.Inner.Hex()), new CString(address.Hex()), NewAccountHelper.Callback); + return NewAccountHelper.Tcs.Task; + } + + [DllImport("__Internal")] + public static extern string AccountAddress(IntPtr account); + + [DllImport("__Internal")] + public static extern string AccountChainId(IntPtr account); + + [DllImport("__Internal")] + public static extern void AccountNonce(IntPtr account, Action cb); + + public class AccountNonceHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(string result) + { + Tcs.SetResult(new FieldElement(result)); + } + } + + public static Task AccountNonceAsync(IntPtr account) + { + AccountNonceHelper.Tcs = new TaskCompletionSource(); + AccountNonce(account, AccountNonceHelper.Callback); + return AccountNonceHelper.Tcs.Task; + } + + [DllImport("__Internal")] + public static extern void AccountExecuteRaw(IntPtr account, CString calls, Action cb); + + public class AccountExecuteRawHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(string result) + { + Tcs.SetResult(new FieldElement(result)); + } + } + + struct SerializedCall + { + public SerializedCall(FieldElement to, string selector, FieldElement[] calldata) + { + this.to = to.Hex(); + this.selector = selector; + this.calldata = calldata.Select(f => f.Hex()).ToArray(); + } + + // hex string of address + public string to; + // the unhashed selector + public string selector; + // array of hex strings + public string[] calldata; + } + + class SerializedBlockId + { + public static object Serialize(dojo.BlockId blockId) + { + return blockId.tag switch + { + dojo.BlockId_Tag.Hash => new BlockIdHash { Hash = new FieldElement(blockId.hash).Hex() }, + dojo.BlockId_Tag.Number => new BlockIdNumber { Number = blockId.number.ToString() }, + dojo.BlockId_Tag.BlockTag_ => new BlockIdTag + { + BlockTag = blockId.block_tag switch + { + dojo.BlockTag.Latest => "Latest", + dojo.BlockTag.Pending => "Pending", + _ => throw new Exception("Unknown block tag") + } + }, + _ => throw new Exception("Unknown block id type") + }; + } + + public struct BlockIdHash + { + public string Hash; + } + + public struct BlockIdNumber + { + public string Number; + } + + public struct BlockIdTag + { + public string BlockTag; + } + } + + public static Task AccountExecuteRawAsync(IntPtr account, dojo.Call[] calls) + { + AccountExecuteRawHelper.Tcs = new TaskCompletionSource(); + AccountExecuteRaw(account, new CString(JsonConvert.SerializeObject(calls.Select(call => new SerializedCall(new FieldElement(call.to), call.selector, call.calldata.ToArray().Select(f => new FieldElement(f)).ToArray())).ToArray())), AccountExecuteRawHelper.Callback); + return AccountExecuteRawHelper.Tcs.Task; + } + + [DllImport("__Internal")] + public static extern void AccountDeployBurner(IntPtr account, CString privateKey, Action cb); + + public class AccountDeployBurnerHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(IntPtr result) + { + Tcs.SetResult(result); + } + } + + public static Task AccountDeployBurnerAsync(IntPtr account, SigningKey signingKey) + { + AccountDeployBurnerHelper.Tcs = new TaskCompletionSource(); + AccountDeployBurner(account, new CString(signingKey.Inner.Hex()), AccountDeployBurnerHelper.Callback); + return AccountDeployBurnerHelper.Tcs.Task; + } + + [DllImport("__Internal")] + public static extern void Call(IntPtr provider, CString call, CString blockId, Action cb); + + public class CallHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(string result) + { + Tcs.SetResult(JsonConvert.DeserializeObject(result).Select(f => new FieldElement(f)).ToArray()); + } + } + + public static Task CallAsync(IntPtr provider, dojo.Call call, dojo.BlockId blockId) + { + WaitForTransactionHelper.Tcs = new TaskCompletionSource(); + var serializedCall = new SerializedCall(new FieldElement(call.to), call.selector, call.calldata.ToArray().Select(f => new FieldElement(f)).ToArray()); + object serializedBlockId = SerializedBlockId.Serialize(blockId); + + Call(provider, new CString(JsonConvert.SerializeObject(serializedCall)), new CString(JsonConvert.SerializeObject(serializedBlockId)), CallHelper.Callback); + return CallHelper.Tcs.Task; + } + + [DllImport("__Internal")] + public static extern void WaitForTransaction(IntPtr provider, CString transactionHash, Action cb); + + public class WaitForTransactionHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(bool result) + { + Tcs.SetResult(result); + } + } + + public static Task WaitForTransactionAsync(IntPtr provider, FieldElement transactionHash) + { + WaitForTransactionHelper.Tcs = new TaskCompletionSource(); + WaitForTransaction(provider, new CString(transactionHash.Hex()), WaitForTransactionHelper.Callback); + return WaitForTransactionHelper.Tcs.Task; + } + + [DllImport("__Internal")] + public static extern string NewSigningKey(); + + [DllImport("__Internal")] + public static extern string Sign(CString privateKey, CString hash); + + [DllImport("__Internal")] + public static extern string NewVerifyingKey(CString privateKey); + + [DllImport("__Internal")] + public static extern bool Verify(CString publicKey, CString hash, CString r, CString s); + + [DllImport("__Internal")] + private static extern string SerializeByteArray(CString byteArray); + + public static FieldElement[] SerializeByteArray(string byteArray) + { + return JsonConvert.DeserializeObject(SerializeByteArray(new CString(byteArray))).Select(f => new FieldElement(f)).ToArray(); + } + + [DllImport("__Internal")] + private static extern string DeserializeByteArray(CString felts); + + public static string DeserializeByteArray(FieldElement[] felts) + { + return DeserializeByteArray(new CString(JsonConvert.SerializeObject(felts.Select(f => f.Hex()).ToArray()))); + } + + [DllImport("__Internal")] + public static extern string PoseidonHash(CString str); + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/StarknetInterop.cs.meta b/Assets/Dojo/Runtime/Starknet/StarknetInterop.cs.meta new file mode 100644 index 00000000..78881954 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/StarknetInterop.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc69fa48bde9d444689116dff1193482 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/TypedData.cs b/Assets/Dojo/Runtime/Starknet/TypedData.cs new file mode 100644 index 00000000..36756a1f --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/TypedData.cs @@ -0,0 +1,290 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Reflection; +using bottlenoselabs.C2CS.Runtime; +using Dojo.Torii; +using dojo_bindings; +using Newtonsoft.Json; + +namespace Dojo.Starknet +{ + public class Domain + { + public string name; + public string version; + public string chainId; + public string revision = "1"; + + public Domain(string name, string version, string chainId) + { + this.name = name; + this.version = version; + this.chainId = chainId; + } + } + + public class TypedData + { + public Dictionary types; + public string primaryType; + public Domain domain; + public Dictionary message; + + public TypedData(Dictionary types, string primaryType, Domain domain, Dictionary message) + { + this.types = types; + this.primaryType = primaryType; + this.domain = domain; + this.message = message; + } + + public struct TypedDataType + { + public string name; + public string type; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string contains; + + public TypedDataType(string name, string type, string contains = null) + { + this.name = name; + this.type = type; + this.contains = contains; + } + } + + public TypedData(Model model) + { + types = new Dictionary + { + // starknet domain type + { + "StarknetDomain", + new TypedDataType[] { + new TypedDataType("name", "shortstring"), + new TypedDataType("version", "shortstring"), + new TypedDataType("chainId", "shortstring"), + new TypedDataType("revision", "shortstring") + } + }, + // primary type + { + "OffchainMessage", + new TypedDataType[] { + // model name + new TypedDataType("model", "shortstring"), + // model type + new TypedDataType(model.Name, "Model") + } + } + }; + + // model members types + types.Add("Model", getMembersTypes(ref types, model.Members)); + + primaryType = "OffchainMessage"; + + // wip + domain = new Domain("Dojo", "1", "1"); + message = new Dictionary + { + // model name + { "model", model.Name } + }; + + // model members + var members = new Dictionary(); + foreach (var member in model.Members) + { + members.Add(member.Key, mapMember(member.Value)); + } + + message.Add(model.Name, members); + } + + object mapMember(object member) + { + return member switch + { + Model.Enum enum_ => new Dictionary + { + { enum_.option, mapMember(enum_.value) } + }, + Model.Struct struct_ => struct_.members.Select(child => new KeyValuePair(child.Key, mapMember(child.Value))).ToDictionary(k => k.Key, v => v.Value), + object[] tuple => tuple.Select(mapMember).ToArray(), + List array => array.Select(mapMember).ToList(), + _ => member + }; + } + + TypedDataType[] getMembersTypes(ref Dictionary types, Dictionary members) + { + var result = new List(); + + foreach (var member in members) + { + switch (member.Value) + { + case string _: + result.Add(new TypedDataType(member.Key, "string")); + break; + case FieldElement _: + result.Add(new TypedDataType(member.Key, "felt")); + break; + case byte: + result.Add(new TypedDataType(member.Key, "u8")); + break; + case ushort: + result.Add(new TypedDataType(member.Key, "u16")); + break; + case uint: + result.Add(new TypedDataType(member.Key, "u32")); + break; + case ulong: + result.Add(new TypedDataType(member.Key, "u64")); + break; + case BigInteger: + result.Add(new TypedDataType(member.Key, "u128")); + break; + case bool: + result.Add(new TypedDataType(member.Key, "bool")); + break; + // Enum + // (variantName, variantValue) + case Model.Enum enum_: + var enumMembers = getMembersTypes(ref types, new Dictionary + { + // for now we only include our selected option + // and its value + { enum_.option, enum_.value }, + // TOOD: maybe include all other enum options + // and their types? + }); + types.TryAdd(enum_.name, enumMembers); + result.Add(new TypedDataType(member.Key, "enum", enum_.name)); + break; + case Model.Struct struct_: + var structMembers = getMembersTypes(ref types, struct_.members); + // add the struct members to the types. it might already be added from + // other members + types.TryAdd(struct_.name, structMembers); + result.Add(new TypedDataType(member.Key, struct_.name)); + break; + // tuples are arrays + case object[] tuple: + var tupleMembers = tuple.Select((v, i) => new KeyValuePair(i.ToString(), v)).ToDictionary(k => k.Key, v => v.Value); + var tupleMembersTypes = getMembersTypes(ref types, tupleMembers); + var formattedTupleName = $"({string.Join(",", tupleMembersTypes.Select(t => t.type))})"; + + result.Add(new TypedDataType(member.Key, formattedTupleName)); + break; + // should be encoded as TypeObject* for arrays + case List array: + TypedDataType inner = getMembersTypes(ref types, new Dictionary + { + { "inner", array[0] } + }).First(); + + result.Add(new TypedDataType(member.Key, $"{inner.type}*")); + break; + } + + } + + return result.ToArray(); + } + + public FieldElement encode(FieldElement address) + { +#if UNITY_WEBGL && !UNITY_EDITOR + return new FieldElement(ToriiWasmInterop.EncodeTypedData(new CString(JsonConvert.SerializeObject(this)), new CString(address.Hex()))); +#else + var result = dojo.typed_data_encode(new CString(JsonConvert.SerializeObject(this)), address.Inner); + if (result.tag == dojo.ResultFieldElement_Tag.ErrFieldElement) + { + throw new System.Exception(result.err.message); + } + + return new FieldElement(result.ok); +#endif + } + + static object mapModelInstanceMember(object member) { + var type = member.GetType(); + + // enums + if (member is Enum) { + object value; + if (type.GetProperty("value") is PropertyInfo prop) { + value = prop.GetValue(member); + } else { + value = ValueTuple.Create(); + } + + // format name to include generic types, like Option + var name = type.BaseType.Name.Split('`')[0]; + if (type.GenericTypeArguments.Length > 0) { + name += "<" + string.Join(",", type.GenericTypeArguments.Select(t => t.Name)) + ">"; + } + + return new Model.Enum(name, type.Name, mapModelInstanceMember(value)); + // tuple -> array + } else if (type.FullName.StartsWith(typeof(ValueTuple).FullName)) { + // get all fields of the tuple + // and cast them to object[] array + var fields = type.GetFields(); + var values = new object[fields.Length]; + for (var i = 0; i < fields.Length; i++) { + values[i] = mapModelInstanceMember(fields[i].GetValue(member)); + } + + return values; + } + // array -> List + else if (type.IsArray) { + var array = (Array)member; + var list = new List(); + for (var i = 0; i < array.Length; i++) { + list.Add(mapModelInstanceMember(array.GetValue(i))); + } + + return list; + } + // struct + else if (type.IsValueType && !type.IsPrimitive && !type.IsEnum) { + var fields = type.GetFields(); + var dict = new Dictionary(); + foreach (var field in fields) { + dict.Add(field.Name, mapModelInstanceMember(field.GetValue(member))); + } + + return new Model.Struct(type.Name, dict); + } + + return member; + } + + public static TypedData From(T model) where T : ModelInstance + { + var fields = model.GetType().GetFields(); + var members = new Dictionary(); + + // map all fields of the model instance + foreach (var field in fields) { + // Check if the field has the ModelField attribute + var attribute = field.GetCustomAttributes(typeof(ModelField), false); + if (attribute.Length == 0) + { + continue; + } + + var modelField = (ModelField)attribute[0]; + members.Add(modelField.Name, mapModelInstanceMember(field.GetValue(model))); + } + + return new TypedData(new Model(model.GetType().Name, members)); + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/TypedData.cs.meta b/Assets/Dojo/Runtime/Starknet/TypedData.cs.meta new file mode 100644 index 00000000..fc8a8a73 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/TypedData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45ec95435755c406d879713a5daf9a06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Starknet/VerifyingKey.cs b/Assets/Dojo/Runtime/Starknet/VerifyingKey.cs new file mode 100644 index 00000000..649b4eef --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/VerifyingKey.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using bottlenoselabs.C2CS.Runtime; +using dojo_bindings; +using Newtonsoft.Json; +using Debug = UnityEngine.Debug; + +namespace Dojo.Starknet +{ + // Wraps a FieldElement and provides helper methods for verifying signatures. + public class VerifyingKey + { + public FieldElement Inner { get; } + + public VerifyingKey(string publicKey) + { + Inner = new FieldElement(publicKey); + } + + public VerifyingKey(dojo.FieldElement publicKey) + { + Inner = new FieldElement(publicKey); + } + + public VerifyingKey(FieldElement publicKey) + { + Inner = publicKey; + } + +#if UNITY_WEBGL && !UNITY_EDITOR + // webgl js interop starknet bindings + public bool Verify(FieldElement message, Signature signature) + { + return StarknetInterop.Verify(new CString(Inner.Hex()), new CString(message.Hex()), new CString(signature.R().Hex()), new CString(signature.S().Hex())); + } +#else + // dojo.c starknet-rs bindings + public bool Verify(FieldElement message, Signature signature) + { + var result = dojo.verifying_key_verify(Inner.Inner, message.Inner, signature.Inner); + if (result.tag == dojo.Resultbool_Tag.Errbool) + { + throw new Exception(result.err.message); + } + + return result.ok; + } +#endif + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Starknet/VerifyingKey.cs.meta b/Assets/Dojo/Runtime/Starknet/VerifyingKey.cs.meta new file mode 100644 index 00000000..48306a44 --- /dev/null +++ b/Assets/Dojo/Runtime/Starknet/VerifyingKey.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 4cdb96afefa244b29fd978135ac2949d +timeCreated: 1702074930 \ No newline at end of file diff --git a/Assets/Dojo/Runtime/SynchronizationMaster.cs b/Assets/Dojo/Runtime/SynchronizationMaster.cs new file mode 100644 index 00000000..925e1bea --- /dev/null +++ b/Assets/Dojo/Runtime/SynchronizationMaster.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Dojo.Starknet; +using Dojo.Torii; +using dojo_bindings; +using Newtonsoft.Json; +using UnityEngine; +using UnityEngine.Events; + +namespace Dojo +{ + public class SynchronizationMaster : MonoBehaviour + { + public WorldManager worldManager; + + // Maximum number of entities to synchronize + public uint limit = 100; + + // Handle entities that get synchronized + private ModelInstance[] _models; + // Returns all of the model definitions + private ModelInstance[] models => _models ??= LoadModels(); + + public UnityEvent> OnSynchronized; + public UnityEvent OnEntitySpawned; + public UnityEvent OnEventMessage; + + // Awake is called when the script instance is being loaded. + void Awake() + { + // We don't want our model definitions to be active. + // Only used as templates for the actual entities to use. + foreach (var model in models) + { + model.enabled = false; + } + } + + // Fetch all entities from the dojo world and spawn them. + public async Task SynchronizeEntities() + { +#if UNITY_WEBGL && !UNITY_EDITOR + var entities = await worldManager.wasmClient.Entities(worldManager.dojoConfig.query); +#else + var entities = await Task.Run(() => worldManager.toriiClient.Entities(worldManager.dojoConfig.query)); +#endif + + var entityGameObjects = new List(); + foreach (var entity in entities) + { + entityGameObjects.Add(SpawnEntity(entity.HashedKeys, entity.Models.Values.ToArray())); + } + + OnSynchronized?.Invoke(entityGameObjects); + return entities.Count; + } + + // Spawn an Entity game object from a dojo.Entity + private GameObject SpawnEntity(FieldElement hashedKeys, Model[] entityModels) + { + // Add the entity to the world. + var entityGameObject = worldManager.AddEntity(hashedKeys.Hex()); + // Initialize each one of the entity models + foreach (var entityModel in entityModels) + { + string[] parts = entityModel.Name.Split('-'); + string @namespace = parts[0]; + string name = parts[1]; + + // Check if we have a model definition for this entity model + var model = models.FirstOrDefault(m => m.GetType().Name == $"{@namespace}_{name}"); + if (model == null) + { + Debug.LogWarning($"Model {entityModel.Name} not found"); + continue; + } + + // Add the model component to the entity + var component = (ModelInstance)entityGameObject.AddComponent(model.GetType()); + component.Initialize(entityModel); + } + + OnEntitySpawned?.Invoke(entityGameObject); + return entityGameObject; + } + + // Handles spawning / updating entities as they are updated from the dojo world + private void HandleEntityUpdate(FieldElement hashedKeys, Model[] entityModels) + { + // Get the entity game object + var entity = GameObject.Find(hashedKeys.Hex()); + if (entity == null) + { + entity = SpawnEntity(hashedKeys, entityModels); + // We don't need to update the entity models + return; + } + + // Update each one of the entity models + foreach (var entityModel in entityModels) + { + string[] parts = entityModel.Name.Split('-'); + string @namespace = parts[0]; + string name = parts[1]; + + var component = entity.GetComponent(name); + if (component == null) + { + // TODO: decouple? + var model = models.FirstOrDefault(m => m.GetType().Name == $"{@namespace}_{name}"); + if (model == null) + { + Debug.LogWarning($"Model {entityModel.Name} not found"); + continue; + } + + // we dont need to initialize the component + // because it'll get updated + component = (ModelInstance)entity.AddComponent(model.GetType()); + } + + // update component with new model data + ((ModelInstance)component).OnUpdate(entityModel); + } + } + + private void HandleEventMessage(FieldElement hashedKeys, Model[] entityModels) + { + foreach (var entityModel in entityModels) + { + var model = models.FirstOrDefault(m => m.GetType().Name == entityModel.Name); + if (model == null) + { + Debug.LogWarning($"Model {entityModel.Name} not found"); + continue; + } + + model.OnUpdate(entityModel); + OnEventMessage?.Invoke(model); + } + } + + // Register our entity callbacks + public void RegisterEntityCallbacks() + { + ToriiEvents.Instance.OnEntityUpdated += HandleEntityUpdate; + } + + // Register event message callbacks + public void RegisterEventMessageCallbacks() + { + ToriiEvents.Instance.OnEventMessageUpdated += HandleEventMessage; + } + + private ModelInstance[] LoadModels() + { + List models = new(); + + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + foreach (Assembly assembly in assemblies) + { + var modelTypes = assembly.GetTypes() + .Where(t => typeof(ModelInstance).IsAssignableFrom(t) && !t.IsAbstract); + + foreach (Type modelType in modelTypes) + { + models.Add((ModelInstance)gameObject.AddComponent(modelType)); + } + } + + return models.ToArray(); + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/SynchronizationMaster.cs.meta b/Assets/Dojo/Runtime/SynchronizationMaster.cs.meta new file mode 100644 index 00000000..bcb73c0a --- /dev/null +++ b/Assets/Dojo/Runtime/SynchronizationMaster.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 03336b1725e0144688810398fccab79e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Torii.meta b/Assets/Dojo/Runtime/Torii.meta new file mode 100644 index 00000000..0ed1002d --- /dev/null +++ b/Assets/Dojo/Runtime/Torii.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 170ffd1e7df754c8782b5ee1790e9bb2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Torii/Entity.cs b/Assets/Dojo/Runtime/Torii/Entity.cs new file mode 100644 index 00000000..dfad17f3 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/Entity.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Dojo.Starknet; +using dojo_bindings; + +namespace Dojo.Torii +{ + // A managed type for Entity + // Frees the underlying dojo.Entity when the object is garbage collected + public class Entity + { + public Dictionary Models { get; } + public FieldElement HashedKeys { get; } + public Entity(FieldElement hashedKeys, Dictionary models) + { + HashedKeys = hashedKeys; + Models = models; + } + + public Entity(dojo.Entity entity) + { + HashedKeys = new FieldElement(entity.hashed_keys); + Models = new Dictionary(entity.models.ToArray().Select(m => new KeyValuePair(m.name, new Model(m)))); + + } + + // freeing the entity is naive. if we copy the entity we will double free + // and seg fault. + // ~Entity() + // { + // dojo.entity_free(_entity); + // } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/Entity.cs.meta b/Assets/Dojo/Runtime/Torii/Entity.cs.meta new file mode 100644 index 00000000..22e7338b --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/Entity.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ab298086a6634622993040ba33b87937 +timeCreated: 1701892820 \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/Model.cs b/Assets/Dojo/Runtime/Torii/Model.cs new file mode 100644 index 00000000..cf8081e2 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/Model.cs @@ -0,0 +1,223 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Runtime.InteropServices; +using Dojo.Starknet; +using dojo_bindings; +using JetBrains.Annotations; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using UnityEngine; + +namespace Dojo.Torii +{ + public class Model + { + public struct Enum + { + public string name; + public string option; + public object value; + + public Enum(string name, string option, object value) + { + this.name = name; + this.option = option; + this.value = value; + } + } + + public struct Struct + { + public string name; + public Dictionary members; + + public Struct(string name, Dictionary members) + { + this.name = name; + this.members = members; + } + } + + public string Name { get; } + public Dictionary Members { get; } + + public Model(string name, Dictionary members) + { + Name = name; + + Members = members.ToDictionary(k => k.Key, v => HandleWasmValue(v.Value)); + } + + public Model(string name, Dictionary members) + { + Name = name; + Members = members; + } + + public Model(dojo.Struct model) + { + Name = model.name; + Members = new Dictionary(model.children.ToArray().Select(m => new KeyValuePair(m.name, HandleCValue(m.ty)))); + } + + private object HandleCValue(dojo.Ty ty) + { + return ty.tag switch + { + dojo.Ty_Tag.Struct_ => HandleCStruct(ty.struct_), + dojo.Ty_Tag.Enum_ => HandleCEnum(ty.enum_), + dojo.Ty_Tag.Tuple_ => ty.tuple.ToArray().Select(m => HandleCValue(m)).ToArray(), + dojo.Ty_Tag.Array_ => ty.array.ToArray().Select(m => HandleCValue(m)).ToList(), + dojo.Ty_Tag.Primitive_ => ty.primitive.tag switch + { + dojo.Primitive_Tag.Bool => Convert.ToBoolean(ty.primitive.bool_.Value), + dojo.Primitive_Tag.I8 => ty.primitive.i8, + dojo.Primitive_Tag.I16 => ty.primitive.i16, + dojo.Primitive_Tag.I32 => ty.primitive.i32, + dojo.Primitive_Tag.I64 => ty.primitive.i64, + dojo.Primitive_Tag.I128 => ConvertTwosComplementToBigInteger(ty.primitive.i128.ToArray()), + dojo.Primitive_Tag.U8 => ty.primitive.u8, + dojo.Primitive_Tag.U16 => ty.primitive.u16, + dojo.Primitive_Tag.U32 => ty.primitive.u32, + dojo.Primitive_Tag.U64 => ty.primitive.u64, + dojo.Primitive_Tag.U128 => ConvertTwosComplementToBigInteger(ty.primitive.u128.ToArray()), + dojo.Primitive_Tag.U256 => new Struct("U256", new Dictionary(){ + {"high", new BigInteger(MemoryMarshal.Cast(ty.primitive.u256).Slice(16, 16).ToArray())}, + {"low", new BigInteger(MemoryMarshal.Cast(ty.primitive.u256).Slice(0, 16).ToArray())} + }), + dojo.Primitive_Tag.USize => ty.primitive.u_size, + dojo.Primitive_Tag.Felt252 => new FieldElement(ty.primitive.felt252), + dojo.Primitive_Tag.ClassHash => new FieldElement(ty.primitive.class_hash), + dojo.Primitive_Tag.ContractAddress => new FieldElement(ty.primitive.contract_address), + _ => throw new Exception("Unknown primitive type: " + ty.primitive.tag) + }, + dojo.Ty_Tag.ByteArray => ty.byte_array, + _ => throw new Exception("Unknown type: " + ty.tag) + }; + } + + private object HandleWasmValue(WasmValue value) + { + Debug.Log($"value: {JsonConvert.SerializeObject(value)}"); + return value.type switch + { + // struct + "struct" => HandleJSStruct(value.type_name, value.value.ToObject>()), + // enum + "enum" => HandleJSEnum(value.type_name, value.value.ToObject()), + // tuple + "tuple" => value.value.ToObject().Select(m => HandleWasmValue(m.ToObject())).ToArray(), + // array + "array" => value.value.ToObject().Select(m => HandleWasmValue(m.ToObject())).ToList(), + "bytearray" => value.value.ToObject(), + "primitive" => value.type_name switch + { + // primitives + "bool" => value.value.ToObject(), + "i8" => value.value.ToObject(), + "i16" => value.value.ToObject(), + "i32" => value.value.ToObject(), + "i64" => ConvertTwosComplementToLong(hexStringToByteArray(value.value.ToObject())), + "i128" => ConvertTwosComplementToBigInteger(hexStringToByteArray(value.value.ToObject())), + "u8" => value.value.ToObject(), + "u16" => value.value.ToObject(), + "u32" => value.value.ToObject(), + "u64" => (long)new BigInteger(hexStringToByteArray(value.value.ToObject()).Reverse().ToArray()), + // NOTE: UNTESTED + // NOTE: slow? + // use BigInteger parse instead maybe but seems a bit + // uninconvenient to use + "u128" => new BigInteger(hexStringToByteArray(value.value.ToObject()).Reverse().ToArray()), + // convert a 64 character hex string to a BigInteger + // IMPLEMNET + "u256" => new Struct("U256", new Dictionary(){ + {"high", new BigInteger(hexStringToByteArray(value.value.ToObject().Substring(2, 32)).Reverse().ToArray())}, + {"low", new BigInteger(hexStringToByteArray(value.value.ToObject().Substring(34, 32)).Reverse().ToArray())} + }), + "usize" => value.value.ToObject(), + // these should be fine + "Felt252" => new FieldElement(value.value.ToObject()), + "ClassHash" => new FieldElement(value.value.ToObject()), + "ContractAddress" => new FieldElement(value.value.ToObject()), + _ => throw new Exception("Unknown primitive type: " + value.type_name) + }, + _ => throw new Exception("Unknown type: " + value.type) + }; + } + + private byte[] hexStringToByteArray(string hex) + { + // Remove "0x" prefix if present + hex = hex.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? hex[2..] : hex; + + // Ensure even number of characters + if (hex.Length % 2 != 0) + hex = "0" + hex; + + byte[] bytes = new byte[hex.Length / 2]; + + for (int i = 0; i < bytes.Length; i++) + { + string byteValue = hex.Substring(i * 2, 2); + bytes[i] = Convert.ToByte(byteValue, 16); + } + + return bytes; + } + + private Struct HandleCStruct(dojo.Struct str) + { + return new Struct(str.name, str.children.ToArray().Select(m => new KeyValuePair(m.name, HandleCValue(m.ty))).ToDictionary(k => k.Key, v => v.Value)); + } + + private Enum HandleCEnum(dojo.Enum en) + { + var option = en.options[en.option]; + + // maybe we should inherit the key? + return new Enum(en.name, option.name, HandleCValue(option.ty)); + } + + private Struct HandleJSStruct(string name, Dictionary str) + { + return new Struct(name, str.Select(m => new KeyValuePair(m.Key, HandleWasmValue(m.Value))).ToDictionary(k => k.Key, v => v.Value)); + } + + private Enum HandleJSEnum(string name, WasmEnum en) + { + return new Enum(name, en.option, HandleWasmValue(en.value)); + } + + private long ConvertTwosComplementToLong(byte[] bytes) + { + var reversed = bytes.Reverse().ToArray(); + var unsigned = new BigInteger(reversed); + + // Check if the highest bit is set (negative number) + if ((unsigned & (BigInteger.One << 63)) != 0) + { + // Convert from two's complement + unsigned -= BigInteger.One << 64; + } + + return (long)unsigned; + } + + private BigInteger ConvertTwosComplementToBigInteger(byte[] bytes) + { + var reversed = bytes.Reverse().ToArray(); + var unsigned = new BigInteger(reversed); + + // Check if the highest bit is set (negative number) + if ((unsigned & (BigInteger.One << 127)) != 0) + { + // Convert from two's complement + unsigned -= BigInteger.One << 128; + } + + return unsigned; + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/Model.cs.meta b/Assets/Dojo/Runtime/Torii/Model.cs.meta new file mode 100644 index 00000000..10b91faa --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/Model.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b814f37e245f449f98116f60af089fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Torii/Query.cs b/Assets/Dojo/Runtime/Torii/Query.cs new file mode 100644 index 00000000..06925076 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/Query.cs @@ -0,0 +1,303 @@ +using System; +using System.Linq; +using bottlenoselabs.C2CS.Runtime; +using Dojo.Starknet; +using dojo_bindings; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using UnityEngine; + +namespace Dojo.Torii +{ +#nullable enable + + [Serializable] + public class Query + { + public uint limit; + public uint offset; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public Clause? clause; + public bool dont_include_hashed_keys; + + public Query(uint limit, uint offset, Clause? clause = null, bool dont_include_hashed_keys = false) + { + this.limit = limit; + this.offset = offset; + this.clause = clause; + this.dont_include_hashed_keys = dont_include_hashed_keys; + } + + public dojo.Query ToNative() + { + var nativeQuery = new dojo.Query + { + limit = limit, + offset = offset, + clause = new dojo.COptionClause { tag = dojo.COptionClause_Tag.NoneClause }, + dont_include_hashed_keys = dont_include_hashed_keys + }; + + if (clause.HasValue) + { + nativeQuery.clause = new dojo.COptionClause + { + tag = dojo.COptionClause_Tag.SomeClause, + some = clause.Value.ToNative() + }; + } + + return nativeQuery; + } + } + + [Serializable] + public struct Clause + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public KeysClause? Keys; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public MemberClause? Member; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public CompositeClause? Composite; + + public static implicit operator Clause(KeysClause keysClause) + { + return new Clause { Keys = keysClause }; + } + + public static implicit operator Clause(MemberClause memberClause) + { + return new Clause { Member = memberClause }; + } + + public static implicit operator Clause(CompositeClause compositeClause) + { + return new Clause { Composite = compositeClause }; + } + + public dojo.Clause ToNative() + { + if (Keys.HasValue) + return new dojo.Clause { tag = dojo.Clause_Tag.Keys, keys = Keys.Value.ToNative() }; + if (Member.HasValue) + return new dojo.Clause { tag = dojo.Clause_Tag.CMember, c_member = Member.Value.ToNative() }; + if (Composite.HasValue) + return new dojo.Clause { tag = dojo.Clause_Tag.Composite, composite = Composite.Value.ToNative() }; + + throw new InvalidOperationException("Clause must have one non-null value"); + } + } + + [Serializable] + public struct EntityKeysClause + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public FieldElement[]? HashedKeys; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public KeysClause? Keys; + + public EntityKeysClause(object type) : this() + { + if (type is FieldElement[] hashedKeys) + HashedKeys = hashedKeys; + else if (type is KeysClause keys) + Keys = keys; + else + throw new ArgumentException("Invalid entity keys clause type"); + } + + public dojo.EntityKeysClause ToNative() + { + if (HashedKeys != null) + return new dojo.EntityKeysClause + { + tag = dojo.EntityKeysClause_Tag.HashedKeys, + hashed_keys = HashedKeys.Select(k => k.Inner).ToArray() + }; + if (Keys.HasValue) + return new dojo.EntityKeysClause + { + tag = dojo.EntityKeysClause_Tag.EntityKeys, + entity_keys = Keys.Value.ToNative() + }; + + throw new InvalidOperationException("EntityKeysClause must have one non-null value"); + } + } + + [Serializable] + public struct KeysClause + { + public FieldElement?[] keys; + [JsonConverter(typeof(StringEnumConverter))] + public dojo.PatternMatching pattern_matching; + public string[] models; + + public KeysClause(FieldElement?[] keys, dojo.PatternMatching pattern_matching, string[] models) + { + this.keys = keys; + this.pattern_matching = pattern_matching; + this.models = models; + } + + public dojo.KeysClause ToNative() + { + return new dojo.KeysClause + { + keys = keys.Select(k => k is null ? + new dojo.COptionFieldElement { tag = dojo.COptionFieldElement_Tag.NoneFieldElement } + : new dojo.COptionFieldElement { tag = dojo.COptionFieldElement_Tag.SomeFieldElement, some = k.Inner }).ToArray(), + pattern_matching = pattern_matching, + models = models + }; + } + } + + [Serializable] + public struct MemberClause + { + public string model; + public string member; + [JsonConverter(typeof(StringEnumConverter))] + public dojo.ComparisonOperator @operator; + public MemberValue value; + + public MemberClause(string model, string member, dojo.ComparisonOperator @operator, MemberValue value) + { + this.model = model; + this.member = member; + this.@operator = @operator; + this.value = value; + } + + public dojo.MemberClause ToNative() + { + return new dojo.MemberClause + { + model = model, + member = member, + operator_ = @operator, + value = value.ToNative() + }; + } + } + + [Serializable] + public struct CompositeClause + { + [JsonConverter(typeof(StringEnumConverter))] + public dojo.LogicalOperator @operator; + public Clause[] clauses; + + public CompositeClause(dojo.LogicalOperator @operator, Clause[] clauses) + { + this.@operator = @operator; + this.clauses = clauses; + } + + public dojo.CompositeClause ToNative() + { + return new dojo.CompositeClause + { + operator_ = @operator, + clauses = clauses.Select(c => c.ToNative()).ToArray() + }; + } + } + + + [Serializable] + public struct MemberValue + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string? String; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public Primitive? Primitive; + + public dojo.MemberValue ToNative() + { + if (String != null) + return new dojo.MemberValue { tag = dojo.MemberValue_Tag.String, @string = String }; + if (Primitive.HasValue) + return new dojo.MemberValue { tag = dojo.MemberValue_Tag.Primitive, primitive = Primitive.Value.ToNative() }; + + throw new InvalidOperationException("MemberValue must have one non-null value"); + } + } + + [Serializable] + public struct Primitive + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public sbyte? I8; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public short? I16; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int? I32; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public long? I64; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public FieldElement? I128; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public byte? U8; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ushort? U16; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public uint? U32; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public ulong? U64; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public FieldElement? U128; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string? U256; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public uint? USize; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public bool? Bool; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public FieldElement? Felt252; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public FieldElement? ClassHash; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public FieldElement? ContractAddress; + + public dojo.Primitive ToNative() + { + if (I8.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.I8, i8 = I8.Value }; + if (I16.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.I16, i16 = I16.Value }; + if (I32.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.I32, i32 = I32.Value }; + if (I64.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.I64, i64 = I64.Value }; + if (I128 != null) + return new dojo.Primitive { tag = dojo.Primitive_Tag.I128, i128 = I128.Inner.data }; + if (U8.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.U8, u8 = U8.Value }; + if (U16.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.U16, u16 = U16.Value }; + if (U32.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.U32, u32 = U32.Value }; + if (U64.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.U64, u64 = U64.Value }; + if (U128 != null) + return new dojo.Primitive { tag = dojo.Primitive_Tag.U128, u128 = U128.Inner.data }; + if (U256 != null) + throw new NotImplementedException("U256 conversion not implemented"); + if (USize.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.USize, u_size = USize.Value }; + if (Bool.HasValue) + return new dojo.Primitive { tag = dojo.Primitive_Tag.Bool, bool_ = Bool.Value }; + if (Felt252 != null) + return new dojo.Primitive { tag = dojo.Primitive_Tag.Felt252, felt252 = Felt252.Inner }; + if (ClassHash != null) + return new dojo.Primitive { tag = dojo.Primitive_Tag.ClassHash, class_hash = ClassHash.Inner }; + if (ContractAddress != null) + return new dojo.Primitive { tag = dojo.Primitive_Tag.ContractAddress, contract_address = ContractAddress.Inner }; + + throw new InvalidOperationException("Primitive must have one non-null value"); + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/Query.cs.meta b/Assets/Dojo/Runtime/Torii/Query.cs.meta new file mode 100644 index 00000000..9637f5e5 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/Query.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5fc551dbdbd6e4edc99d0b5e70f85bd2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Torii/ToriiClient.cs b/Assets/Dojo/Runtime/Torii/ToriiClient.cs new file mode 100644 index 00000000..3792feee --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiClient.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using bottlenoselabs.C2CS.Runtime; +using UnityEngine; +using dojo_bindings; +using Dojo.Starknet; +using Newtonsoft.Json; +using System.Linq; +namespace Dojo.Torii +{ + public unsafe class ToriiClient + { + private dojo.FnPtr_FieldElement_CArrayStruct_Void.@delegate onEntityStateUpdate; + private dojo.FnPtr_FieldElement_CArrayStruct_Void.@delegate onEventMessagesUpdate; + private dojo.ToriiClient* client; + private dojo.Subscription* entitySubscription; + private dojo.Subscription* eventMessagesSubscription; + + public ToriiClient(string toriiUrl, string rpcUrl, string relayUrl, FieldElement worldAddress, bool dispatchEventsToMainThread = true) + { + CString ctoriiUrl = CString.FromString(toriiUrl); + CString crpcUrl = CString.FromString(rpcUrl); + CString crelayUrl = CString.FromString(relayUrl); + + var result = dojo.client_new(ctoriiUrl, crpcUrl, crelayUrl, worldAddress.Inner); + if (result.tag == dojo.ResultToriiClient_Tag.ErrToriiClient) + { + throw new Exception(result.err.message); + } + + client = result._ok; + dojo.client_set_logger(client, new dojo.FnPtr_CString_Void((msg) => Debug.Log(msg))); + + RegisterEntityStateUpdateEvent(new EntityKeysClause[] { }, dispatchEventsToMainThread); + RegisterEventMessageUpdateEvent(new EntityKeysClause[] { }, dispatchEventsToMainThread); + } + + // We assume the torii client won't be copied around. + // So we can free the underlying c client when the managed client is garbage collected. + ~ToriiClient() + { + dojo.subscription_cancel(entitySubscription); + dojo.subscription_cancel(eventMessagesSubscription); + + // dojo.client_free(client); + } + + public dojo.WorldMetadata WorldMetadata() + { + // TODO: implement a managed type for WorldMetadata too + dojo.WorldMetadata worldMetadata = dojo.client_metadata(client); + + return worldMetadata; + } + + // NOT USED? potentially deprecated + // [CanBeNull] + // public Model Model(dojo.KeysClause query) + // { + // dojo.ResultCOptionTy result = dojo.client_model(client, &query); + // if (result.tag == dojo.ResultCOptionTy_Tag.ErrCOptionTy) + // { + // throw new Exception(result.err.message); + // } + + // // can be None - nullable + // if (result.ok.tag == dojo.COptionTy_Tag.NoneTy) + // { + // return null; + // } + + // // we instantiate a new managed Ty object + // // which will free the underlying c ty when it is garbage collected + // return new Ty(result.ok._some.); + // } + + public List Entities(Query query) + { + var nativeQuery = query.ToNative(); + + dojo.ResultCArrayEntity result = dojo.client_entities(client, &nativeQuery); + if (result.tag == dojo.ResultCArrayEntity_Tag.ErrCArrayEntity) + { + throw new Exception(result.err.message); + } + + var entities = new List(); + for (var i = 0; i < (int)result._ok.data_len; i++) + { + entities.Add(new Entity(result._ok.data[i])); + } + + dojo.carray_free(result._ok.data, result._ok.data_len); + return entities; + } + + public List EventMessages(Query query, bool historical = false) + { + var nativeQuery = query.ToNative(); + + dojo.ResultCArrayEntity result = dojo.client_event_messages(client, &nativeQuery, historical); + if (result.tag == dojo.ResultCArrayEntity_Tag.ErrCArrayEntity) + { + throw new Exception(result.err.message); + } + + var entities = new List(); + for (var i = 0; i < (int)result._ok.data_len; i++) + { + entities.Add(new Entity(result._ok.data[i])); + } + + dojo.carray_free(result._ok.data, result._ok.data_len); + return entities; + } + + private void RegisterEntityStateUpdateEvent(EntityKeysClause[] clauses, bool dispatchToMainThread = true) + { + onEntityStateUpdate = (key, models) => + { + var mappedModels = new Model[(int)models.data_len]; + for (var i = 0; i < (int)models.data_len; i++) + { + mappedModels[i] = new Model(models.data[i]); + // cleanup model + // dojo.model_free(&models.data[i]); + } + + // only run this when in unity play mode + // we need our unity main thread dispatcher to run this on the main thread + if (dispatchToMainThread) + { + UnityMainThreadDispatcher.Instance().Enqueue(() => ToriiEvents.Instance.EntityUpdated(new FieldElement(key), mappedModels)); + } + else + { + ToriiEvents.Instance.EntityUpdated(new FieldElement(key), mappedModels); + } + + // cleanup + dojo.carray_free(models.data, models.data_len); + // TODO: free field element + }; + + + dojo.EntityKeysClause* clausesPtr = (dojo.EntityKeysClause*)0; + if (clauses.Length > 0) + { + var mappedClauses = clauses.Select(c => c.ToNative()).ToArray(); + fixed (dojo.EntityKeysClause* ptr = &mappedClauses[0]) + { + clausesPtr = ptr; + } + } + + + dojo.ResultSubscription res = dojo.client_on_entity_state_update(client, clausesPtr, (UIntPtr)clauses.Length, new dojo.FnPtr_FieldElement_CArrayStruct_Void(onEntityStateUpdate)); + if (res.tag == dojo.ResultSubscription_Tag.ErrSubscription) + { + throw new Exception(res.err.message); + } + + entitySubscription = res._ok; + } + + public void UpdateEntitySubscription(EntityKeysClause[] clauses) + { + var mappedClauses = clauses.Select(c => c.ToNative()).ToArray(); + dojo.EntityKeysClause* clausesPtr; + fixed (dojo.EntityKeysClause* ptr = &mappedClauses[0]) + { + clausesPtr = ptr; + } + + dojo.client_update_entity_subscription(client, entitySubscription, clausesPtr, (UIntPtr)clauses.Length); + } + + private void RegisterEventMessageUpdateEvent(EntityKeysClause[] clauses, bool historical = false, bool dispatchToMainThread = true) + { + onEventMessagesUpdate = (key, models) => + { + var mappedModels = new Model[(int)models.data_len]; + for (var i = 0; i < (int)models.data_len; i++) + { + mappedModels[i] = new Model(models.data[i]); + // cleanup model + // dojo.model_free(&models.data[i]); + } + + // only run this when in unity play mode + // we need our unity main thread dispatcher to run this on the main thread + if (dispatchToMainThread) + { + UnityMainThreadDispatcher.Instance().Enqueue(() => ToriiEvents.Instance.EventMessageUpdated(new FieldElement(key), mappedModels)); + } + else + { + ToriiEvents.Instance.EventMessageUpdated(new FieldElement(key), mappedModels); + } + + // cleanup + dojo.carray_free(models.data, models.data_len); + // TODO: free field element + }; + + + dojo.EntityKeysClause* clausesPtr = (dojo.EntityKeysClause*)0; + if (clauses.Length > 0) + { + var mappedClauses = clauses.Select(c => c.ToNative()).ToArray(); + fixed (dojo.EntityKeysClause* ptr = &mappedClauses[0]) + { + clausesPtr = ptr; + } + } + + dojo.ResultSubscription res = dojo.client_on_event_message_update(client, clausesPtr, (UIntPtr)clauses.Length, historical, new dojo.FnPtr_FieldElement_CArrayStruct_Void(onEventMessagesUpdate)); + if (res.tag == dojo.ResultSubscription_Tag.ErrSubscription) + { + throw new Exception(res.err.message); + } + + eventMessagesSubscription = res._ok; + } + + public void UpdateEventMessageSubscription(EntityKeysClause[] clauses, bool historical = false) + { + var mappedClauses = clauses.Select(c => c.ToNative()).ToArray(); + dojo.EntityKeysClause* clausesPtr; + fixed (dojo.EntityKeysClause* ptr = &mappedClauses[0]) + { + clausesPtr = ptr; + } + + dojo.client_update_event_message_subscription(client, eventMessagesSubscription, clausesPtr, (UIntPtr)clauses.Length, historical); + } + + public Span PublishMessage(TypedData typedData, FieldElement[] signature) + { + var mappedSignature = signature.Select(s => s.Inner).ToArray(); + dojo.FieldElement* signaturePtr; + fixed (dojo.FieldElement* ptr = &mappedSignature[0]) + { + signaturePtr = ptr; + } + + var result = dojo.client_publish_message(client, new CString(JsonConvert.SerializeObject(typedData)), signaturePtr, (UIntPtr)signature.Length); + if (result.tag == dojo.ResultCArrayu8_Tag.ErrCArrayu8) + { + throw new Exception(result.err.message); + } + + return result.ok; + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/ToriiClient.cs.meta b/Assets/Dojo/Runtime/Torii/ToriiClient.cs.meta new file mode 100644 index 00000000..0e8f9c95 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91e0e9dc49b4c4e17b4b1197264ed4bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Torii/ToriiEvents.cs b/Assets/Dojo/Runtime/Torii/ToriiEvents.cs new file mode 100644 index 00000000..5334b7fe --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiEvents.cs @@ -0,0 +1,48 @@ +using System; +using Dojo.Starknet; +using dojo_bindings; +using UnityEngine; + +namespace Dojo.Torii +{ + public class ToriiEvents + { + private static ToriiEvents instance; + + public static ToriiEvents Instance + { + get + { + if (instance == null) + { + instance = new ToriiEvents(); + } + + return instance; + } + } + + public delegate void OnSyncModelUpdateDelegate(); + public delegate void OnEntityStateUpdateDelegate(FieldElement key, Model[] models); + public delegate void OnEventMessageUpdateDelegate(FieldElement key, Model[] models); + + public event OnEntityStateUpdateDelegate OnEntityUpdated; + public event OnEventMessageUpdateDelegate OnEventMessageUpdated; + public event OnSyncModelUpdateDelegate OnSyncModelUpdated; + + public void EventMessageUpdated(FieldElement key, Model[] models) + { + OnEventMessageUpdated?.Invoke(key, models); + } + + public void EntityUpdated(FieldElement key, Model[] models) + { + OnEntityUpdated?.Invoke(key, models); + } + + public void SyncModelUpdated() + { + OnSyncModelUpdated?.Invoke(); + } + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/ToriiEvents.cs.meta b/Assets/Dojo/Runtime/Torii/ToriiEvents.cs.meta new file mode 100644 index 00000000..b8ea0a60 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiEvents.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 642cb7614a6b4abaa32ebc4c95bf1336 +timeCreated: 1702573728 \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs b/Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs new file mode 100644 index 00000000..df0c122d --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using AOT; +using bottlenoselabs.C2CS.Runtime; +using Dojo.Starknet; +using dojo_bindings; +using Newtonsoft.Json; +using UnityEngine; + +namespace Dojo.Torii +{ + public class ToriiWasmClient + { + private string toriiUrl; + private string rpcUrl; + private string relayUrl; + private FieldElement world; + public IntPtr clientPtr; + + IntPtr entitySubscription; + IntPtr eventMessageSubscription; + + public ToriiWasmClient(string toriiUrl, string rpcUrl, string relayUrl, FieldElement world) + { + this.toriiUrl = toriiUrl; + this.rpcUrl = rpcUrl; + this.relayUrl = relayUrl; + this.world = world; + } + + private static class CreateClientHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(IntPtr clientPtr) + { + Tcs.SetResult(clientPtr); + } + } + + public async Task CreateClient() + { + CreateClientHelper.Tcs = new TaskCompletionSource(); + ToriiWasmInterop.CreateClient(new CString(rpcUrl), new CString(toriiUrl), new CString(relayUrl), new CString(world.Hex()), CreateClientHelper.Callback); + clientPtr = await CreateClientHelper.Tcs.Task; + + entitySubscription = await RegisterEntityStateUpdateEvent(new KeysClause[] { }); + eventMessageSubscription = await RegisterEventMessageUpdateEvent(new KeysClause[] { }); + } + + private static class GetEntitiesHelper + { + public static TaskCompletionSource> Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(string entities) + { + var parsedEntities = JsonConvert.DeserializeObject>>>(entities); + var entityList = new List(); + + foreach (var entity in parsedEntities) + { + var models = new Dictionary(); + foreach (var model in entity.Value) + { + models.Add(model.Key, new Model( + model.Key, + model.Value.ToDictionary( + m => m.Key, + m => m.Value + ) + )); + } + + entityList.Add(new Entity(new FieldElement(entity.Key), models)); + } + + Tcs.SetResult(entityList); + } + } + + public Task> Entities(Query query) + { + GetEntitiesHelper.Tcs = new TaskCompletionSource>(); + ToriiWasmInterop.GetEntities(clientPtr, new CString(JsonConvert.SerializeObject(query)), GetEntitiesHelper.Callback); + return GetEntitiesHelper.Tcs.Task; + } + + public Task> EventMessages(Query query) + { + GetEntitiesHelper.Tcs = new TaskCompletionSource>(); + ToriiWasmInterop.GetEventMessages(clientPtr, new CString(JsonConvert.SerializeObject(query)), GetEntitiesHelper.Callback); + return GetEntitiesHelper.Tcs.Task; + } + + private static class OnEntityUpdatedHelper + { + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(string hashed_keys, string models) + { + var parsedModels = JsonConvert.DeserializeObject>>(models).Select(m => new Model( + m.Key, + m.Value + )).ToArray(); + + ToriiEvents.Instance.EntityUpdated(new FieldElement(hashed_keys), parsedModels); + } + } + + private static class SubscriptionHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(IntPtr subPtr) + { + Tcs.SetResult(subPtr); + } + } + + public async Task RegisterEntityStateUpdateEvent(KeysClause[] clauses) + { + SubscriptionHelper.Tcs = new TaskCompletionSource(); + ToriiWasmInterop.OnEntityUpdated(clientPtr, new CString(JsonConvert.SerializeObject(clauses)), OnEntityUpdatedHelper.Callback, SubscriptionHelper.Callback); + return await SubscriptionHelper.Tcs.Task; + } + + public void UpdateEntitySubscription(KeysClause[] clauses) + { + ToriiWasmInterop.UpdateEntitySubscription(clientPtr, entitySubscription, new CString(JsonConvert.SerializeObject(clauses))); + } + + private static class OnEventMessageUpdatedHelper + { + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(string hashed_keys, string models) + { + var parsedModels = JsonConvert.DeserializeObject>>(models).Select(m => new Model( + m.Key, + m.Value + )).ToArray(); + + ToriiEvents.Instance.EventMessageUpdated(new FieldElement(hashed_keys), parsedModels); + } + } + + public async Task RegisterEventMessageUpdateEvent(KeysClause[] clauses) + { + SubscriptionHelper.Tcs = new TaskCompletionSource(); + ToriiWasmInterop.OnEventMessageUpdated(clientPtr, new CString(JsonConvert.SerializeObject(clauses)), OnEventMessageUpdatedHelper.Callback, SubscriptionHelper.Callback); + return await SubscriptionHelper.Tcs.Task; + } + + public void UpdateEventMessageSubscription(KeysClause[] clauses) + { + ToriiWasmInterop.UpdateEventMessageSubscription(clientPtr, eventMessageSubscription, new CString(JsonConvert.SerializeObject(clauses))); + } + + private static class PublishMessageHelper + { + public static TaskCompletionSource Tcs; + + [MonoPInvokeCallback(typeof(Action))] + public static void Callback(string messageId) + { + Tcs.SetResult(JsonConvert.DeserializeObject(messageId)); + } + } + + public Task PublishMessage(TypedData typedData, FieldElement[] signature) + { + PublishMessageHelper.Tcs = new TaskCompletionSource(); + ToriiWasmInterop.PublishMessage(clientPtr, new CString(JsonConvert.SerializeObject(typedData)), new CString(JsonConvert.SerializeObject(signature)), PublishMessageHelper.Callback); + return PublishMessageHelper.Tcs.Task; + } + + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs.meta b/Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs.meta new file mode 100644 index 00000000..742cdca0 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiWasmClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36dd8a29682074310a17ed3141123c34 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs b/Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs new file mode 100644 index 00000000..c2c5e59d --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs @@ -0,0 +1,83 @@ +using UnityEngine; +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using bottlenoselabs.C2CS.Runtime; +using AOT; +using System.Collections.Generic; +using dojo_bindings; +using Dojo.Starknet; +using Newtonsoft.Json; +using System.Linq; +using Newtonsoft.Json.Linq; + + +namespace Dojo.Torii +{ + [Serializable] + public struct WasmValue + { + public string type; + public string type_name; + public JToken value; + public bool key; + } + + [Serializable] + public struct WasmEnum + { + public string option; + public WasmValue value; + } + + public class ToriiWasmInterop : MonoBehaviour + { + // Creates a new client and returns the pointer to it + [DllImport("__Internal")] + public static extern void CreateClient(CString rpcUrl, CString toriiUrl, CString relayUrl, CString worldAddress, Action cb); + + // Returns a dictionary of all of the entities + [DllImport("__Internal")] + public static extern void GetEntities(IntPtr clientPtr, CString query, Action cb); + + [DllImport("__Internal")] + public static extern void GetEventMessages(IntPtr clientPtr, CString query, Action cb); + + // Get the value of a model for a specific set of keys + [DllImport("__Internal")] + public static extern string GetModelValue(IntPtr clientPtr, CString model, CString keys); + + // Calls the callback at [callbackObjectName].[callbackMethodName] on entity updated + [DllImport("__Internal")] + public static extern void OnEntityUpdated(IntPtr clientPtr, CString clauses, Action cb, Action subCb); + + [DllImport("__Internal")] + public static extern void UpdateEntitySubscription(IntPtr clientPtr, IntPtr subPtr, CString clauses); + + // Calls the callback at [callbackObjectName].[callbackMethodName] on event mnessage updated + [DllImport("__Internal")] + public static extern void OnEventMessageUpdated(IntPtr clientPtr, CString clauses, Action cb, Action subCb); + + [DllImport("__Internal")] + public static extern void UpdateEventMessageSubscription(IntPtr clientPtr, IntPtr subPtr, CString clauses); + + // Add models to sync + [DllImport("__Internal")] + public static extern void AddModelsToSync(IntPtr clientPtr, CString models); + + // Remove models to sync + [DllImport("__Internal")] + public static extern void RemoveModelsToSync(IntPtr clientPtr, CString models); + + // Calls the callback at [callbackObjectName].[callbackMethodName] on model change + [DllImport("__Internal")] + public static extern void OnSyncModelChange(IntPtr clientPtr, CString model, CString callbackObjectName, CString callbackMethodName); + + [DllImport("__Internal")] + public static extern string EncodeTypedData(CString typedData, CString address); + + + [DllImport("__Internal")] + public static extern void PublishMessage(IntPtr clientPtr, CString typedData, CString signature, Action cb); + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs.meta b/Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs.meta new file mode 100644 index 00000000..f939db06 --- /dev/null +++ b/Assets/Dojo/Runtime/Torii/ToriiWasmInterop.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d95e0060dd634843b30e3347384dd00 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs new file mode 100644 index 00000000..d853913f --- /dev/null +++ b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs @@ -0,0 +1,121 @@ +/* +Copyright 2015 Pim de Witte All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System; +using System.Threading.Tasks; + +namespace Dojo { + /// Author: Pim de Witte (pimdewitte.com) and contributors, https://github.com/PimDeWitte/UnityMainThreadDispatcher + /// + /// A thread-safe class which holds a queue with actions to execute on the next Update() method. It can be used to make calls to the main thread for + /// things such as UI Manipulation in Unity. It was developed for use in combination with the Firebase Unity plugin, which uses separate threads for event handling + /// + public class UnityMainThreadDispatcher : MonoBehaviour { + + private static readonly Queue _executionQueue = new Queue(); + + public void Update() { + lock(_executionQueue) { + while (_executionQueue.Count > 0) { + _executionQueue.Dequeue().Invoke(); + } + } + } + + /// + /// Locks the queue and adds the IEnumerator to the queue + /// + /// IEnumerator function that will be executed from the main thread. + public void Enqueue(IEnumerator action) { + lock (_executionQueue) { + _executionQueue.Enqueue (() => { + StartCoroutine (action); + }); + } + } + + /// + /// Locks the queue and adds the Action to the queue + /// + /// function that will be executed from the main thread. + public void Enqueue(Action action) + { + Enqueue(ActionWrapper(action)); + } + + /// + /// Locks the queue and adds the Action to the queue, returning a Task which is completed when the action completes + /// + /// function that will be executed from the main thread. + /// A Task that can be awaited until the action completes + public Task EnqueueAsync(Action action) + { + var tcs = new TaskCompletionSource(); + + void WrappedAction() { + try + { + action(); + tcs.TrySetResult(true); + } catch (Exception ex) + { + tcs.TrySetException(ex); + } + } + + Enqueue(ActionWrapper(WrappedAction)); + return tcs.Task; + } + + + IEnumerator ActionWrapper(Action a) + { + a(); + yield return null; + } + + + private static UnityMainThreadDispatcher _instance = null; + + public static bool Exists() { + return _instance != null; + } + + public static UnityMainThreadDispatcher Instance() { + if (!Exists ()) { + throw new Exception ("UnityMainThreadDispatcher could not find the UnityMainThreadDispatcher object. Please ensure you have added the MainThreadExecutor Prefab to your scene."); + } + return _instance; + } + + + void Awake() { + if (_instance == null) { + _instance = this; + DontDestroyOnLoad(this.gameObject); + } + } + + void OnDestroy() { + _instance = null; + } + + + } +} \ No newline at end of file diff --git a/Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs.meta b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs.meta new file mode 100644 index 00000000..114f810d --- /dev/null +++ b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e64d6ffea92654f2985ae6e815d40ad7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab new file mode 100644 index 00000000..6c12637e --- /dev/null +++ b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab @@ -0,0 +1,50 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &184210 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 22414968} + - component: {fileID: 6342550579897674515} + m_Layer: 0 + m_Name: UnityMainThreadDispatcher + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &22414968 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 184210} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 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: -50, y: -50} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0, y: 0} +--- !u!114 &6342550579897674515 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 184210} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e64d6ffea92654f2985ae6e815d40ad7, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab.meta b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab.meta new file mode 100644 index 00000000..803ed892 --- /dev/null +++ b/Assets/Dojo/Runtime/UnityMainThreadDispatcher.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c3c54c612cab04d86ab0ee8c4125943d +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/WorldManager.cs b/Assets/Dojo/Runtime/WorldManager.cs new file mode 100644 index 00000000..e258569d --- /dev/null +++ b/Assets/Dojo/Runtime/WorldManager.cs @@ -0,0 +1,126 @@ +using System.Linq; +using dojo_bindings; +using UnityEngine; +using Dojo.Torii; +using System; +using Dojo.Starknet; +using System.Threading.Tasks; + +namespace Dojo +{ + public class WorldManager : MonoBehaviour + { + public SynchronizationMaster synchronizationMaster; + public ToriiClient toriiClient; + public ToriiWasmClient wasmClient; + [SerializeField] public WorldManagerData dojoConfig; + + async void Awake() + { +#if UNITY_WEBGL && !UNITY_EDITOR + wasmClient = new ToriiWasmClient(dojoConfig.toriiUrl, dojoConfig.rpcUrl, + dojoConfig.relayWebrtcUrl, dojoConfig.worldAddress); + await wasmClient.CreateClient(); +#else + toriiClient = new ToriiClient(dojoConfig.toriiUrl, dojoConfig.rpcUrl, + dojoConfig.relayUrl, dojoConfig.worldAddress); +#endif + + /* fetch entities from the world + TODO: maybe do in the start function of the SynchronizationMaster? + problem is when to start the subscription service + */ + await synchronizationMaster.SynchronizeEntities(); + + // listen for entity updates + synchronizationMaster.RegisterEntityCallbacks(); + synchronizationMaster.RegisterEventMessageCallbacks(); + } + + // #if UNITY_WEBGL && !UNITY_EDITOR + // // internal callback to be called for when the client is created + // // on the wasm sdk. + // public void OnClientCreated(float clientPtr) + // { + // toriiClient.wasmClientPtr = (IntPtr)clientPtr; + // // we dont start the subscription service + // // because wasm already does it. + + // // fetch entities from the world + // // TODO: maybe do in the start function of the SynchronizationMaster? + // // problem is when to start the subscription service + // synchronizationMaster.SynchronizeEntities(); + + // // listen for entity updates + // synchronizationMaster.RegisterEntityCallbacks(); + // } + // #endif + + /* Get a child entity from the WorldManager game object. + Name is usually the hashed_keys of the entity as a hex string. + */ + public GameObject Entity(string name) + { + var entity = transform.Find(name); + if (entity == null) + { + Debug.LogError($"Entity {name} not found"); + return null; + } + + return entity.gameObject; + } + + // Return all children entities. + public GameObject[] Entities() + { + return transform.Cast().Select(t => t.gameObject).ToArray(); + } + + // Return all children entities. + // That have the specified component. + public GameObject[] Entities() where T : Component + { + return transform.Cast() + .Select(t => t.gameObject) + .Where(g => g.GetComponent() != null) + .ToArray(); + } + + // Add a new entity game object as a child of the WorldManager game object. + public GameObject AddEntity(string key) + { + // check if entity already exists + var entity = transform.Find(key)?.gameObject; + if (entity != null) + { + Debug.LogWarning($"Entity {key} already exists"); + return entity.gameObject; + } + + entity = new GameObject(key); + entity.transform.parent = transform; + + return entity; + } + + // Remove an entity game object from the WorldManager game object. + public void RemoveEntity(string key) + { + var entity = transform.Find(key); + if (entity != null) + { + Destroy(entity.gameObject); + } + } + + public async Task Publish(TypedData typedData, FieldElement[] signature) + { +#if UNITY_WEBGL && !UNITY_EDITOR + return await wasmClient.PublishMessage(typedData, signature); +#else + return await Task.Run(() => toriiClient.PublishMessage(typedData, signature).ToArray()); +#endif + } + } +} diff --git a/Assets/Dojo/Runtime/WorldManager.cs.meta b/Assets/Dojo/Runtime/WorldManager.cs.meta new file mode 100644 index 00000000..5b925751 --- /dev/null +++ b/Assets/Dojo/Runtime/WorldManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85bbcaeafdf5e41c6a2f48ff65820b7d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/bindings.meta b/Assets/Dojo/Runtime/bindings.meta new file mode 100644 index 00000000..304582e0 --- /dev/null +++ b/Assets/Dojo/Runtime/bindings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e737eb36a634e4749adbb89b50c74761 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/bindings/client.meta b/Assets/Dojo/Runtime/bindings/client.meta new file mode 100644 index 00000000..8216d0b3 --- /dev/null +++ b/Assets/Dojo/Runtime/bindings/client.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d5fd9914df07a4811bb84c0520a694cc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs b/Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs new file mode 100644 index 00000000..0720567a --- /dev/null +++ b/Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs @@ -0,0 +1,27 @@ +// To disable generating this file set `isEnabledGenerateAssemblyAttributes` to `false` in the config file for generating C# code. +// +// This code was generated by the following tool on 2024-11-04 18:42:12 GMT-05:00: +// https://github.com/bottlenoselabs/c2cs (v0.0.0.0) +// +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +// ReSharper disable All + +#region Template +#nullable enable +#pragma warning disable CS1591 +#pragma warning disable CS8981 +using bottlenoselabs.C2CS.Runtime; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Linq; +#endregion + +#if NET7_0_OR_GREATER +[assembly: DisableRuntimeMarshalling] +#endif + +[assembly: DefaultDllImportSearchPathsAttribute(DllImportSearchPath.SafeDirectories)] diff --git a/Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs.meta b/Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs.meta new file mode 100644 index 00000000..bc2da10c --- /dev/null +++ b/Assets/Dojo/Runtime/bindings/client/AssemblyAttributes.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9233e4708d16d4b64972ed5e59ec9cac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs b/Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs new file mode 100644 index 00000000..5c9782fe --- /dev/null +++ b/Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs @@ -0,0 +1,790 @@ + +// To disable generating this file set `isEnabledGeneratingRuntimeCode` to `false` in the config file for generating C# code. + +// +// This code was generated by the following tool on 2024-11-04 18:42:12 GMT-05:00: +// https://github.com/bottlenoselabs/c2cs (v0.0.0.0) +// +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +// ReSharper disable All + +#region Template +#nullable enable +#pragma warning disable CS1591 +#pragma warning disable CS8981 +using bottlenoselabs.C2CS.Runtime; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Linq; +#endregion + +namespace bottlenoselabs.C2CS.Runtime +{ + + /// + /// Specifies a C `const` for a parameter or return value. + /// + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue)] + public sealed class CConstAttribute : Attribute + { + // marker + } + + /// + /// Specifies a C node with a specific kind for a C# type. + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Enum | AttributeTargets.Field)] + public sealed class CNodeAttribute : Attribute + { + /// + /// Gets or sets the C node kind. + /// + public string Kind { get; set; } = string.Empty; + } + + /// + /// A boolean value type with the same memory layout as a in both managed and unmanaged contexts; + /// equivalent to a standard bool found in C/C++/ObjC where 0 is false and any other value is + /// true. + /// + [StructLayout(LayoutKind.Sequential)] + public readonly struct CBool : IEquatable + { + public readonly byte Value; + + private CBool(bool value) + { + Value = Convert.ToByte(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static implicit operator CBool(bool value) + { + return FromBoolean(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static CBool FromBoolean(bool value) + { + return new CBool(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static implicit operator bool(CBool value) + { + return ToBoolean(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static bool ToBoolean(CBool value) + { + return Convert.ToBoolean(value.Value); + } + + /// + public override string ToString() + { + return ToBoolean(this).ToString(); + } + + /// + public override bool Equals(object? obj) + { + return obj is CBool b && Equals(b); + } + + /// + public bool Equals(CBool other) + { + return Value == other.Value; + } + + /// + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + /// + /// Returns a value that indicates whether two specified structures are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool operator ==(CBool left, CBool right) + { + return left.Value == right.Value; + } + + /// + /// Returns a value that indicates whether two specified structures are not equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are not equal; otherwise, false. + public static bool operator !=(CBool left, CBool right) + { + return !(left == right); + } + + /// + /// Returns a value that indicates whether two specified structures are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool Equals(CBool left, CBool right) + { + return left.Value == right.Value; + } + } + + /// + /// A value type with the same memory layout as a in a managed context and char in + /// an unmanaged context. + /// + [StructLayout(LayoutKind.Sequential)] + public readonly struct CChar : IEquatable, IEquatable + { + public readonly byte Value; + + private CChar(byte value) + { + Value = Convert.ToByte(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static implicit operator CChar(byte value) + { + return FromByte(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static CChar FromByte(byte value) + { + return new CChar(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static implicit operator byte(CChar value) + { + return ToByte(value); + } + + /// + /// Converts the specified to a . + /// + /// The value. + /// A . + public static byte ToByte(CChar value) + { + return value.Value; + } + + /// + public override string ToString() + { + return Value.ToString(CultureInfo.InvariantCulture); + } + + /// + public override bool Equals(object? obj) + { + return obj is CChar value && Equals(value); + } + + /// + public bool Equals(byte other) + { + return Value == other; + } + + /// + public bool Equals(CChar other) + { + return Value == other.Value; + } + + /// + public override int GetHashCode() + { + return Value.GetHashCode(); + } + + /// + /// Returns a value that indicates whether two specified structures are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool operator ==(CChar left, CChar right) + { + return left.Value == right.Value; + } + + /// + /// Returns a value that indicates whether two specified structures are not equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are not equal; otherwise, false. + public static bool operator !=(CChar left, CChar right) + { + return !(left == right); + } + + /// + /// Returns a value that indicates whether two specified structures are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool Equals(CChar left, CChar right) + { + return left.Value == right.Value; + } + } + + /// + /// A pointer value type of bytes that represent a string; the C type `char*`. + /// + [StructLayout(LayoutKind.Sequential)] + public readonly unsafe struct CString : IEquatable, IDisposable + { + public readonly nint Pointer; + + /// + /// Gets a value indicating whether this is a null pointer. + /// + public bool IsNull => Pointer == 0; + + /// + /// Initializes a new instance of the struct. + /// + /// The pointer value. + public CString(byte* value) + { + Pointer = (nint)value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The pointer value. + public CString(nint value) + { + Pointer = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The string value. + public CString(string s) + { + Pointer = FromString(s).Pointer; + } + + /// + /// Attempts to free the memory pointed by the . + /// + public void Dispose() + { + Marshal.FreeHGlobal(Pointer); + } + + /// + /// Performs an explicit conversion from an to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static explicit operator CString(nint value) + { + return FromIntPtr(value); + } + + /// + /// Performs an explicit conversion from an to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static CString FromIntPtr(nint value) + { + return new CString(value); + } + + /// + /// Performs an implicit conversion from a byte pointer to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static implicit operator CString(byte* value) + { + return From(value); + } + + /// + /// Performs an implicit conversion from a byte pointer to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static CString From(byte* value) + { + return new CString((nint)value); + } + + /// + /// Performs an implicit conversion from a to a . + /// + /// The pointer. + /// + /// The resulting . + /// + public static implicit operator nint(CString value) + { + return value.Pointer; + } + + /// + /// Performs an implicit conversion from a to a . + /// + /// The pointer. + /// + /// The resulting . + /// + public static nint ToIntPtr(CString value) + { + return value.Pointer; + } + + /// + /// Performs an explicit conversion from a to a . + /// + /// The . + /// + /// The resulting . + /// + public static explicit operator string(CString value) + { + return ToString(value); + } + + /// + /// Converts a C style string (ANSI or UTF-8) of type `char` (one dimensional byte array + /// terminated by a 0x0) to a UTF-16 by allocating and copying. + /// + /// A pointer to the C string. + /// A equivalent of . + public static string ToString(CString value) + { + if (value.IsNull) + { + return string.Empty; + } + + // calls ASM/C/C++ functions to calculate length and then "FastAllocate" the string with the GC + // https://mattwarren.org/2016/05/31/Strings-and-the-CLR-a-Special-Relationship/ + var result = Marshal.PtrToStringAnsi(value.Pointer); + + if (string.IsNullOrEmpty(result)) + { + return string.Empty; + } + + return result; + } + + /// + /// Performs an explicit conversion from a to a . + /// + /// The . + /// + /// The resulting . + /// + public static explicit operator CString(string s) + { + return FromString(s); + } + + /// + /// Converts a UTF-16 to a C style string (one dimensional byte array terminated by a + /// 0x0) by allocating and copying. + /// + /// The . + /// A C string pointer. + public static CString FromString(string str) + { + var pointer = Marshal.StringToHGlobalAnsi(str); + return new CString(pointer); + } + + /// + public override string ToString() + { + return ToString(this); + } + + /// + public override bool Equals(object? obj) + { + return obj is CString value && Equals(value); + } + + /// + public bool Equals(CString other) + { + return Pointer == other.Pointer; + } + + /// + public override int GetHashCode() + { + return Pointer.GetHashCode(); + } + + /// + /// Returns a value that indicates whether two specified structures are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool operator ==(CString left, CString right) + { + return left.Pointer == right.Pointer; + } + + /// + /// Returns a value that indicates whether two specified structures are not equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are not equal; otherwise, false. + public static bool operator !=(CString left, CString right) + { + return !(left == right); + } + } + + /// + /// Utility methods for interoperability with C style strings in C#. + /// + public static unsafe class CStrings + { + /// + /// Converts an array of strings to an array of C strings of type `char` (multi-dimensional array of one + /// dimensional byte arrays each terminated by a 0x0) by allocating and copying if not already cached. + /// + /// + /// Calls . + /// + /// The strings. + /// An array pointer of C string pointers. You are responsible for freeing the returned pointer. + public static CString* CStringArray(ReadOnlySpan values) + { + var pointerSize = IntPtr.Size; + var result = (CString*)Marshal.AllocHGlobal(pointerSize * values.Length); + for (var i = 0; i < values.Length; ++i) + { + var @string = values[i]; + var cString = CString.FromString(@string); + result[i] = cString; + } + + return result; + } + + /// + /// Converts an array of strings to an array of C strings of type `wchar_t` (multi-dimensional array of one + /// dimensional ushort arrays each terminated by a 0x0) by allocating and copying if not already cached. + /// + /// + /// Calls . + /// + /// The strings. + /// An array pointer of C string pointers. You are responsible for freeing the returned pointer. + public static CStringWide* CStringWideArray(ReadOnlySpan values) + { + var pointerSize = IntPtr.Size; + var result = (CStringWide*)Marshal.AllocHGlobal(pointerSize * values.Length); + for (var i = 0; i < values.Length; ++i) + { + var @string = values[i]; + var cString = CStringWide.FromString(@string); + result[i] = cString; + } + + return result; + } + } + + /// + /// A pointer value type that represents a wide string; C type `wchar_t*`. + /// + [StructLayout(LayoutKind.Sequential)] + public readonly unsafe struct CStringWide : IEquatable + { + public readonly nint Pointer; + + /// + /// Gets a value indicating whether this is a null pointer. + /// + public bool IsNull => Pointer == 0; + + /// + /// Initializes a new instance of the struct. + /// + /// The pointer value. + public CStringWide(byte* value) + { + Pointer = (nint)value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The pointer value. + public CStringWide(nint value) + { + Pointer = value; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The string value. + public CStringWide(string s) + { + Pointer = FromString(s).Pointer; + } + + /// + /// Performs an explicit conversion from a to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static explicit operator CStringWide(nint value) + { + return FromIntPtr(value); + } + + /// + /// Performs an explicit conversion from a to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static CStringWide FromIntPtr(nint value) + { + return new CStringWide(value); + } + + /// + /// Performs an implicit conversion from a byte pointer to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static implicit operator CStringWide(byte* value) + { + return From(value); + } + + /// + /// Performs an implicit conversion from a byte pointer to a . + /// + /// The pointer value. + /// + /// The resulting . + /// + public static CStringWide From(byte* value) + { + return new CStringWide((nint)value); + } + + /// + /// Performs an implicit conversion from a to a . + /// + /// The pointer. + /// + /// The resulting . + /// + public static implicit operator nint(CStringWide value) + { + return value.Pointer; + } + + /// + /// Performs an implicit conversion from a to a . + /// + /// The pointer. + /// + /// The resulting . + /// + public static nint ToIntPtr(CStringWide value) + { + return value.Pointer; + } + + /// + /// Performs an explicit conversion from a to a . + /// + /// The . + /// + /// The resulting . + /// + public static explicit operator string(CStringWide value) + { + return ToString(value); + } + + /// + /// Converts a C style string (unicode) of type `wchar_t` (one dimensional ushort array + /// terminated by a 0x0) to a UTF-16 by allocating and copying. + /// + /// A pointer to the C string. + /// A equivalent of . + public static string ToString(CStringWide value) + { + if (value.IsNull) + { + return string.Empty; + } + + // calls ASM/C/C++ functions to calculate length and then "FastAllocate" the string with the GC + // https://mattwarren.org/2016/05/31/Strings-and-the-CLR-a-Special-Relationship/ + var result = Marshal.PtrToStringUni(value.Pointer); + + if (string.IsNullOrEmpty(result)) + { + return string.Empty; + } + + return result; + } + + /// + /// Performs an explicit conversion from a to a . + /// + /// The . + /// + /// The resulting . + /// + public static explicit operator CStringWide(string s) + { + return FromString(s); + } + + /// + /// Converts a C string pointer (one dimensional byte array terminated by a + /// 0x0) for a specified by allocating and copying if not already cached. + /// + /// The . + /// A C string pointer. + public static CStringWide FromString(string str) + { + var pointer = Marshal.StringToHGlobalUni(str); + return new CStringWide(pointer); + } + + /// + public override string ToString() + { + return ToString(this); + } + + /// + public override bool Equals(object? obj) + { + return obj is CStringWide value && Equals(value); + } + + /// + public bool Equals(CStringWide other) + { + return Pointer == other.Pointer; + } + + /// + public override int GetHashCode() + { + return Pointer.GetHashCode(); + } + + /// + /// Returns a value that indicates whether two specified structures are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool operator ==(CStringWide left, CStringWide right) + { + return left.Pointer == right.Pointer; + } + + /// + /// Returns a value that indicates whether two specified structures are not equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are not equal; otherwise, false. + public static bool operator !=(CStringWide left, CStringWide right) + { + return !(left == right); + } + + /// + /// Returns a value that indicates whether two specified structures are equal. + /// + /// The first to compare. + /// The second to compare. + /// true if and are equal; otherwise, false. + public static bool Equals(CStringWide left, CStringWide right) + { + return left.Pointer == right.Pointer; + } + } +} diff --git a/Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs.meta b/Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs.meta new file mode 100644 index 00000000..8f8aca17 --- /dev/null +++ b/Assets/Dojo/Runtime/bindings/client/Runtime.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d614dd06d58f455992af3473838d86e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Runtime/bindings/client/dojo.gen.cs b/Assets/Dojo/Runtime/bindings/client/dojo.gen.cs new file mode 100644 index 00000000..4e05830f --- /dev/null +++ b/Assets/Dojo/Runtime/bindings/client/dojo.gen.cs @@ -0,0 +1,3131 @@ + +// +// This code was generated by the following tool on 2024-11-04 18:42:12 GMT-05:00: +// https://github.com/bottlenoselabs/c2cs (v0.0.0.0) +// +// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. +// +// ReSharper disable All + +#region Template +#nullable enable +#pragma warning disable CS1591 +#pragma warning disable CS8981 +using bottlenoselabs.C2CS.Runtime; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Linq; +#endregion + +namespace dojo_bindings +{ + + public static unsafe partial class dojo + { + private const string LibraryName = "libdojo_c"; + + #region API + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_address", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement account_address(Account* account); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_chain_id", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement account_chain_id(Account* account); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_deploy_burner", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultAccount account_deploy_burner(Provider* provider, Account* master_account, FieldElement signing_key); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_execute_raw", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultFieldElement account_execute_raw(Account* account, Call* calldata, UIntPtr calldata_len); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void account_free(Account* account); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_new", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultAccount account_new(Provider* rpc, FieldElement private_key, CString address); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_nonce", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultFieldElement account_nonce(Account* account); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "account_set_block_id", CallingConvention = CallingConvention.Cdecl)] + public static extern void account_set_block_id(Account* account, BlockId block_id); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "bytearray_deserialize", CallingConvention = CallingConvention.Cdecl)] + public static extern Resultc_char bytearray_deserialize(FieldElement* felts, UIntPtr felts_len); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "bytearray_serialize", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultCArrayFieldElement bytearray_serialize(CString str); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "cairo_short_string_to_felt", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultFieldElement cairo_short_string_to_felt(CString str); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "carray_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void carray_free(void* data, UIntPtr data_len); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_entities", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultCArrayEntity client_entities(ToriiClient* client, Query* query); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_event_messages", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultCArrayEntity client_event_messages(ToriiClient* client, Query* query, CBool historical); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void client_free(ToriiClient* t); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_metadata", CallingConvention = CallingConvention.Cdecl)] + public static extern WorldMetadata client_metadata(ToriiClient* client); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_new", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultToriiClient client_new(CString torii_url, CString rpc_url, CString libp2p_relay_url, FieldElement world); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_on_entity_state_update", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultSubscription client_on_entity_state_update(ToriiClient* client, EntityKeysClause* clauses, UIntPtr clauses_len, FnPtr_FieldElement_CArrayStruct_Void callback); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_on_event_message_update", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultSubscription client_on_event_message_update(ToriiClient* client, EntityKeysClause* clauses, UIntPtr clauses_len, CBool historical, FnPtr_FieldElement_CArrayStruct_Void callback); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_on_starknet_event", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultSubscription client_on_starknet_event(ToriiClient* client, EntityKeysClause* clauses, UIntPtr clauses_len, FnPtr_Event_Void callback); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_publish_message", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultCArrayu8 client_publish_message(ToriiClient* client, CString message, FieldElement* signature_felts, UIntPtr signature_felts_len); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_set_logger", CallingConvention = CallingConvention.Cdecl)] + public static extern void client_set_logger(ToriiClient* client, FnPtr_CString_Void logger); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_update_entity_subscription", CallingConvention = CallingConvention.Cdecl)] + public static extern Resultbool client_update_entity_subscription(ToriiClient* client, Subscription* subscription, EntityKeysClause* clauses, UIntPtr clauses_len); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "client_update_event_message_subscription", CallingConvention = CallingConvention.Cdecl)] + public static extern Resultbool client_update_event_message_subscription(ToriiClient* client, Subscription* subscription, EntityKeysClause* clauses, UIntPtr clauses_len, CBool historical); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "entity_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void entity_free(Entity* entity); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "error_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void error_free(Error* error); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "get_selector_from_name", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultFieldElement get_selector_from_name(CString name); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "get_selector_from_tag", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement get_selector_from_tag(CString tag); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "hash_get_contract_address", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement hash_get_contract_address(FieldElement class_hash, FieldElement salt, FieldElement* constructor_calldata, UIntPtr constructor_calldata_len, FieldElement deployer_address); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "model_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void model_free(Struct* model); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "on_indexer_update", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultSubscription on_indexer_update(ToriiClient* client, FieldElement* contract_address, FnPtr_IndexerUpdate_Void callback); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "parse_cairo_short_string", CallingConvention = CallingConvention.Cdecl)] + public static extern Resultc_char parse_cairo_short_string(FieldElement felt); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "poseidon_hash", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement poseidon_hash(FieldElement* felts, UIntPtr felts_len); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "provider_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void provider_free(Provider* rpc); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "provider_new", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultProvider provider_new(CString rpc_url); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "signing_key_new", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement signing_key_new(); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "signing_key_sign", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultSignature signing_key_sign(FieldElement private_key, FieldElement hash); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "starknet_call", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultCArrayFieldElement starknet_call(Provider* provider, Call call, BlockId block_id); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "starknet_keccak", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement starknet_keccak(byte* bytes, UIntPtr bytes_len); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "string_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void string_free(CString @string); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "subscription_cancel", CallingConvention = CallingConvention.Cdecl)] + public static extern void subscription_cancel(Subscription* subscription); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "ty_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void ty_free(Ty* ty); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "typed_data_encode", CallingConvention = CallingConvention.Cdecl)] + public static extern ResultFieldElement typed_data_encode(CString typed_data, FieldElement address); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "verifying_key_new", CallingConvention = CallingConvention.Cdecl)] + public static extern FieldElement verifying_key_new(FieldElement signing_key); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "verifying_key_verify", CallingConvention = CallingConvention.Cdecl)] + public static extern Resultbool verifying_key_verify(FieldElement verifying_key, FieldElement hash, Signature signature); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "wait_for_transaction", CallingConvention = CallingConvention.Cdecl)] + public static extern Resultbool wait_for_transaction(Provider* rpc, FieldElement txn_hash); + + [CNode(Kind = "Function")] + [DllImport(LibraryName, EntryPoint = "world_metadata_free", CallingConvention = CallingConvention.Cdecl)] + public static extern void world_metadata_free(WorldMetadata* metadata); + + #endregion + + #region Types + + [CNode(Kind = "FunctionPointer")] + [StructLayout(LayoutKind.Sequential)] + public struct FnPtr_CString_Void + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public unsafe delegate void @delegate(CString param); + + public IntPtr Pointer; + + public FnPtr_CString_Void(@delegate d) + { + Pointer = Marshal.GetFunctionPointerForDelegate(d); + } + } + + [CNode(Kind = "FunctionPointer")] + [StructLayout(LayoutKind.Sequential)] + public struct FnPtr_Event_Void + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public unsafe delegate void @delegate(Event param); + + public IntPtr Pointer; + + public FnPtr_Event_Void(@delegate d) + { + Pointer = Marshal.GetFunctionPointerForDelegate(d); + } + } + + [CNode(Kind = "FunctionPointer")] + [StructLayout(LayoutKind.Sequential)] + public struct FnPtr_FieldElement_CArrayStruct_Void + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public unsafe delegate void @delegate(FieldElement param, CArrayStruct param2); + + public IntPtr Pointer; + + public FnPtr_FieldElement_CArrayStruct_Void(@delegate d) + { + Pointer = Marshal.GetFunctionPointerForDelegate(d); + } + } + + [CNode(Kind = "FunctionPointer")] + [StructLayout(LayoutKind.Sequential)] + public struct FnPtr_IndexerUpdate_Void + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public unsafe delegate void @delegate(IndexerUpdate param); + + public IntPtr Pointer; + + public FnPtr_IndexerUpdate_Void(@delegate d) + { + Pointer = Marshal.GetFunctionPointerForDelegate(d); + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct BlockId + { + [FieldOffset(0)] // size = 4 + public BlockId_Tag tag; + + [FieldOffset(8)] // size = 32 + public FieldElement hash; + + [FieldOffset(8)] // size = 8 + public ulong number; + + [FieldOffset(8)] // size = 4 + public BlockTag block_tag; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 8)] + public struct BlockId_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 32 + public FieldElement hash; + + [FieldOffset(0)] // size = 8 + public ulong number; + + [FieldOffset(0)] // size = 4 + public BlockTag block_tag; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct BlockId_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 32 + public FieldElement hash; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct BlockId_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public ulong number; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 4, Pack = 4)] + public struct BlockId_ANONYMOUS_FIELD1_ANONYMOUS_FIELD2 + { + [FieldOffset(0)] // size = 4 + public BlockTag block_tag; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayCHashItemFieldElementModelMetadata + { + [FieldOffset(0)] // size = 8 + public CHashItemFieldElementModelMetadata* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayCOptionFieldElement + { + [FieldOffset(0)] // size = 8 + public COptionFieldElement* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayClause + { + [FieldOffset(0)] // size = 8 + public Clause* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayEntity + { + [FieldOffset(0)] // size = 8 + public Entity* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayEnumOption + { + [FieldOffset(0)] // size = 8 + public EnumOption* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayFieldElement + { + [FieldOffset(0)] // size = 8 + public FieldElement* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayMember + { + [FieldOffset(0)] // size = 8 + public Member* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayStruct + { + [FieldOffset(0)] // size = 8 + public Struct* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayTy + { + [FieldOffset(0)] // size = 8 + public Ty* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayc_char + { + [FieldOffset(0)] // size = 8 + public CString* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct CArrayu8 + { + [FieldOffset(0)] // size = 8 + public byte* data; + + [FieldOffset(8)] // size = 8 + public UIntPtr data_len; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 184, Pack = 8)] + public struct CHashItemFieldElementModelMetadata + { + [FieldOffset(0)] // size = 32 + public FieldElement key; + + [FieldOffset(32)] // size = 152 + public ModelMetadata value; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 88, Pack = 8)] + public struct COptionClause + { + [FieldOffset(0)] // size = 4 + public COptionClause_Tag tag; + + [FieldOffset(8)] // size = 80 + public Clause some; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 80, Pack = 8)] + public struct COptionClause_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 80 + public Clause some; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 80, Pack = 8)] + public struct COptionClause_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 80 + public Clause some; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 36, Pack = 4)] + public struct COptionFieldElement + { + [FieldOffset(0)] // size = 4 + public COptionFieldElement_Tag tag; + + [FieldOffset(4)] // size = 32 + public FieldElement some; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct COptionFieldElement_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 32 + public FieldElement some; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct COptionFieldElement_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 32 + public FieldElement some; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 56, Pack = 8)] + public struct Call + { + [FieldOffset(0)] // size = 32 + public FieldElement to; + + [FieldOffset(32)] // size = 8 + public CString selector_; + + public string selector + { + get + { + return CString.ToString(selector_); + } + set + { + selector_ = CString.FromString(value); + } + } + + [FieldOffset(40)] // size = 16 + public CArrayFieldElement _calldata; + + public Span calldata + { + get + { + fixed (Call* @this = &this) + { + var span = new Span(@this->_calldata.data, (int)@this->_calldata.data_len); + return span; + } + } + + set + { + + _calldata = new CArrayFieldElement(); + _calldata.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _calldata.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 80, Pack = 8)] + public struct Clause + { + [FieldOffset(0)] // size = 4 + public Clause_Tag tag; + + [FieldOffset(8)] // size = 40 + public KeysClause keys; + + [FieldOffset(8)] // size = 72 + public MemberClause c_member; + + [FieldOffset(8)] // size = 24 + public CompositeClause composite; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 72, Pack = 8)] + public struct Clause_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 40 + public KeysClause keys; + + [FieldOffset(0)] // size = 72 + public MemberClause c_member; + + [FieldOffset(0)] // size = 24 + public CompositeClause composite; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct Clause_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 40 + public KeysClause keys; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 72, Pack = 8)] + public struct Clause_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 72 + public MemberClause c_member; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 24, Pack = 8)] + public struct Clause_ANONYMOUS_FIELD1_ANONYMOUS_FIELD2 + { + [FieldOffset(0)] // size = 24 + public CompositeClause composite; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 24, Pack = 8)] + public struct CompositeClause + { + [FieldOffset(0)] // size = 4 + public LogicalOperator operator_; + + [FieldOffset(8)] // size = 16 + public CArrayClause _clauses; + + public Span clauses + { + get + { + fixed (CompositeClause* @this = &this) + { + var span = new Span(@this->_clauses.data, (int)@this->_clauses.data_len); + return span; + } + } + + set + { + + _clauses = new CArrayClause(); + _clauses.data_len = (UIntPtr)value.Length; + fixed (Clause* ptr = value) + { + _clauses.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 48, Pack = 8)] + public struct Entity + { + [FieldOffset(0)] // size = 32 + public FieldElement hashed_keys; + + [FieldOffset(32)] // size = 16 + public CArrayStruct _models; + + public Span models + { + get + { + fixed (Entity* @this = &this) + { + var span = new Span(@this->_models.data, (int)@this->_models.data_len); + return span; + } + } + + set + { + + _models = new CArrayStruct(); + _models.data_len = (UIntPtr)value.Length; + fixed (Struct* ptr = value) + { + _models.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 48, Pack = 8)] + public struct EntityKeysClause + { + [FieldOffset(0)] // size = 4 + public EntityKeysClause_Tag tag; + + [FieldOffset(8)] // size = 16 + public CArrayFieldElement _hashed_keys; + + public Span hashed_keys + { + get + { + fixed (EntityKeysClause* @this = &this) + { + var span = new Span(@this->_hashed_keys.data, (int)@this->_hashed_keys.data_len); + return span; + } + } + + set + { + + _hashed_keys = new CArrayFieldElement(); + _hashed_keys.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _hashed_keys.data = ptr; + } + } + } + + [FieldOffset(8)] // size = 40 + public KeysClause entity_keys; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct EntityKeysClause_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 16 + public CArrayFieldElement _hashed_keys; + + public Span hashed_keys + { + get + { + fixed (EntityKeysClause_ANONYMOUS_FIELD1* @this = &this) + { + var span = new Span(@this->_hashed_keys.data, (int)@this->_hashed_keys.data_len); + return span; + } + } + + set + { + + _hashed_keys = new CArrayFieldElement(); + _hashed_keys.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _hashed_keys.data = ptr; + } + } + } + + [FieldOffset(0)] // size = 40 + public KeysClause entity_keys; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct EntityKeysClause_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 16 + public CArrayFieldElement _hashed_keys; + + public Span hashed_keys + { + get + { + fixed (EntityKeysClause_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0* @this = &this) + { + var span = new Span(@this->_hashed_keys.data, (int)@this->_hashed_keys.data_len); + return span; + } + } + + set + { + + _hashed_keys = new CArrayFieldElement(); + _hashed_keys.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _hashed_keys.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct EntityKeysClause_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 40 + public KeysClause entity_keys; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 8)] + public struct Enum + { + [FieldOffset(0)] // size = 8 + public CString name_; + + public string name + { + get + { + return CString.ToString(name_); + } + set + { + name_ = CString.FromString(value); + } + } + + [FieldOffset(8)] // size = 1 + public byte option; + + [FieldOffset(16)] // size = 16 + public CArrayEnumOption _options; + + public Span options + { + get + { + fixed (Enum* @this = &this) + { + var span = new Span(@this->_options.data, (int)@this->_options.data_len); + return span; + } + } + + set + { + + _options = new CArrayEnumOption(); + _options.data_len = (UIntPtr)value.Length; + fixed (EnumOption* ptr = value) + { + _options.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct EnumOption + { + [FieldOffset(0)] // size = 8 + public CString name_; + + public string name + { + get + { + return CString.ToString(name_); + } + set + { + name_ = CString.FromString(value); + } + } + + [FieldOffset(8)] // size = 8 + public Ty* _ty; + + public Ty ty + { + get + { + return *_ty; + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Error + { + [FieldOffset(0)] // size = 8 + public CString message_; + + public string message + { + get + { + return CString.ToString(message_); + } + set + { + message_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 64, Pack = 8)] + public struct Event + { + [FieldOffset(0)] // size = 16 + public CArrayFieldElement _keys; + + public Span keys + { + get + { + fixed (Event* @this = &this) + { + var span = new Span(@this->_keys.data, (int)@this->_keys.data_len); + return span; + } + } + + set + { + + _keys = new CArrayFieldElement(); + _keys.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _keys.data = ptr; + } + } + } + + [FieldOffset(16)] // size = 16 + public CArrayFieldElement _data; + + public Span data + { + get + { + fixed (Event* @this = &this) + { + var span = new Span(@this->_data.data, (int)@this->_data.data_len); + return span; + } + } + + set + { + + _data = new CArrayFieldElement(); + _data.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _data.data = ptr; + } + } + } + + [FieldOffset(32)] // size = 32 + public FieldElement transaction_hash; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct FieldElement + { + [FieldOffset(0)] // size = 32 + public fixed byte _data[32]; // uint8_t[32] + + public Span data + { + get + { + fixed (FieldElement* @this = &this) + { + var pointer = &@this->_data[0]; + var span = new Span(pointer, 32); + return span; + } + } + + set + { + fixed (FieldElement* @this = &this) + { + var pointer = &@this->_data[0]; + var span = new Span(pointer, 32); + value.CopyTo(span); + } + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 56, Pack = 8)] + public struct IndexerUpdate + { + [FieldOffset(0)] // size = 8 + public long head; + + [FieldOffset(8)] // size = 8 + public long tps; + + [FieldOffset(16)] // size = 8 + public long last_block_timestamp; + + [FieldOffset(24)] // size = 32 + public FieldElement contract_address; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct KeysClause + { + [FieldOffset(0)] // size = 16 + public CArrayCOptionFieldElement _keys; + + public Span keys + { + get + { + fixed (KeysClause* @this = &this) + { + var span = new Span(@this->_keys.data, (int)@this->_keys.data_len); + return span; + } + } + + set + { + + _keys = new CArrayCOptionFieldElement(); + _keys.data_len = (UIntPtr)value.Length; + fixed (COptionFieldElement* ptr = value) + { + _keys.data = ptr; + } + } + } + + [FieldOffset(16)] // size = 4 + public PatternMatching pattern_matching; + + [FieldOffset(24)] // size = 16 + public CArrayc_char _models; + + public Span models + { + get + { + fixed (KeysClause* @this = &this) + { + var span = new Span(@this->_models.data, (int)@this->_models.data_len); + return span.ToArray().Select(str => CString.ToString(str)).ToArray(); + } + } + + set + { + var strings = value.ToArray().Select(str => CString.FromString(str)).ToArray(); + _models = new CArrayc_char(); + _models.data_len = (UIntPtr)value.Length; + fixed (CString* ptr = strings) + { + _models.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 24, Pack = 8)] + public struct Member + { + [FieldOffset(0)] // size = 8 + public CString name_; + + public string name + { + get + { + return CString.ToString(name_); + } + set + { + name_ = CString.FromString(value); + } + } + + [FieldOffset(8)] // size = 8 + public Ty* _ty; + + public Ty ty + { + get + { + return *_ty; + } + } + + [FieldOffset(16)] // size = 1 + public CBool key; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 72, Pack = 8)] + public struct MemberClause + { + [FieldOffset(0)] // size = 8 + public CString model_; + + public string model + { + get + { + return CString.ToString(model_); + } + set + { + model_ = CString.FromString(value); + } + } + + [FieldOffset(8)] // size = 8 + public CString member_; + + public string member + { + get + { + return CString.ToString(member_); + } + set + { + member_ = CString.FromString(value); + } + } + + [FieldOffset(16)] // size = 4 + public ComparisonOperator operator_; + + [FieldOffset(24)] // size = 48 + public MemberValue value; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 48, Pack = 8)] + public struct MemberValue + { + [FieldOffset(0)] // size = 4 + public MemberValue_Tag tag; + + [FieldOffset(8)] // size = 40 + public Primitive primitive; + + [FieldOffset(8)] // size = 8 + public CString @string_; + + public string @string + { + get + { + return CString.ToString(@string_); + } + set + { + @string_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct MemberValue_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 40 + public Primitive primitive; + + [FieldOffset(0)] // size = 8 + public CString @string_; + + public string @string + { + get + { + return CString.ToString(@string_); + } + set + { + @string_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct MemberValue_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 40 + public Primitive primitive; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct MemberValue_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public CString @string_; + + public string @string + { + get + { + return CString.ToString(@string_); + } + set + { + @string_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 152, Pack = 8)] + public struct ModelMetadata + { + [FieldOffset(0)] // size = 48 + public Ty schema; + + [FieldOffset(48)] // size = 8 + public CString namespace__; + + public string namespace_ + { + get + { + return CString.ToString(namespace__); + } + set + { + namespace__ = CString.FromString(value); + } + } + + [FieldOffset(56)] // size = 8 + public CString name_; + + public string name + { + get + { + return CString.ToString(name_); + } + set + { + name_ = CString.FromString(value); + } + } + + [FieldOffset(64)] // size = 4 + public uint packed_size; + + [FieldOffset(68)] // size = 4 + public uint unpacked_size; + + [FieldOffset(72)] // size = 32 + public FieldElement class_hash; + + [FieldOffset(104)] // size = 32 + public FieldElement contract_address; + + [FieldOffset(136)] // size = 16 + public CArrayFieldElement _layout; + + public Span layout + { + get + { + fixed (ModelMetadata* @this = &this) + { + var span = new Span(@this->_layout.data, (int)@this->_layout.data_len); + return span; + } + } + + set + { + + _layout = new CArrayFieldElement(); + _layout.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _layout.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct Primitive + { + [FieldOffset(0)] // size = 4 + public Primitive_Tag tag; + + [FieldOffset(8)] // size = 1 + public sbyte i8; + + [FieldOffset(8)] // size = 2 + public short i16; + + [FieldOffset(8)] // size = 4 + public int i32; + + [FieldOffset(8)] // size = 8 + public long i64; + + [FieldOffset(8)] // size = 16 + public fixed byte _i128[16]; // uint8_t[16] + + public Span i128 + { + get + { + fixed (Primitive* @this = &this) + { + var pointer = &@this->_i128[0]; + var span = new Span(pointer, 16); + return span; + } + } + + set + { + fixed (Primitive* @this = &this) + { + var pointer = &@this->_i128[0]; + var span = new Span(pointer, 16); + value.CopyTo(span); + } + } + } + + [FieldOffset(8)] // size = 1 + public byte u8; + + [FieldOffset(8)] // size = 2 + public ushort u16; + + [FieldOffset(8)] // size = 4 + public uint u32; + + [FieldOffset(8)] // size = 8 + public ulong u64; + + [FieldOffset(8)] // size = 16 + public fixed byte _u128[16]; // uint8_t[16] + + public Span u128 + { + get + { + fixed (Primitive* @this = &this) + { + var pointer = &@this->_u128[0]; + var span = new Span(pointer, 16); + return span; + } + } + + set + { + fixed (Primitive* @this = &this) + { + var pointer = &@this->_u128[0]; + var span = new Span(pointer, 16); + value.CopyTo(span); + } + } + } + + [FieldOffset(8)] // size = 32 + public fixed byte _u256[32]; // uint64_t[4] + + public Span u256 + { + get + { + fixed (Primitive* @this = &this) + { + var pointer = &@this->_u256[0]; + var span = new Span(pointer, 4); + return span; + } + } + + set + { + fixed (Primitive* @this = &this) + { + var pointer = &@this->_u256[0]; + var span = new Span(pointer, 4); + value.CopyTo(span); + } + } + } + + [FieldOffset(8)] // size = 4 + public uint u_size; + + [FieldOffset(8)] // size = 1 + public CBool bool_; + + [FieldOffset(8)] // size = 32 + public FieldElement felt252; + + [FieldOffset(8)] // size = 32 + public FieldElement class_hash; + + [FieldOffset(8)] // size = 32 + public FieldElement contract_address; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 8)] + public struct Primitive_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 1 + public sbyte i8; + + [FieldOffset(0)] // size = 2 + public short i16; + + [FieldOffset(0)] // size = 4 + public int i32; + + [FieldOffset(0)] // size = 8 + public long i64; + + [FieldOffset(0)] // size = 16 + public fixed byte _i128[16]; // uint8_t[16] + + public Span i128 + { + get + { + fixed (Primitive_ANONYMOUS_FIELD1* @this = &this) + { + var pointer = &@this->_i128[0]; + var span = new Span(pointer, 16); + return span; + } + } + + set + { + fixed (Primitive_ANONYMOUS_FIELD1* @this = &this) + { + var pointer = &@this->_i128[0]; + var span = new Span(pointer, 16); + value.CopyTo(span); + } + } + } + + [FieldOffset(0)] // size = 1 + public byte u8; + + [FieldOffset(0)] // size = 2 + public ushort u16; + + [FieldOffset(0)] // size = 4 + public uint u32; + + [FieldOffset(0)] // size = 8 + public ulong u64; + + [FieldOffset(0)] // size = 16 + public fixed byte _u128[16]; // uint8_t[16] + + public Span u128 + { + get + { + fixed (Primitive_ANONYMOUS_FIELD1* @this = &this) + { + var pointer = &@this->_u128[0]; + var span = new Span(pointer, 16); + return span; + } + } + + set + { + fixed (Primitive_ANONYMOUS_FIELD1* @this = &this) + { + var pointer = &@this->_u128[0]; + var span = new Span(pointer, 16); + value.CopyTo(span); + } + } + } + + [FieldOffset(0)] // size = 32 + public fixed byte _u256[32]; // uint64_t[4] + + public Span u256 + { + get + { + fixed (Primitive_ANONYMOUS_FIELD1* @this = &this) + { + var pointer = &@this->_u256[0]; + var span = new Span(pointer, 4); + return span; + } + } + + set + { + fixed (Primitive_ANONYMOUS_FIELD1* @this = &this) + { + var pointer = &@this->_u256[0]; + var span = new Span(pointer, 4); + value.CopyTo(span); + } + } + } + + [FieldOffset(0)] // size = 4 + public uint u_size; + + [FieldOffset(0)] // size = 1 + public CBool bool_; + + [FieldOffset(0)] // size = 32 + public FieldElement felt252; + + [FieldOffset(0)] // size = 32 + public FieldElement class_hash; + + [FieldOffset(0)] // size = 32 + public FieldElement contract_address; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 1, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 1 + public sbyte i8; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 2, Pack = 2)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 2 + public short i16; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 8)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD10 + { + [FieldOffset(0)] // size = 32 + public fixed byte _u256[32]; // uint64_t[4] + + public Span u256 + { + get + { + fixed (Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD10* @this = &this) + { + var pointer = &@this->_u256[0]; + var span = new Span(pointer, 4); + return span; + } + } + + set + { + fixed (Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD10* @this = &this) + { + var pointer = &@this->_u256[0]; + var span = new Span(pointer, 4); + value.CopyTo(span); + } + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 4, Pack = 4)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD11 + { + [FieldOffset(0)] // size = 4 + public uint u_size; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 1, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD12 + { + [FieldOffset(0)] // size = 1 + public CBool bool_; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD13 + { + [FieldOffset(0)] // size = 32 + public FieldElement felt252; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD14 + { + [FieldOffset(0)] // size = 32 + public FieldElement class_hash; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD15 + { + [FieldOffset(0)] // size = 32 + public FieldElement contract_address; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 4, Pack = 4)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD2 + { + [FieldOffset(0)] // size = 4 + public int i32; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD3 + { + [FieldOffset(0)] // size = 8 + public long i64; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD4 + { + [FieldOffset(0)] // size = 16 + public fixed byte _i128[16]; // uint8_t[16] + + public Span i128 + { + get + { + fixed (Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD4* @this = &this) + { + var pointer = &@this->_i128[0]; + var span = new Span(pointer, 16); + return span; + } + } + + set + { + fixed (Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD4* @this = &this) + { + var pointer = &@this->_i128[0]; + var span = new Span(pointer, 16); + value.CopyTo(span); + } + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 1, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD5 + { + [FieldOffset(0)] // size = 1 + public byte u8; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 2, Pack = 2)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD6 + { + [FieldOffset(0)] // size = 2 + public ushort u16; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 4, Pack = 4)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD7 + { + [FieldOffset(0)] // size = 4 + public uint u32; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD8 + { + [FieldOffset(0)] // size = 8 + public ulong u64; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)] + public struct Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD9 + { + [FieldOffset(0)] // size = 16 + public fixed byte _u128[16]; // uint8_t[16] + + public Span u128 + { + get + { + fixed (Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD9* @this = &this) + { + var pointer = &@this->_u128[0]; + var span = new Span(pointer, 16); + return span; + } + } + + set + { + fixed (Primitive_ANONYMOUS_FIELD1_ANONYMOUS_FIELD9* @this = &this) + { + var pointer = &@this->_u128[0]; + var span = new Span(pointer, 16); + value.CopyTo(span); + } + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 104, Pack = 8)] + public struct Query + { + [FieldOffset(0)] // size = 4 + public uint limit; + + [FieldOffset(4)] // size = 4 + public uint offset; + + [FieldOffset(8)] // size = 88 + public COptionClause clause; + + [FieldOffset(96)] // size = 1 + public CBool dont_include_hashed_keys; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultAccount + { + [FieldOffset(0)] // size = 4 + public ResultAccount_Tag tag; + + [FieldOffset(8)] // size = 8 + public Account* _ok; + + public Account ok + { + get + { + return *_ok; + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultAccount_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Account* _ok; + + public Account ok + { + get + { + return *_ok; + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultAccount_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 8 + public Account* _ok; + + public Account ok + { + get + { + return *_ok; + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultAccount_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 24, Pack = 8)] + public struct ResultCArrayEntity + { + [FieldOffset(0)] // size = 4 + public ResultCArrayEntity_Tag tag; + + [FieldOffset(8)] // size = 16 + public CArrayEntity _ok; + + public Span ok + { + get + { + fixed (ResultCArrayEntity* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayEntity(); + _ok.data_len = (UIntPtr)value.Length; + fixed (Entity* ptr = value) + { + _ok.data = ptr; + } + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultCArrayEntity_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 16 + public CArrayEntity _ok; + + public Span ok + { + get + { + fixed (ResultCArrayEntity_ANONYMOUS_FIELD1* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayEntity(); + _ok.data_len = (UIntPtr)value.Length; + fixed (Entity* ptr = value) + { + _ok.data = ptr; + } + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultCArrayEntity_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 16 + public CArrayEntity _ok; + + public Span ok + { + get + { + fixed (ResultCArrayEntity_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayEntity(); + _ok.data_len = (UIntPtr)value.Length; + fixed (Entity* ptr = value) + { + _ok.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultCArrayEntity_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 24, Pack = 8)] + public struct ResultCArrayFieldElement + { + [FieldOffset(0)] // size = 4 + public ResultCArrayFieldElement_Tag tag; + + [FieldOffset(8)] // size = 16 + public CArrayFieldElement _ok; + + public Span ok + { + get + { + fixed (ResultCArrayFieldElement* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayFieldElement(); + _ok.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _ok.data = ptr; + } + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultCArrayFieldElement_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 16 + public CArrayFieldElement _ok; + + public Span ok + { + get + { + fixed (ResultCArrayFieldElement_ANONYMOUS_FIELD1* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayFieldElement(); + _ok.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _ok.data = ptr; + } + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultCArrayFieldElement_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 16 + public CArrayFieldElement _ok; + + public Span ok + { + get + { + fixed (ResultCArrayFieldElement_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayFieldElement(); + _ok.data_len = (UIntPtr)value.Length; + fixed (FieldElement* ptr = value) + { + _ok.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultCArrayFieldElement_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 24, Pack = 8)] + public struct ResultCArrayu8 + { + [FieldOffset(0)] // size = 4 + public ResultCArrayu8_Tag tag; + + [FieldOffset(8)] // size = 16 + public CArrayu8 _ok; + + public Span ok + { + get + { + fixed (ResultCArrayu8* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayu8(); + _ok.data_len = (UIntPtr)value.Length; + fixed (byte* ptr = value) + { + _ok.data = ptr; + } + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultCArrayu8_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 16 + public CArrayu8 _ok; + + public Span ok + { + get + { + fixed (ResultCArrayu8_ANONYMOUS_FIELD1* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayu8(); + _ok.data_len = (UIntPtr)value.Length; + fixed (byte* ptr = value) + { + _ok.data = ptr; + } + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultCArrayu8_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 16 + public CArrayu8 _ok; + + public Span ok + { + get + { + fixed (ResultCArrayu8_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0* @this = &this) + { + var span = new Span(@this->_ok.data, (int)@this->_ok.data_len); + return span; + } + } + + set + { + + _ok = new CArrayu8(); + _ok.data_len = (UIntPtr)value.Length; + fixed (byte* ptr = value) + { + _ok.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultCArrayu8_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct ResultFieldElement + { + [FieldOffset(0)] // size = 4 + public ResultFieldElement_Tag tag; + + [FieldOffset(8)] // size = 32 + public FieldElement ok; + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 8)] + public struct ResultFieldElement_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 32 + public FieldElement ok; + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 1)] + public struct ResultFieldElement_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 32 + public FieldElement ok; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultFieldElement_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultProvider + { + [FieldOffset(0)] // size = 4 + public ResultProvider_Tag tag; + + [FieldOffset(8)] // size = 8 + public Provider* _ok; + + public Provider ok + { + get + { + return *_ok; + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultProvider_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Provider* _ok; + + public Provider ok + { + get + { + return *_ok; + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultProvider_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 8 + public Provider* _ok; + + public Provider ok + { + get + { + return *_ok; + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultProvider_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 72, Pack = 8)] + public struct ResultSignature + { + [FieldOffset(0)] // size = 4 + public ResultSignature_Tag tag; + + [FieldOffset(8)] // size = 64 + public Signature ok; + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 64, Pack = 8)] + public struct ResultSignature_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 64 + public Signature ok; + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 64, Pack = 1)] + public struct ResultSignature_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 64 + public Signature ok; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultSignature_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultSubscription + { + [FieldOffset(0)] // size = 4 + public ResultSubscription_Tag tag; + + [FieldOffset(8)] // size = 8 + public Subscription* _ok; + + public Subscription ok + { + get + { + return *_ok; + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultSubscription_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Subscription* _ok; + + public Subscription ok + { + get + { + return *_ok; + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultSubscription_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 8 + public Subscription* _ok; + + public Subscription ok + { + get + { + return *_ok; + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultSubscription_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct ResultToriiClient + { + [FieldOffset(0)] // size = 4 + public ResultToriiClient_Tag tag; + + [FieldOffset(8)] // size = 8 + public ToriiClient* _ok; + + public ToriiClient ok + { + get + { + return *_ok; + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultToriiClient_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public ToriiClient* _ok; + + public ToriiClient ok + { + get + { + return *_ok; + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultToriiClient_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 8 + public ToriiClient* _ok; + + public ToriiClient ok + { + get + { + return *_ok; + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct ResultToriiClient_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct Resultbool + { + [FieldOffset(0)] // size = 4 + public Resultbool_Tag tag; + + [FieldOffset(8)] // size = 1 + public CBool ok; + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Resultbool_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 1 + public CBool ok; + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 1, Pack = 1)] + public struct Resultbool_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 1 + public CBool ok; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Resultbool_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct Resultc_char + { + [FieldOffset(0)] // size = 4 + public Resultc_char_Tag tag; + + [FieldOffset(8)] // size = 8 + public CString ok_; + + public string ok + { + get + { + return CString.ToString(ok_); + } + set + { + ok_ = CString.FromString(value); + } + } + + [FieldOffset(8)] // size = 8 + public Error err; + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Resultc_char_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public CString ok_; + + public string ok + { + get + { + return CString.ToString(ok_); + } + set + { + ok_ = CString.FromString(value); + } + } + + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Resultc_char_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 8 + public CString ok_; + + public string ok + { + get + { + return CString.ToString(ok_); + } + set + { + ok_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Resultc_char_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 8 + public Error err; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 64, Pack = 1)] + public struct Signature + { + [FieldOffset(0)] // size = 32 + public FieldElement r; + + [FieldOffset(32)] // size = 32 + public FieldElement s; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 24, Pack = 8)] + public struct Struct + { + [FieldOffset(0)] // size = 8 + public CString name_; + + public string name + { + get + { + return CString.ToString(name_); + } + set + { + name_ = CString.FromString(value); + } + } + + [FieldOffset(8)] // size = 16 + public CArrayMember _children; + + public Span children + { + get + { + fixed (Struct* @this = &this) + { + var span = new Span(@this->_children.data, (int)@this->_children.data_len); + return span; + } + } + + set + { + + _children = new CArrayMember(); + _children.data_len = (UIntPtr)value.Length; + fixed (Member* ptr = value) + { + _children.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 48, Pack = 8)] + public struct Ty + { + [FieldOffset(0)] // size = 4 + public Ty_Tag tag; + + [FieldOffset(8)] + public Struct struct_; + + [FieldOffset(8)] // size = 40 + public Primitive primitive; + + [FieldOffset(8)] // size = 32 + public Enum enum_; + + [FieldOffset(8)] // size = 16 + public CArrayTy _tuple; + + public Span tuple + { + get + { + fixed (Ty* @this = &this) + { + var span = new Span(@this->_tuple.data, (int)@this->_tuple.data_len); + return span; + } + } + + set + { + + _tuple = new CArrayTy(); + _tuple.data_len = (UIntPtr)value.Length; + fixed (Ty* ptr = value) + { + _tuple.data = ptr; + } + } + } + + [FieldOffset(8)] // size = 16 + public CArrayTy _array; + + public Span array + { + get + { + fixed (Ty* @this = &this) + { + var span = new Span(@this->_array.data, (int)@this->_array.data_len); + return span; + } + } + + set + { + + _array = new CArrayTy(); + _array.data_len = (UIntPtr)value.Length; + fixed (Ty* ptr = value) + { + _array.data = ptr; + } + } + } + + [FieldOffset(8)] // size = 8 + public CString byte_array_; + + public string byte_array + { + get + { + return CString.ToString(byte_array_); + } + set + { + byte_array_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Union")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct Ty_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 40 + public Primitive primitive; + + [FieldOffset(0)] // size = 32 + public Enum enum_; + + [FieldOffset(0)] // size = 16 + public CArrayTy _tuple; + + public Span tuple + { + get + { + fixed (Ty_ANONYMOUS_FIELD1* @this = &this) + { + var span = new Span(@this->_tuple.data, (int)@this->_tuple.data_len); + return span; + } + } + + set + { + + _tuple = new CArrayTy(); + _tuple.data_len = (UIntPtr)value.Length; + fixed (Ty* ptr = value) + { + _tuple.data = ptr; + } + } + } + + [FieldOffset(0)] // size = 16 + public CArrayTy _array; + + public Span array + { + get + { + fixed (Ty_ANONYMOUS_FIELD1* @this = &this) + { + var span = new Span(@this->_array.data, (int)@this->_array.data_len); + return span; + } + } + + set + { + + _array = new CArrayTy(); + _array.data_len = (UIntPtr)value.Length; + fixed (Ty* ptr = value) + { + _array.data = ptr; + } + } + } + + [FieldOffset(0)] // size = 8 + public CString byte_array_; + + public string byte_array + { + get + { + return CString.ToString(byte_array_); + } + set + { + byte_array_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 40, Pack = 8)] + public struct Ty_ANONYMOUS_FIELD1_ANONYMOUS_FIELD0 + { + [FieldOffset(0)] // size = 40 + public Primitive primitive; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 32, Pack = 8)] + public struct Ty_ANONYMOUS_FIELD1_ANONYMOUS_FIELD1 + { + [FieldOffset(0)] // size = 32 + public Enum enum_; + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct Ty_ANONYMOUS_FIELD1_ANONYMOUS_FIELD2 + { + [FieldOffset(0)] // size = 16 + public CArrayTy _tuple; + + public Span tuple + { + get + { + fixed (Ty_ANONYMOUS_FIELD1_ANONYMOUS_FIELD2* @this = &this) + { + var span = new Span(@this->_tuple.data, (int)@this->_tuple.data_len); + return span; + } + } + + set + { + + _tuple = new CArrayTy(); + _tuple.data_len = (UIntPtr)value.Length; + fixed (Ty* ptr = value) + { + _tuple.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 16, Pack = 8)] + public struct Ty_ANONYMOUS_FIELD1_ANONYMOUS_FIELD3 + { + [FieldOffset(0)] // size = 16 + public CArrayTy _array; + + public Span array + { + get + { + fixed (Ty_ANONYMOUS_FIELD1_ANONYMOUS_FIELD3* @this = &this) + { + var span = new Span(@this->_array.data, (int)@this->_array.data_len); + return span; + } + } + + set + { + + _array = new CArrayTy(); + _array.data_len = (UIntPtr)value.Length; + fixed (Ty* ptr = value) + { + _array.data = ptr; + } + } + } + + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)] + public struct Ty_ANONYMOUS_FIELD1_ANONYMOUS_FIELD4 + { + [FieldOffset(0)] // size = 8 + public CString byte_array_; + + public string byte_array + { + get + { + return CString.ToString(byte_array_); + } + set + { + byte_array_ = CString.FromString(value); + } + } + } + + [CNode(Kind = "Struct")] + [StructLayout(LayoutKind.Explicit, Size = 48, Pack = 8)] + public struct WorldMetadata + { + [FieldOffset(0)] // size = 32 + public FieldElement world_address; + + [FieldOffset(32)] // size = 16 + public CArrayCHashItemFieldElementModelMetadata _models; + + public Span models + { + get + { + fixed (WorldMetadata* @this = &this) + { + var span = new Span(@this->_models.data, (int)@this->_models.data_len); + return span; + } + } + + set + { + + _models = new CArrayCHashItemFieldElementModelMetadata(); + _models.data_len = (UIntPtr)value.Length; + fixed (CHashItemFieldElementModelMetadata* ptr = value) + { + _models.data = ptr; + } + } + } + + } + + [CNode(Kind = "Enum")] + public enum BlockId_Tag : int + { + Hash = 0, + Number = 1, + BlockTag_ = 2 + } + + [CNode(Kind = "Enum")] + public enum BlockTag : int + { + Latest = 0, + Pending = 1 + } + + [CNode(Kind = "Enum")] + public enum COptionClause_Tag : int + { + SomeClause = 0, + NoneClause = 1 + } + + [CNode(Kind = "Enum")] + public enum COptionFieldElement_Tag : int + { + SomeFieldElement = 0, + NoneFieldElement = 1 + } + + [CNode(Kind = "Enum")] + public enum Clause_Tag : int + { + Keys = 0, + CMember = 1, + Composite = 2 + } + + [CNode(Kind = "Enum")] + public enum ComparisonOperator : int + { + Eq = 0, + Neq = 1, + Gt = 2, + Gte = 3, + Lt = 4, + Lte = 5 + } + + [CNode(Kind = "Enum")] + public enum EntityKeysClause_Tag : int + { + HashedKeys = 0, + EntityKeys = 1 + } + + [CNode(Kind = "Enum")] + public enum LogicalOperator : int + { + And = 0, + Or = 1 + } + + [CNode(Kind = "Enum")] + public enum MemberValue_Tag : int + { + String = 0, + Primitive = 1 + } + + [CNode(Kind = "Enum")] + public enum PatternMatching : int + { + FixedLen = 0, + VariableLen = 1 + } + + [CNode(Kind = "Enum")] + public enum Primitive_Tag : int + { + I8 = 0, + I16 = 1, + I32 = 2, + I64 = 3, + I128 = 4, + U8 = 5, + U16 = 6, + U32 = 7, + U64 = 8, + U128 = 9, + U256 = 10, + USize = 11, + Bool = 12, + Felt252 = 13, + ClassHash = 14, + ContractAddress = 15 + } + + [CNode(Kind = "Enum")] + public enum ResultAccount_Tag : int + { + OkAccount = 0, + ErrAccount = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultCArrayEntity_Tag : int + { + OkCArrayEntity = 0, + ErrCArrayEntity = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultCArrayFieldElement_Tag : int + { + OkCArrayFieldElement = 0, + ErrCArrayFieldElement = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultCArrayu8_Tag : int + { + OkCArrayu8 = 0, + ErrCArrayu8 = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultFieldElement_Tag : int + { + OkFieldElement = 0, + ErrFieldElement = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultProvider_Tag : int + { + OkProvider = 0, + ErrProvider = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultSignature_Tag : int + { + OkSignature = 0, + ErrSignature = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultSubscription_Tag : int + { + OkSubscription = 0, + ErrSubscription = 1 + } + + [CNode(Kind = "Enum")] + public enum ResultToriiClient_Tag : int + { + OkToriiClient = 0, + ErrToriiClient = 1 + } + + [CNode(Kind = "Enum")] + public enum Resultbool_Tag : int + { + Okbool = 0, + Errbool = 1 + } + + [CNode(Kind = "Enum")] + public enum Resultc_char_Tag : int + { + Okc_char = 0, + Errc_char = 1 + } + + [CNode(Kind = "Enum")] + public enum Ty_Tag : int + { + Primitive_ = 0, + Struct_ = 1, + Enum_ = 2, + Tuple_ = 3, + Array_ = 4, + ByteArray = 5 + } + + [CNode(Kind = "OpaqueType")] + [StructLayout(LayoutKind.Sequential)] + public struct Account + { + } + + [CNode(Kind = "OpaqueType")] + [StructLayout(LayoutKind.Sequential)] + public struct Provider + { + } + + [CNode(Kind = "OpaqueType")] + [StructLayout(LayoutKind.Sequential)] + public struct Subscription + { + } + + [CNode(Kind = "OpaqueType")] + [StructLayout(LayoutKind.Sequential)] + public struct ToriiClient + { + } + + #endregion + } + +} diff --git a/Assets/Dojo/Runtime/bindings/client/dojo.gen.cs.meta b/Assets/Dojo/Runtime/bindings/client/dojo.gen.cs.meta new file mode 100644 index 00000000..e54a24b7 --- /dev/null +++ b/Assets/Dojo/Runtime/bindings/client/dojo.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45de9f924acb84ff2a96d02c261538e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Tests.meta b/Assets/Dojo/Tests.meta new file mode 100644 index 00000000..fa53f2c7 --- /dev/null +++ b/Assets/Dojo/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c0a2c1428dbf4814b4cf269abc35661 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Tests/Runtime.meta b/Assets/Dojo/Tests/Runtime.meta new file mode 100644 index 00000000..6453b3cc --- /dev/null +++ b/Assets/Dojo/Tests/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f23454e95b9b44809807856d112b37c2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef b/Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef new file mode 100644 index 00000000..5053db7e --- /dev/null +++ b/Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef @@ -0,0 +1,22 @@ +{ + "name": "DojoRuntimeTests", + "rootNamespace": "", + "references": [ + "GUID:1cfdd07e9f0f54188b58166d8196b85c", + "GUID:27619889b8ba8c24980f49ee34dbb44a", + "GUID:0acc523941302664db1f4e527237feb3" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": true, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef.meta b/Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef.meta new file mode 100644 index 00000000..da4ea7ad --- /dev/null +++ b/Assets/Dojo/Tests/Runtime/DojoRuntimeTests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 32e5d5389fb954cc29019acbcb8f738f +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Dojo/Tests/Runtime/DojoTests.cs b/Assets/Dojo/Tests/Runtime/DojoTests.cs new file mode 100644 index 00000000..b2055969 --- /dev/null +++ b/Assets/Dojo/Tests/Runtime/DojoTests.cs @@ -0,0 +1,223 @@ +using System; +using System.Linq; +using bottlenoselabs.C2CS.Runtime; +using dojo_bindings; +using NUnit.Framework; +using Dojo.Torii; +using Dojo.Starknet; +using UnityEditor.VersionControl; +using System.Diagnostics; +using UnityEngine; +using Debug = UnityEngine.Debug; +using UnityEngine.SceneManagement; +using UnityEngine.UIElements; + +public class Tests +{ + private readonly string toriiUrl = "http://0.0.0.0:8080"; + private readonly string rpcUrl = "http://0.0.0.0:5050"; + private readonly string relayUrl = "/ip4/127.0.0.1/tcp/9090"; + // private readonly string playerKey = "0x028cd7ee02d7f6ec9810e75b930e8e607793b302445abbdee0ac88143f18da20"; + private readonly FieldElement playerAddress = new FieldElement("0x6162896d1d7ab204c7ccac6dd5f8e9e7c25ecd5ae4fcb4ad32e57786bb46e03"); + private readonly FieldElement worldAddress = new FieldElement("0x07efebb0c2d4cc285d48a97a7174def3be7fdd6b7bd29cca758fa2e17e03ef30"); + private readonly FieldElement actionsAddress = new FieldElement("0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af"); + + private ToriiClient client; + private JsonRpcClient provider; + private Account account; + + // our callbacks will mutate these variables + // we can use this to check that the callback was called + // when our account spawns + private bool modelEntityUpdated = false; + private bool entityUpdated = false; + private bool eventMessageUpdated = false; + + [SetUp] + public void SetupTorii() + { + client = new ToriiClient(toriiUrl, rpcUrl, relayUrl, worldAddress, false); + + if (client == null) throw new Exception("client is null"); + } + + [SetUp] + public void SetupAccount() + { + provider = new JsonRpcClient(rpcUrl); + + var signer = new SigningKey("0x1800000000300000180000000000030000000000003006001800006600"); + + account = new Account(provider, signer, playerAddress); + } + + [Test] + public void TestAccountAddress() + { + var address = account.Address; + + Assert.That(address, Is.EqualTo(playerAddress)); + } + + // [Test] + // public void TestAccountChainId() + // { + // // var chainId = account.ChainId(); + + // // check chainid? + // } + + // [Test] + // public void TestAccountSetBlockId() + // { + // var blockId = new dojo.BlockId + // { + // tag = dojo.BlockId_Tag.BlockTag_, + // block_tag = dojo.BlockTag.Pending + // }; + + // account.SetBlockId(blockId); + // } + + [Test, Order(3)] + public async void TestAccountExecuteRaw() + { + dojo.Call call = new dojo.Call() + { + to = actionsAddress.Inner, + selector = "spawn" + }; + + var txnHash = await account.ExecuteRaw(new[] { call }); + + await provider.WaitForTransaction(txnHash); + + // We wait until our callback is called to mark our + var start = DateTime.Now; + // entity as updated. We timeout after 5 seconds. + while (!(entityUpdated && modelEntityUpdated) && DateTime.Now - start < TimeSpan.FromSeconds(5)) + { + } + + + if (entityUpdated != modelEntityUpdated) + { + Debug.LogWarning("Entity update status mismatch. One of the callbacks was not called."); + Debug.LogWarning($"entityUpdated ({entityUpdated}) != modelEntityUpdated ({modelEntityUpdated})"); + } + Assert.That(entityUpdated || modelEntityUpdated, Is.True); + + // Move to check for event message update + call = new dojo.Call() + { + to = actionsAddress.Inner, + selector = "move", + calldata = new dojo.FieldElement[] { new FieldElement(0).Inner } + }; + + txnHash = await account.ExecuteRaw(new[] { call }); + + await provider.WaitForTransaction(txnHash); + + // We wait until our callback is called to mark our + // entity as updated. We timeout after 5 seconds. + start = DateTime.Now; + // entity as updated. We timeout after 5 seconds. + while (!eventMessageUpdated && DateTime.Now - start < TimeSpan.FromSeconds(5)) + { + } + + Assert.That(eventMessageUpdated, Is.True); + } + + [Test] + public void TestWorldMetadata() + { + var worldMetadata = client.WorldMetadata(); + + // models should correspond to Moves and Position + var movesExists = false; + var positionExists = false; + foreach (var cHashItemCCharModelMetadata in worldMetadata.models) + { + var modelMetadata = cHashItemCCharModelMetadata.value; + switch (modelMetadata.name) + { + case "": + + case "Moves": + movesExists = true; + + Assert.That(modelMetadata.schema.tag, Is.EqualTo(dojo.Ty_Tag.Struct_)); + Assert.That(modelMetadata.schema.struct_.children[0].name, Is.EqualTo("player")); + Assert.That(modelMetadata.schema.struct_.children[1].name, Is.EqualTo("remaining")); + Assert.That(modelMetadata.schema.struct_.children[2].name, Is.EqualTo("last_direction")); + + // maybe worth verifying the field types? + + break; + case "Position": + positionExists = true; + + Assert.That(modelMetadata.schema.tag, Is.EqualTo(dojo.Ty_Tag.Struct_)); + Assert.That(modelMetadata.schema.struct_.children[0].name, Is.EqualTo("player")); + Assert.That(modelMetadata.schema.struct_.children[1].name, Is.EqualTo("vec")); + + // maybe worth verifying the field types? + + break; + } + } + + Assert.That(worldMetadata.world_address, Is.EqualTo(worldAddress.Inner)); + Assert.That(movesExists, Is.True); + Assert.That(positionExists, Is.True); + } + + [Test, Order(1)] + public void TestEntities() + { + var query = new Query(5, 0); + + var entities = client.Entities(query); + Assert.That(entities.Count, Is.GreaterThanOrEqualTo(1)); + } + + // Deprecated? + // [Test] + // public void TestModel() + // { + // var query = new dojo.KeysClause + // { + // model = "Moves", + // keys = new[] { playerKey } + // }; + + // var model = client.Model(query); + + // Assert.That(model.struct_.name, Is.EqualTo("Moves")); + // Assert.That(model.struct_.children[0].name, Is.EqualTo("player")); + // } + + [Test, Order(2)] + public void TestOnEntityStateUpdate() + { + ToriiEvents.OnEntityStateUpdateDelegate callback = (key, models) => + { + if (models.Length == 0) return; + entityUpdated = models[0].Members["player"] == playerAddress; + }; + ToriiEvents.Instance.OnEntityUpdated += callback; + } + + [Test, Order(2)] + public void TestOnEventMessageUpdate() + { + ToriiEvents.OnEventMessageUpdateDelegate callback = (key, models) => + { + if (models.Length == 0) return; + eventMessageUpdated = models[0].Members["player"] == playerAddress; + }; + ToriiEvents.Instance.OnEventMessageUpdated += callback; + } +} \ No newline at end of file diff --git a/Assets/Dojo/Tests/Runtime/DojoTests.cs.meta b/Assets/Dojo/Tests/Runtime/DojoTests.cs.meta new file mode 100644 index 00000000..7888e62e --- /dev/null +++ b/Assets/Dojo/Tests/Runtime/DojoTests.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7d3c3d153da442a7a7144ee6ce27b941 +timeCreated: 1701893385 \ No newline at end of file diff --git a/Assets/Spawn And Move.meta b/Assets/Spawn And Move.meta new file mode 100644 index 00000000..e3085c21 --- /dev/null +++ b/Assets/Spawn And Move.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 77f05577af439454291599ea893dffc1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/CameraFollow.cs b/Assets/Spawn And Move/CameraFollow.cs new file mode 100644 index 00000000..27ef36d3 --- /dev/null +++ b/Assets/Spawn And Move/CameraFollow.cs @@ -0,0 +1,54 @@ +using Dojo; +using UnityEngine; + +public class CameraFollow : MonoBehaviour +{ + public WorldManager worldManager; + public float height = 10.0f; // height of the camera above the center point + public float damping = 1.0f; // damping factor to smooth camera movement + public float speed = 10.0f; // speed of camera movement + + + void Update() + { + // all entities with the position model, + // we only want to consider those for "follow" + var entities = worldManager.Entities(); + + if (entities.Length > 0) + { + Vector3 centerPoint = GetCenterPoint(entities); + Vector3 offset = new Vector3(0, height, -height); + Vector3 desiredPosition = centerPoint + offset; + Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, damping * Time.deltaTime); + transform.position = smoothedPosition; + + transform.LookAt(centerPoint); + } + + // Camera control with mouse + if (Input.GetMouseButton(1)) + { + float mouseX = Input.GetAxis("Mouse X"); + float mouseY = Input.GetAxis("Mouse Y"); + + transform.RotateAround(GetCenterPoint(entities), Vector3.up, mouseX * speed); + transform.RotateAround(GetCenterPoint(entities), transform.right, -mouseY * speed); + } + } + + Vector3 GetCenterPoint(GameObject[] entities) + { + if (entities.Length == 1) + { + return entities[0].transform.position; + } + + var bounds = new Bounds(entities[0].transform.position, Vector3.zero); + for (int i = 0; i < entities.Length; i++) + { + bounds.Encapsulate(entities[i].transform.position); + } + return bounds.center; + } +} \ No newline at end of file diff --git a/Assets/Spawn And Move/CameraFollow.cs.meta b/Assets/Spawn And Move/CameraFollow.cs.meta new file mode 100644 index 00000000..903bead2 --- /dev/null +++ b/Assets/Spawn And Move/CameraFollow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9601f4ab467894a87a34f22f6b453eb8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/ChatManager.cs b/Assets/Spawn And Move/ChatManager.cs new file mode 100644 index 00000000..b1bdc46c --- /dev/null +++ b/Assets/Spawn And Move/ChatManager.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using Dojo; +using Dojo.Starknet; +using Dojo.Torii; +using dojo_bindings; +using Newtonsoft.Json; +using UnityEngine; +using UnityEngine.UI; + +public class ChatManager : MonoBehaviour +{ + public bool chatOpen = false; + public FieldElement channel = new FieldElement(0); + + public dojoExample.GameManager gameManager; + public WorldManager worldManager; + + private Transform chatScrollView; + private TMPro.TMP_InputField chatInput; + + // Start is called before the first frame update + async void Start() + { + chatInput = GetComponentInChildren(true); + chatInput.gameObject.SetActive(false); + + chatScrollView = transform.Find("Scroll View/Viewport/Content"); + } + + // Update is called once per frame + void Update() + { + if (Input.GetKeyUp(KeyCode.T)) + { + chatInput.gameObject.SetActive(true); + chatInput.GetComponent().ActivateInputField(); + chatOpen = true; + } + + // chat interactions below + if (!chatOpen) return; + // if we press enter, send message + if (Input.GetKeyUp(KeyCode.Return)) + { + SendMessage(chatInput.text); + chatInput.gameObject.SetActive(false); + chatInput.text = ""; + chatOpen = false; + } + + // if press esc. close chat + if (Input.GetKeyUp(KeyCode.Escape)) + { + chatInput.gameObject.SetActive(false); + chatInput.text = ""; + chatOpen = false; + } + } + + async void SendMessage(string message) + { + var account = gameManager.burnerManager.CurrentBurner ?? gameManager.masterAccount; + // random salt for the message + var randomBytes = new byte[28]; + RandomNumberGenerator.Fill(randomBytes); + + // copy to a 32 byte array + var salt = new byte[32]; + randomBytes.CopyTo(salt, 0); + + salt = salt.Reverse().ToArray(); + + var typed_data = TypedData.From(new ns_Message + { + identity = account.Address, + message = message, + channel = channel, + salt = new FieldElement(salt), + }); + + Debug.Log(JsonConvert.SerializeObject(typed_data)); + + FieldElement messageHash = typed_data.encode(account.Address); + Signature signature = account.Signer.Sign(messageHash); + + await worldManager.Publish(typed_data, signature.ToFeltArray()); + } +} diff --git a/Assets/Spawn And Move/ChatManager.cs.meta b/Assets/Spawn And Move/ChatManager.cs.meta new file mode 100644 index 00000000..9c51f50c --- /dev/null +++ b/Assets/Spawn And Move/ChatManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4245acacf3c4f4b789faaee65493eedf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Contracts.meta b/Assets/Spawn And Move/Contracts.meta new file mode 100644 index 00000000..08ca0075 --- /dev/null +++ b/Assets/Spawn And Move/Contracts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7a34f1e1d36964110b7f3df17dbde841 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Contracts/ns-actions.gen.cs b/Assets/Spawn And Move/Contracts/ns-actions.gen.cs new file mode 100644 index 00000000..22bdb384 --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-actions.gen.cs @@ -0,0 +1,177 @@ +// Generated by dojo-bindgen on Tue, 5 Nov 2024 17:50:16 +0000. Do not modify this file manually. +using System; +using System.Threading.Tasks; +using Dojo; +using Dojo.Starknet; +using UnityEngine; +using dojo_bindings; +using System.Collections.Generic; +using System.Linq; +using Enum = Dojo.Starknet.Enum; + +// System definitions for `ns-actions` contract +public class Actions : MonoBehaviour { + // The address of this contract + public string contractAddress; + + + // Call the `spawn` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task spawn(Account account) { + List calldata = new List(); + + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "spawn", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `move` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task move(Account account, Direction direction) { + List calldata = new List(); + calldata.Add(new FieldElement(Enum.GetIndex(direction)).Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "move", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `set_player_config` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task set_player_config(Account account, string name) { + List calldata = new List(); + calldata.AddRange(ByteArray.Serialize(name).Select(f => f.Inner)); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "set_player_config", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `reset_player_config` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task reset_player_config(Account account) { + List calldata = new List(); + + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "reset_player_config", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `set_player_server_profile` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task set_player_server_profile(Account account, uint server_id, string name) { + List calldata = new List(); + calldata.Add(new FieldElement(server_id).Inner); + calldata.AddRange(ByteArray.Serialize(name).Select(f => f.Inner)); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "set_player_server_profile", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `set_models` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task set_models(Account account, FieldElement seed, uint n_models) { + List calldata = new List(); + calldata.Add(seed.Inner); + calldata.Add(new FieldElement(n_models).Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "set_models", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `enter_dungeon` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task enter_dungeon(Account account, FieldElement dungeon_address) { + List calldata = new List(); + calldata.Add(dungeon_address.Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "enter_dungeon", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `set_test` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task set_test(Account account, ns_Test test) { + List calldata = new List(); + calldata.Add(new FieldElement(test.ok).Inner); + calldata.Add(new FieldElement(test.x).Inner); + calldata.Add(new FieldElement(test.y).Inner); + calldata.Add(new FieldElement(test.z).Inner); + calldata.Add(new FieldElement(test.a.high).Inner); + calldata.Add(new FieldElement(test.a.low).Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "set_test", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `upgrade` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task upgrade(Account account, FieldElement new_class_hash) { + List calldata = new List(); + calldata.Add(new_class_hash.Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "upgrade", + calldata = calldata.ToArray() + } + }); + } + +} + \ No newline at end of file diff --git a/Assets/Spawn And Move/Contracts/ns-actions.gen.cs.meta b/Assets/Spawn And Move/Contracts/ns-actions.gen.cs.meta new file mode 100644 index 00000000..6feb110e --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-actions.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4fd9ad215c314bb1944a6d6b467f464 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs b/Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs new file mode 100644 index 00000000..5c4fb432 --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs @@ -0,0 +1,51 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using System.Threading.Tasks; +using Dojo; +using Dojo.Starknet; +using UnityEngine; +using dojo_bindings; +using System.Collections.Generic; +using System.Linq; +using Enum = Dojo.Starknet.Enum; + +// System definitions for `ns-dungeon` contract +public class Dungeon : MonoBehaviour { + // The address of this contract + public string contractAddress; + + + // Call the `enter` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task enter(Account account) { + List calldata = new List(); + + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "enter", + calldata = calldata.ToArray() + } + }); + } + + + + // Call the `upgrade` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task upgrade(Account account, FieldElement new_class_hash) { + List calldata = new List(); + calldata.Add(new_class_hash.Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "upgrade", + calldata = calldata.ToArray() + } + }); + } + +} + \ No newline at end of file diff --git a/Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs.meta b/Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs.meta new file mode 100644 index 00000000..9ecab7a9 --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-dungeon.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1a69951e43d840fe80e0a266dc125c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs b/Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs new file mode 100644 index 00000000..b7cb3ca1 --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs @@ -0,0 +1,34 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using System.Threading.Tasks; +using Dojo; +using Dojo.Starknet; +using UnityEngine; +using dojo_bindings; +using System.Collections.Generic; +using System.Linq; +using Enum = Dojo.Starknet.Enum; + +// System definitions for `ns-mock_token` contract +public class Mock_token : MonoBehaviour { + // The address of this contract + public string contractAddress; + + + // Call the `upgrade` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task upgrade(Account account, FieldElement new_class_hash) { + List calldata = new List(); + calldata.Add(new_class_hash.Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "upgrade", + calldata = calldata.ToArray() + } + }); + } + +} + \ No newline at end of file diff --git a/Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs.meta b/Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs.meta new file mode 100644 index 00000000..f0fa1a1d --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-mock_token.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5f5cdb1324add48b281a8e49a0807d14 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Contracts/ns-others.gen.cs b/Assets/Spawn And Move/Contracts/ns-others.gen.cs new file mode 100644 index 00000000..ea2e66db --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-others.gen.cs @@ -0,0 +1,34 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using System.Threading.Tasks; +using Dojo; +using Dojo.Starknet; +using UnityEngine; +using dojo_bindings; +using System.Collections.Generic; +using System.Linq; +using Enum = Dojo.Starknet.Enum; + +// System definitions for `ns-others` contract +public class Others : MonoBehaviour { + // The address of this contract + public string contractAddress; + + + // Call the `upgrade` system with the specified Account and calldata + // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be confirmed. + public async Task upgrade(Account account, FieldElement new_class_hash) { + List calldata = new List(); + calldata.Add(new_class_hash.Inner); + + return await account.ExecuteRaw(new dojo.Call[] { + new dojo.Call{ + to = new FieldElement(contractAddress).Inner, + selector = "upgrade", + calldata = calldata.ToArray() + } + }); + } + +} + \ No newline at end of file diff --git a/Assets/Spawn And Move/Contracts/ns-others.gen.cs.meta b/Assets/Spawn And Move/Contracts/ns-others.gen.cs.meta new file mode 100644 index 00000000..f891c3f9 --- /dev/null +++ b/Assets/Spawn And Move/Contracts/ns-others.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f1e407e50a7e04802a83bf8e856174e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/GameManager.cs b/Assets/Spawn And Move/GameManager.cs new file mode 100644 index 00000000..39aec22b --- /dev/null +++ b/Assets/Spawn And Move/GameManager.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using bottlenoselabs.C2CS.Runtime; +using Dojo; +using Dojo.Starknet; +using dojo_bindings; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.UI; +using Object = System.Object; +using Random = UnityEngine.Random; + +// Fix to use Records in Unity ref. https://stackoverflow.com/a/73100830 +using System.ComponentModel; +namespace System.Runtime.CompilerServices +{ + [EditorBrowsable(EditorBrowsableState.Never)] + internal class IsExternalInit{} +} +namespace dojoExample +{ + public class GameManager : MonoBehaviour + { + [SerializeField] WorldManager worldManager; + [SerializeField] ChatManager chatManager; + + [SerializeField] WorldManagerData dojoConfig; + [SerializeField] GameManagerData gameManagerData; + + public BurnerManager burnerManager; + private Dictionary spawnedAccounts = new(); + public Actions actions; + + public JsonRpcClient provider; + public Account masterAccount; + + + void Start() + { + provider = new JsonRpcClient(dojoConfig.rpcUrl); + masterAccount = new Account(provider, new SigningKey(gameManagerData.masterPrivateKey), new FieldElement(gameManagerData.masterAddress)); + burnerManager = new BurnerManager(provider, masterAccount); + + worldManager.synchronizationMaster.OnEntitySpawned.AddListener(InitEntity); + foreach (var entity in worldManager.Entities()) + { + InitEntity(entity); + } + } + + async void Update() + { + // dont register inputs if our chat is open + if (chatManager.chatOpen) return; + + if (Input.GetKeyUp(KeyCode.E)) + { + spawnedAccounts[masterAccount.Address] = null; + var txHash = await actions.spawn(masterAccount); + } + + if (Input.GetKeyUp(KeyCode.Space)) + { + var burner = await burnerManager.DeployBurner(); + spawnedAccounts[burner.Address] = null; + var txHash = await actions.spawn(burner); + } + + if (Input.GetMouseButtonUp(0)) + { + var ray = Camera.main.ScreenPointToRay(Input.mousePosition); + var hit = Physics.Raycast(ray, out var hitInfo); + if (hit && hitInfo.transform.parent != null) + { + var entity = hitInfo.transform.parent; + ns_Position position; + entity.TryGetComponent(out position); + + if (position && spawnedAccounts.ContainsValue(entity.name)) + { + var previousBurner = burnerManager.CurrentBurner; + if (previousBurner != null) + { + worldManager.Entity(spawnedAccounts[previousBurner.Address]) + .GetComponent().textTag.color = Color.black; + } + + var burner = spawnedAccounts.First(b => b.Value == entity.name); + var burnerAddress = burner.Key; + var burnerInstance = burnerManager.Burners.First(b => b.Address == burnerAddress); + + position.textTag.color = Color.blue; + } + } + } + + if (Input.GetKeyDown(KeyCode.W)) + { + // coordinates are different between dojo world and unity + Move(new Direction.Down()); + } + else if (Input.GetKeyDown(KeyCode.A)) + { + Move(new Direction.Left()); + } + else if (Input.GetKeyDown(KeyCode.S)) + { + Move(new Direction.Up()); + } + else if (Input.GetKeyDown(KeyCode.D)) + { + Move(new Direction.Right()); + } + } + + private async void Move(Direction direction) + { + await actions.move(burnerManager.CurrentBurner ?? masterAccount, direction); + } + + private void InitEntity(GameObject entity) + { + // check if entity has position component + if (!entity.TryGetComponent(out ns_Position position)) return; + + var capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule); + // change color of capsule to a random color + capsule.GetComponent().material.color = Random.ColorHSV(); + capsule.transform.parent = entity.transform; + + foreach (var account in spawnedAccounts) + { + if (account.Value == null) + { + spawnedAccounts[account.Key] = entity.name; + break; + } + } + } + } + +} + diff --git a/Assets/Spawn And Move/GameManager.cs.meta b/Assets/Spawn And Move/GameManager.cs.meta new file mode 100644 index 00000000..55b2cd14 --- /dev/null +++ b/Assets/Spawn And Move/GameManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 607a463b8a907498380786d00fd65442 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/GameManagerData.asset b/Assets/Spawn And Move/GameManagerData.asset new file mode 100644 index 00000000..888d64f4 --- /dev/null +++ b/Assets/Spawn And Move/GameManagerData.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 383d2b450adbb055b96dab4340377ead, type: 3} + m_Name: GameManagerData + m_EditorClassIdentifier: + masterPrivateKey: 0xc5b2fcab997346f3ea1c00b002ecf6f382c5f9c9659a3894eb783c5320f912 + masterAddress: 0x127fd5f1fe78a71f8bcd1fec63e3fe2f0486b6ecd5c86a0466c3a21fa5cfcec diff --git a/Assets/Spawn And Move/GameManagerData.asset.meta b/Assets/Spawn And Move/GameManagerData.asset.meta new file mode 100644 index 00000000..66cea923 --- /dev/null +++ b/Assets/Spawn And Move/GameManagerData.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 22f53d4a93d2d44199b824f3780fe0ad +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/GameManagerData.cs b/Assets/Spawn And Move/GameManagerData.cs new file mode 100644 index 00000000..0123f48f --- /dev/null +++ b/Assets/Spawn And Move/GameManagerData.cs @@ -0,0 +1,8 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "GameManagerData", menuName = "ScriptableObjects/GameManagerData", order = 2)] +public class GameManagerData : ScriptableObject +{ + public string masterPrivateKey; + public string masterAddress; +} diff --git a/Assets/Spawn And Move/GameManagerData.cs.meta b/Assets/Spawn And Move/GameManagerData.cs.meta new file mode 100644 index 00000000..65556783 --- /dev/null +++ b/Assets/Spawn And Move/GameManagerData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 383d2b450adbb055b96dab4340377ead +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models.meta b/Assets/Spawn And Move/Models.meta new file mode 100644 index 00000000..f6eef832 --- /dev/null +++ b/Assets/Spawn And Move/Models.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3528cb466956f47c9bcf2e3b6cd8e965 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models/ns-Message.gen.cs b/Assets/Spawn And Move/Models/ns-Message.gen.cs new file mode 100644 index 00000000..94c8c25f --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Message.gen.cs @@ -0,0 +1,39 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; + +// Type definition for `core::option::Option::` enum +public abstract record Option() : Enum { + public record Some(A value) : Option; + public record None() : Option; +} + +// Model definition for `dojo_examples::models::Message` model +public class ns_Message : ModelInstance { + [ModelField("identity")] + public FieldElement identity; + + [ModelField("channel")] + public FieldElement channel; + + [ModelField("message")] + public string message; + + [ModelField("salt")] + public FieldElement salt; + + // Start is called before the first frame update + void Start() { + } + + // Update is called once per frame + void Update() { + } +} + + \ No newline at end of file diff --git a/Assets/Spawn And Move/Models/ns-Message.gen.cs.meta b/Assets/Spawn And Move/Models/ns-Message.gen.cs.meta new file mode 100644 index 00000000..c8853e1f --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Message.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18d933e97f7b2440d9c030315b902cf7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models/ns-MockToken.gen.cs b/Assets/Spawn And Move/Models/ns-MockToken.gen.cs new file mode 100644 index 00000000..a971e192 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-MockToken.gen.cs @@ -0,0 +1,28 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; +using BigInteger = System.Numerics.BigInteger; + +// Model definition for `dojo_examples::models::MockToken` model +public class ns_MockToken : ModelInstance { + [ModelField("account")] + public FieldElement account; + + [ModelField("amount")] + public BigInteger amount; + + // Start is called before the first frame update + void Start() { + } + + // Update is called once per frame + void Update() { + } +} + + \ No newline at end of file diff --git a/Assets/Spawn And Move/Models/ns-MockToken.gen.cs.meta b/Assets/Spawn And Move/Models/ns-MockToken.gen.cs.meta new file mode 100644 index 00000000..ab85d1a8 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-MockToken.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 355646c4df0cc4696b6d57b91c6cc1a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models/ns-Moves.gen.cs b/Assets/Spawn And Move/Models/ns-Moves.gen.cs new file mode 100644 index 00000000..d7a23c83 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Moves.gen.cs @@ -0,0 +1,47 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; + +// Type definition for `dojo_examples::models::MovesValue` struct +[Serializable] +public struct MovesValue { + public byte remaining; + public Direction last_direction; +} + +// Type definition for `dojo_examples::models::Direction` enum +public abstract record Direction() : Enum { + public record None() : Direction; + public record Left() : Direction; + public record Right() : Direction; + public record Up() : Direction; + public record Down() : Direction; +} + + +// Model definition for `dojo_examples::models::Moves` model +public class ns_Moves : ModelInstance { + [ModelField("player")] + public FieldElement player; + + [ModelField("remaining")] + public byte remaining; + + [ModelField("last_direction")] + public Direction last_direction; + + // Start is called before the first frame update + void Start() { + } + + // Update is called once per frame + void Update() { + } +} + + \ No newline at end of file diff --git a/Assets/Spawn And Move/Models/ns-Moves.gen.cs.meta b/Assets/Spawn And Move/Models/ns-Moves.gen.cs.meta new file mode 100644 index 00000000..ee17477e --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Moves.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 234c19253773c4135bf618c0ace5796d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs b/Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs new file mode 100644 index 00000000..94c05205 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs @@ -0,0 +1,50 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; + +// Type definition for `dojo_examples::models::PlayerConfigValue` struct +[Serializable] +public struct PlayerConfigValue { + public string name; + public PlayerItem[] items; + public Option favorite_item; +} + +// Type definition for `dojo_examples::models::PlayerItem` struct +[Serializable] +public struct PlayerItem { + public uint item_id; + public uint quantity; + public int score; +} + + +// Model definition for `dojo_examples::models::PlayerConfig` model +public class ns_PlayerConfig : ModelInstance { + [ModelField("player")] + public FieldElement player; + + [ModelField("name")] + public string name; + + [ModelField("items")] + public PlayerItem[] items; + + [ModelField("favorite_item")] + public Option favorite_item; + + // Start is called before the first frame update + void Start() { + } + + // Update is called once per frame + void Update() { + } +} + + \ No newline at end of file diff --git a/Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs.meta b/Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs.meta new file mode 100644 index 00000000..5b059961 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-PlayerConfig.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95bc3be73555741d4bbdb0d4f0ba7c21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models/ns-Position.gen.cs b/Assets/Spawn And Move/Models/ns-Position.gen.cs new file mode 100644 index 00000000..4d427ae7 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Position.gen.cs @@ -0,0 +1,61 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; +using UnityEngine; + +// Type definition for `dojo_examples::models::PositionValue` struct +[Serializable] +public struct PositionValue { + public Vec2 vec; +} + +// Type definition for `dojo_examples::models::Vec2` struct +[Serializable] +public struct Vec2 { + public uint x; + public uint y; +} + + +// Model definition for `dojo_examples::models::Position` model +public class ns_Position : ModelInstance { + [ModelField("player")] + public FieldElement player; + + [ModelField("vec")] + public Vec2 vec; + + // component fields + public TextMesh textTag; + public string shortPlayerAddress; + + void Start() + { + var target = new Vector3(vec.x, 0, vec.y); + gameObject.transform.position = target; + } + + void Update() + { + // our curent position is gameObject.transform.position + // move towards the target position + var step = 3.0f * Time.deltaTime; + // scale down our positions + Vector3 oldPosition = gameObject.transform.position; + var target = new Vector3(vec.x, oldPosition.y, vec.y); + gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, target, step); + + // if we are close enough to the target position, snap to it + if (Vector3.Distance(gameObject.transform.position, target) < 0.001f) + { + gameObject.transform.position = target; + } + } +} + + \ No newline at end of file diff --git a/Assets/Spawn And Move/Models/ns-Position.gen.cs.meta b/Assets/Spawn And Move/Models/ns-Position.gen.cs.meta new file mode 100644 index 00000000..696bbb65 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Position.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45c0a1fb0e691417d9a26e42e6984340 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs b/Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs new file mode 100644 index 00000000..2fe24567 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs @@ -0,0 +1,37 @@ +// Generated by dojo-bindgen on Mon, 4 Nov 2024 23:36:28 +0000. Do not modify this file manually. +using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; + +// Type definition for `dojo_examples::models::ServerProfileValue` struct +[Serializable] +public struct ServerProfileValue { + public string name; +} + + +// Model definition for `dojo_examples::models::ServerProfile` model +public class ns_ServerProfile : ModelInstance { + [ModelField("player")] + public FieldElement player; + + [ModelField("server_id")] + public uint server_id; + + [ModelField("name")] + public string name; + + // Start is called before the first frame update + void Start() { + } + + // Update is called once per frame + void Update() { + } +} + + \ No newline at end of file diff --git a/Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs.meta b/Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs.meta new file mode 100644 index 00000000..1f27ee97 --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-ServerProfile.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5abe444062e6f408f9c1bb3d38113765 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Models/ns-Test.gen.cs b/Assets/Spawn And Move/Models/ns-Test.gen.cs new file mode 100644 index 00000000..c52c362a --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Test.gen.cs @@ -0,0 +1,52 @@ +// Generated by dojo-bindgen on Tue, 5 Nov 2024 17:50:16 +0000. Do not modify this file manually. +using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; +using BigInteger = System.Numerics.BigInteger; +using UnityEngine; +using Newtonsoft.Json; + +// Type definition for `core::integer::u256` struct +[Serializable] +public struct U256 { + public BigInteger low; + public BigInteger high; +} + + +// Model definition for `dojo_examples::models::Test` model +public class ns_Test : ModelInstance { + [ModelField("ok")] + public uint ok; + + [ModelField("x")] + public long x; + + [ModelField("y")] + public BigInteger y; + + [ModelField("z")] + public BigInteger z; + + [ModelField("a")] + public U256 a; + + // Start is called before the first frame update + void Start() { + Debug.Log($"ok: {ok}"); + Debug.Log($"x: {x}"); + Debug.Log($"y: {y}"); + Debug.Log($"z: {z}"); + Debug.Log($"a: {JsonConvert.SerializeObject(a)}"); + } + + // Update is called once per frame + void Update() { + } +} + + \ No newline at end of file diff --git a/Assets/Spawn And Move/Models/ns-Test.gen.cs.meta b/Assets/Spawn And Move/Models/ns-Test.gen.cs.meta new file mode 100644 index 00000000..5cb63a9d --- /dev/null +++ b/Assets/Spawn And Move/Models/ns-Test.gen.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19be8c27493a84425a322ec031b0fffe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Scenes.meta b/Assets/Spawn And Move/Scenes.meta new file mode 100644 index 00000000..309228bd --- /dev/null +++ b/Assets/Spawn And Move/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 196f7cf3de88d42c695e90b623202ead +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Scenes/SampleScene.meta b/Assets/Spawn And Move/Scenes/SampleScene.meta new file mode 100644 index 00000000..3ed78423 --- /dev/null +++ b/Assets/Spawn And Move/Scenes/SampleScene.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4344ed9b4430848a68e700fe9357af07 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Scenes/SampleScene.unity b/Assets/Spawn And Move/Scenes/SampleScene.unity new file mode 100644 index 00000000..f6942f7f --- /dev/null +++ b/Assets/Spawn And Move/Scenes/SampleScene.unity @@ -0,0 +1,2080 @@ +%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: 705507994} + m_IndirectSpecularColor: {r: 0.44657886, g: 0.49641275, b: 0.5748176, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + 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: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 500 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 2 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + 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 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1001 &36216327 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 184210, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_Name + value: UnityMainThreadDispatcher + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_Pivot.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_Pivot.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMax.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMax.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMin.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMin.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_SizeDelta.x + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchoredPosition.x + value: -50 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchoredPosition.y + value: -50 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} +--- !u!1 &216707119 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 216707120} + - component: {fileID: 216707122} + - component: {fileID: 216707121} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &216707120 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 216707119} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1621275504} + 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!114 &216707121 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 216707119} + 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: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + 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 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &216707122 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 216707119} + m_CullTransparentMesh: 1 +--- !u!1 &420577426 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 420577427} + - component: {fileID: 420577430} + - component: {fileID: 420577429} + - component: {fileID: 420577428} + m_Layer: 5 + m_Name: Scroll View + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &420577427 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 420577426} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 543268536} + - {fileID: 1031934510} + m_Father: {fileID: 1082089484} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 9.759944, y: 0} + m_SizeDelta: {x: 19.520113, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &420577428 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 420577426} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1aa08ab6e0800fa44ae55d278d1423e3, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 1436812977} + m_Horizontal: 0 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 543268536} + m_HorizontalScrollbar: {fileID: 0} + m_VerticalScrollbar: {fileID: 1031934511} + m_HorizontalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 2 + m_HorizontalScrollbarSpacing: -3 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &420577429 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 420577426} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 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 &420577430 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 420577426} + m_CullTransparentMesh: 1 +--- !u!1 &421222451 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 421222452} + - component: {fileID: 421222455} + - component: {fileID: 421222454} + - component: {fileID: 421222453} + m_Layer: 5 + m_Name: Placeholder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &421222452 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 421222451} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 951569879} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &421222453 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 421222451} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 1 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: -1 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &421222454 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 421222451} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Enter text... + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 2150773298 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 0.5} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 14 + m_fontSizeBase: 14 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 0 + m_fontSizeMax: 0 + m_fontStyle: 2 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &421222455 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 421222451} + m_CullTransparentMesh: 1 +--- !u!1 &462311468 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 462311472} + - component: {fileID: 462311471} + - component: {fileID: 462311470} + - component: {fileID: 462311469} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &462311469 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 462311468} + 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 &462311470 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 462311468} + 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 + m_PresetInfoIsWorld: 0 +--- !u!223 &462311471 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 462311468} + 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_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &462311472 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 462311468} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1082089484} + m_Father: {fileID: 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!1 &543268535 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 543268536} + - component: {fileID: 543268539} + - component: {fileID: 543268538} + - component: {fileID: 543268537} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &543268536 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543268535} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1436812977} + m_Father: {fileID: 420577427} + 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: 1} +--- !u!114 &543268537 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543268535} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!114 &543268538 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543268535} + 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: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10917, 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 &543268539 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 543268535} + m_CullTransparentMesh: 1 +--- !u!1 &691548659 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + m_PrefabInstance: {fileID: 1014796538906876319} + m_PrefabAsset: {fileID: 0} +--- !u!1 &705507993 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 705507995} + - component: {fileID: 705507994} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &705507994 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.802082 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 1 + 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_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &705507995 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 705507993} + serializedVersion: 2 + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &922574854 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 922574857} + - component: {fileID: 922574856} + - component: {fileID: 922574855} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &922574855 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 922574854} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &922574856 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 922574854} + 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 &922574857 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 922574854} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &951569878 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 951569879} + - component: {fileID: 951569880} + m_Layer: 5 + m_Name: Text Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &951569879 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 951569878} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 421222452} + - {fileID: 1467797445} + m_Father: {fileID: 1909232410} + 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.4999962} + m_SizeDelta: {x: -20, y: -13} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &951569880 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 951569878} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3312d7739989d2b4e91e6319e9a96d76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: {x: -8, y: -5, z: -8, w: -5} + m_Softness: {x: 0, y: 0} +--- !u!1 &963194225 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 963194228} + - component: {fileID: 963194227} + - component: {fileID: 963194226} + - component: {fileID: 963194229} + 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 &963194226 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 +--- !u!20 &963194227 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + 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 &963194228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + serializedVersion: 2 + m_LocalRotation: {x: 0.5697441, y: -0, z: -0, w: 0.82182217} + m_LocalPosition: {x: 0, y: 15.93, z: -6.8} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 69.465, y: 0, z: 0} +--- !u!114 &963194229 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 963194225} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9601f4ab467894a87a34f22f6b453eb8, type: 3} + m_Name: + m_EditorClassIdentifier: + worldManager: {fileID: 2019443015} + height: 10 + damping: 1 + speed: 10 +--- !u!1 &1031934509 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1031934510} + - component: {fileID: 1031934513} + - component: {fileID: 1031934512} + - component: {fileID: 1031934511} + 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 &1031934510 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1031934509} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1621275504} + m_Father: {fileID: 420577427} + 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: -17} + m_Pivot: {x: 1, y: 1} +--- !u!114 &1031934511 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1031934509} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2a4db7a114972834c8e4117be1d82ba3, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 0} + 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: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 216707121} + m_HandleRect: {fileID: 216707120} + m_Direction: 2 + m_Value: 0 + m_Size: 1 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!114 &1031934512 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1031934509} + 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: 1, g: 1, b: 1, a: 0} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 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 &1031934513 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1031934509} + m_CullTransparentMesh: 1 +--- !u!1 &1082089483 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1082089484} + - component: {fileID: 1082089485} + m_Layer: 5 + m_Name: Chat + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1082089484 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1082089483} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 420577427} + - {fileID: 1909232410} + m_Father: {fileID: 462311472} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 148.1, y: -148.85} + m_SizeDelta: {x: 296.2, y: 297.7} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1082089485 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1082089483} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4245acacf3c4f4b789faaee65493eedf, type: 3} + m_Name: + m_EditorClassIdentifier: + chatOpen: 0 + channel: + hex: 0x0000000000000000000000000000000000000000000000000000000000000000 + gameManager: {fileID: 2019443018} + worldManager: {fileID: 2019443015} +--- !u!1 &1436812976 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1436812977} + - component: {fileID: 1436812979} + - component: {fileID: 1436812978} + - component: {fileID: 1436812980} + m_Layer: 5 + m_Name: Content + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1436812977 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1436812976} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 543268536} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 5, y: 0} + m_SizeDelta: {x: -5, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &1436812978 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1436812976} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 0, g: 0, b: 0, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1436812979 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1436812976} + m_CullTransparentMesh: 1 +--- !u!114 &1436812980 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1436812976} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 2 +--- !u!1 &1467797444 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1467797445} + - component: {fileID: 1467797447} + - component: {fileID: 1467797446} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1467797445 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1467797444} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 951569879} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1467797446 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1467797444} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: "\u200B" + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4281479730 + m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 14 + m_fontSizeBase: 14 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 0 + m_fontSizeMax: 0 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_enableExtraPadding: 1 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &1467797447 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1467797444} + m_CullTransparentMesh: 1 +--- !u!1 &1603019347 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1603019351} + - component: {fileID: 1603019350} + - component: {fileID: 1603019349} + - component: {fileID: 1603019348} + - component: {fileID: 1603019352} + m_Layer: 0 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!64 &1603019348 +MeshCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1603019347} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 5 + m_Convex: 0 + m_CookingOptions: 30 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1603019349 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1603019347} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, 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: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &1603019350 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1603019347} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1603019351 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1603019347} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.059959, y: -1, z: -0.089834} + m_LocalScale: {x: 579.44196, y: 1, z: 204.42252} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1603019352 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1603019347} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ab13a05e740f84a6d9c745e33f5bd407, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &1621275503 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1621275504} + 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 &1621275504 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1621275503} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 216707120} + m_Father: {fileID: 1031934510} + 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} +--- !u!1 &1909232409 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1909232410} + - component: {fileID: 1909232413} + - component: {fileID: 1909232412} + - component: {fileID: 1909232411} + m_Layer: 5 + m_Name: InputField (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1909232410 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1909232409} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 951569879} + m_Father: {fileID: 1082089484} + 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: -15.499954} + m_SizeDelta: {x: 0, y: 30.199997} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1909232411 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1909232409} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2da0c512f12947e489f739169773d7ca, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + 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: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1909232412} + m_TextViewport: {fileID: 951569879} + m_TextComponent: {fileID: 1467797446} + m_Placeholder: {fileID: 421222454} + m_VerticalScrollbar: {fileID: 0} + m_VerticalScrollbarEventHandler: {fileID: 0} + m_LayoutGroup: {fileID: 0} + m_ScrollSensitivity: 1 + m_ContentType: 0 + m_InputType: 0 + m_AsteriskChar: 42 + m_KeyboardType: 0 + m_LineType: 0 + m_HideMobileInput: 0 + m_HideSoftKeyboard: 0 + m_CharacterValidation: 0 + m_RegexValue: + m_GlobalPointSize: 14 + m_CharacterLimit: 0 + m_OnEndEdit: + m_PersistentCalls: + m_Calls: [] + m_OnSubmit: + m_PersistentCalls: + m_Calls: [] + m_OnSelect: + m_PersistentCalls: + m_Calls: [] + m_OnDeselect: + m_PersistentCalls: + m_Calls: [] + m_OnTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnEndTextSelection: + m_PersistentCalls: + m_Calls: [] + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] + m_OnTouchScreenKeyboardStatusChanged: + 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 + m_RichText: 1 + m_GlobalFontAsset: {fileID: 0} + m_OnFocusSelectAll: 1 + m_ResetOnDeActivation: 1 + m_RestoreOriginalTextOnEscape: 1 + m_isRichTextEditingAllowed: 0 + m_LineLimit: 0 + m_InputValidator: {fileID: 0} +--- !u!114 &1909232412 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1909232409} + 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: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10911, 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 &1909232413 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1909232409} + m_CullTransparentMesh: 1 +--- !u!114 &2019443015 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + m_PrefabInstance: {fileID: 1014796538906876319} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 691548659} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 85bbcaeafdf5e41c6a2f48ff65820b7d, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &2019443018 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 691548659} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 607a463b8a907498380786d00fd65442, type: 3} + m_Name: + m_EditorClassIdentifier: + worldManager: {fileID: 2019443015} + chatManager: {fileID: 1082089485} + dojoConfig: {fileID: 11400000, guid: 1d6a5fa48aab79f0084b213f6fc768c5, type: 2} + gameManagerData: {fileID: 11400000, guid: 22f53d4a93d2d44199b824f3780fe0ad, type: 2} + actions: {fileID: 2019443024} +--- !u!114 &2019443024 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 691548659} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c4fd9ad215c314bb1944a6d6b467f464, type: 3} + m_Name: + m_EditorClassIdentifier: + contractAddress: 0x058b83bea84766c5725c12e239c1ec9e1fde679ddf709b772fe7a8fdfd3cda27 +--- !u!1001 &1014796538906876319 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: relayUrl + value: /ip4/127.0.0.1/tcp/9090 + objectReference: {fileID: 0} + - target: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: worldAddress + value: 0x28f5999ae62fec17c09c52a800e244961dba05251f5aaf923afabd9c9804d1a + objectReference: {fileID: 0} + - target: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: relayWebrtcUrl + value: /ip4/127.0.0.1/udp/9091/webrtc-direct/certhash/uEiCAoeHQh49fCHDolECesXO0CPR7fpz0sv0PWVaIahzT4g + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: models.Array.size + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: models.Array.data[0] + value: + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: models.Array.data[1] + value: + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEventMessage.m_PersistentCalls.m_Calls.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 11500000, guid: 043ae0b8f2d5246499b92dea35147ab6, + type: 3} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEventMessage.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_Name + value: WorldManager + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + insertIndex: -1 + addedObject: {fileID: 2019443018} + - targetCorrespondingSourceObject: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + insertIndex: -1 + addedObject: {fileID: 2019443024} + m_SourcePrefab: {fileID: 100100000, guid: d2e25933f4d69473a8994ee7470b2610, type: 3} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 963194228} + - {fileID: 705507995} + - {fileID: 1014796538906876319} + - {fileID: 36216327} + - {fileID: 1603019351} + - {fileID: 462311472} + - {fileID: 922574857} diff --git a/Assets/Spawn And Move/Scenes/SampleScene.unity.meta b/Assets/Spawn And Move/Scenes/SampleScene.unity.meta new file mode 100644 index 00000000..952bd1e9 --- /dev/null +++ b/Assets/Spawn And Move/Scenes/SampleScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9fc0d4010bbf28b4594072e72b8655ab +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Spawn And Move/Scenes/SampleScene/LightingData.asset b/Assets/Spawn And Move/Scenes/SampleScene/LightingData.asset new file mode 100644 index 0000000000000000000000000000000000000000..e9ce5cae0ba24e3d6eb6faf2b4f216a1543abc24 GIT binary patch literal 18232 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%0Aazb^Wj{XI6hC*(azPw&U0<(M} z^&y1vqUJ3`r|+ajZ)VGDxQ&^%R?6u+yR2A*nnX)3OnA$Pw(8zC~?CD$-S3ORhX{M85hGl`T z(pF6cq*}F2nZ3rC!#nHvJ<+Ths?kzi32&4HCzl67qolVmW1i^eXmi3NEsVL|k|_tqkLHA`?bQ1 zggx!k_2dJrmFf>uNk$4g};|gUFLJ@}jZHG!M{8h${_J z7!sggi3!3IpaZlV-%~}R$l(an&REhv*m-{mAz6NihKNIc`UW9fL<+ZprUet|u|pah zkOq!4imf5;2FW@J@K+yfxJu=X7UD`*yxr6J9hy{CjEyM$6!EQ->DT2o{>F~m5F{XF z_{sBQ6H@Qnv<{Gb?|RcJxYXn@57ZF;8`&z^7+5J}r@F+6{7}jxAXW;%umm83kbuWo zC*kvHC*9KzGDTcQeE1EI6SR`#38xAg{Wnw-^v(VK$XFSa%h=-+0ricteWy#LmSLMC1L<(m`X z7arIhJrQYREHQd#`BYAP=ACEa&*muGXB!V5b@6k)H;r#|uC<i$Nd}&^1aC zKD0+zmx(#aH%?@ZCm<_zR{ZDNB<5u9Oy-dzyagB@Tm`RRweV6Cw^al?5>dpLnhq0a zXHy=HMmtThwElDSPfYzH-*%wNR^%lQ2F*a#?WW$(97TbuTUsMG8O}`Y&CCs1=g7f+ z?@+Ucnu1CYgV~gjg7B6u5>)K5mHYTjvG?}zUxa(SHgx@k5X#Ze1l!LD97{3*Ku%j0 z^d{*S&x9w$W|;)vacX$Rk5ABIo9=2;ML{_EG5(Tg{KYCpQp3|>853n1-JY<*ef{Qg zs}Kj%dqK{po<>!D#kjnScxHmLIbLTr<>!=k5JzSn-<-{fHi#;eb!-aAF9a#`xRkSL z*cC>ys(8hM!qj>6fqr*^#a;JK_{(i7GvOws{)m^JTuC(f<7yZVmCGAW90~H_)##(? z`WS9l=Y>R+XtyEeL2v?K1W14AU2pHQ+`>|jV!#vp>tvb2AyZ)X0a}H0?Z8i{AmS<* zdKHL{$On{|zefDwytFwqIe|AttiLn9kecdB2}Pv7jw3CsNGp@NlggX_!b{m@+^sTi zZ^${G7fVa;y-kDgsZ~8FhfP`R*Q2BrG*d__{R>hKF$gIzpj37_Bv?pf3LFOf1;#Jm z$;oCMW!>}pK+v_%!9ka7#UBSa8HT0lTVKvGGi1*8n_dvxOn5h;-r5R{NKMo0)Kf`P;>siJ_G z*gVHM?)&}ye*S~!hv#y;7>IM%b{^+Zuh;AFST*Y56HoToC5<2z%(te#>Yt>x$MKK1 z@v_#gmoC)~{|j38d)fpY1Xe0%juk~$t<%721~A}>JHhQI-oaY|+&Y}f4=XQe#svt@qYa}r>m}V34P#`%U&_h`CbF0 zNtSOVM2U8or{%g0rPAZMzg%fu?!rtp&f97^lnV*y$SO4y>YE3KO)*aR$>lQIuv%8^ zCS-}%#B`U(s&tnx#wFv7Xa@)BIiN6=MP?+^8^tAYk)OnP;L6B+Bok7LIlZRnd*-%D zw)(GW(WEKcw*a~wP77~u!z$#y3oXKp*TAk@b##vcS@xp2R}GDDm)c7=*=XmN_PAYj zFAvf1PiziT50Bnx_+W;P0UVwFqg4MG)|up%Qf$%myP(bX@8aV9eB-TP&qNAo6`slXXo0 zA-RuKpy_7;E>ulKMGAWAQpK{q@FSiVbssa-{6evPS2smo6YqW3GB5xEk)@V z2gWm(s@128ZZ*PVdZH3NBF4SZZ(zs##VR6%`6Z-Apu`XEzKqA27@g3M;mqLhNi+bm z@LSmY(I2oJs@+_|b=%v+E{|J!;dK3)Fl|Wtpm0W05%6lJS*dvG*)I1kXf1aI!IA+7 z{z%Xs!GEnM2S=?(b=yNR zO7Gi-uJMH|&n1U%8#Tu8vMPE%s~7U z(hPu4z!We63sAy6h#C_dU^^E1Q1^O4+_oI=^v3*Quo`$ZsWA}}?hG7_EQTC?#9xM- zjV)#gl7nD0(Jy{K*+s|T zC;ML;^+E>WT-*_JIaj;)1Tl09uqgAfG(2Ou;dZ{&1Sr!ppd<$}MJXWofbMWEx31BN z?`x0Y{3nZNg%c8$ZwpfTG&nB?PTHg_9DP;_Q)Ya8PK8tk6oeQh_4GO1jxBWiukzjP zKG#L(8br6ej&}`W*gM106|4{0$_!^AIrk%XAvwLcG{wVS_-^;}$=#c7?^bu5>)xCM zuk!vMc$Mci<7#*Aa7EpVFkzIW?ASwCS=xcBSAk)y1?2M|*&^n`KC%{~ZyVzLOCO}N zG{h-f$F}HdLw;V42~>qogz8c-MuzkZG8P=_A`<5`^}cuKyv84*r^{lbONx&jis_cO zA{k{6k~iFpqKM)eZU+8DIpOZ3@9D%&(fLOyS#Nl+lglF#goBv&&g{?uE2&4ZWpnu>7AIshWi*8X77yVC0v1N|4>vPu0EL5DN91rbi>`a(hz6mT zHJJD!Q8*@qL$Z)Pne--(zL0pPwENWvA)xzJy0lLte`^0Yz_@!LzogO!0Npwqn+aZl z&I>B3)>c-kc&Knr3*zovK>RphkT!2~CIhE|k`dU+=j~1D;>X=NJ0IMRl3Wy`p_FxJ z9~FzLiORAIjR+zO@lDiiyR`d@D)}=3to;tdXtNI}g2WvT>9qf4nl!zj+(@aiCO8$K;;%QB@4yF^KPtFStO0* ze=t)LoIM<3l7LH+MdhqvL4cCC3(|bBSEloj;iOuJ3X4JS9Ne_o?|U>xUALFNzc6=f zm!Pq?qrE*??sgKs3oc5%M?;cs`5ll>_n;6GXeSVCu|SIs<$2JngoF>(^dNwP(5x-u zUBF&pW~gtS-F{c378)IBxp4U+UIKapF`pb5B44bpwMG1lCXs%eIdr;ve28C>%vR(a zSL94yaN%(4$8>w-@j5E7g#tHQFLW8yNL`@e;S!_XU~**V=P7=RQf|3idHZ?Q4najS z{xIPq<~->P3m3Zx9V2}OPNln-R6+7theU?Sl%9JExkdz*zxt>GlHBn@+S0Xj_ z*<%(YM(<9a>S&w9vqulV3=i9MxlKzyJX~#qbd*TDfI*Xhl*a7X{Pp)A z>{ZM><$Q1mRsvf?Lz^f-BR8li1d4ovngW_mdVKUOrUD{L1a}&1(1gP9X67VZmN`TA zV2Q#c(8t|*@4UQv{x)sosB-1JnX`#z73n;@olS=oOMkeKc8yW<^QfWav zm)GS)BgS|EdTSpEmLPW8?h#r;sqPc{AU3Kvq{&$<%d!`FAW$F;@G8>a@Q=$+)*|_M z37C<6q3z*AqX|T9Y_N~I2!*JU!8!Nt?%I3KMtjL*O6Kmj5WNA4j!OIVYXZpJMQ=wf zEwC{ws3i4!5(4YjsO@4Z;RkijU>^?bJbB zwX)K{L&GoxAqN{B>X4z$A$tQ?6u{D$hdcw-4Nab<5jemwFTn8TvG0WM1f(;L01nwc zj8kHfWvMErp{nsm__A$$|ErJb3xL=11Yi`D$54d~h0YMfF;Il9Ac#YbNJlb0I37n# z+#wl4hRbQZ2`8uzxG?uwKm;d{2q!)g_^cQaLn`u;HxShZgMjpk+DN@hXXmMf6-bU6AU%Sx7uj3WETCvmz{i~6{kA{f zUecp6SOMpA7Asy#$$jP)Q{c9KUH2#Z-QJ&3=Qa~|e&lY5wHq^=i7#%Kn7Ao$g5rL* zC(tXS@M?3Y%1lO><~FJOvD)L^k9Tv)4U%6A8CFAJ&u_p$XF5n{G)Yd*OJNsZOlJ2? zW(QY97B$hc4y%yJH#OU9ARCW6Tqo#7bM|NGUd^y{&agb3 z^PY*9SrV6ZBUpP-icdIjt2uBhKa)|WRaVqk?{14=@49*JC;i=3(cg2M@1aZb_6>NX zYI4{|wi5kjF4htRojOBrVG0RP^Wff+xpN)#hX^Yv_|ZX)PW*HITVvkF_@l=G{rnQ5 zwjIz)@qPLs1Res3W9tvDcQJ;zp~;nH7_-1k5U>;x&=C>P4R+Ze+Y!m8aYdYxdJ-li za7PmA0vtjF_C5i2VWLz@)Xv{?b(^s_{$bu9rN2%ttnWS$%3EU4JZOKF(rYtjGFzJQ zY|d!f?MyShFfn9xAwyQ`Iqp7XaxOqWQJC1QpHP69euxIna~>!oJ2%`6-~34w7|sNVl23FOiN^;>#$T6=5A&J0K)cd7 zcmABD1Oqe;30AV)DgR;wB_#$1VpSE-M3l{p?hNR|x=O5z$5A$n?XQFNc0sXo9wR6D?(vOv!$hNu3q z0$KdxBa2drJc|c2I4hU?@_L69bB^p}JLo6ff?vt?3xrP$i4j3tvi$JxEiouXYe&9> z3fs%Sx4z-Jd%3cD4`AFygp4`ZMDRG;K|Vb#f{Y09W5`adxP-OVfF?t=I9{It%dw&^ zh{v+Ac?xV`Cg_v&=Wumx&@>VTqPh;Fm`05!sb)B5D3ta9&sb~rm_SQaab-JRS-KT+ zrqWlS2o(kN4?OOKSy7mt3Vm8!KA$R!CxLR6956`S8Fpo_1*1idKH1Hj$}@jubV7%g zUcZ^p%}tn~Cshc{7}0VH{f*myWyA3I>?Eu!hfK-j1x+})Z>XjLXLfm61eK*i(cwm= z8lAC4TQBUg)Xf&@jX~KAk_Tj6=m7p-x?VdkO{2&G&OSn*{P5FDm!L2a(mpLKoC6j# z$(t4f<|qH3jX7L*O}jri%n$1uQYAK1l{if`cNVIF1!r>Iya-G|NOuA?bl9uFoK!T7 z82c975QqyMQD9_XW9Z9v&pt{F9M<3&fqd{+@CXXt6O0fB7GYaL!7mvmL+!f9!JJ0( z0E3<(KG*}BE=W4olL>vBg%81!G(<@ns$&v3Pfs~d?*NX8g6`)T5LYA>ekWoVxF=No z=;8_fwV%CD(V$NSc_$VFUU;wc5fXsTtJ?|c(uEpeTOj<3!oXU7DB%Nu>xTFLTohsy zvQ2u!&rl)f?X5ZT2FWCqD76QZK0_mU0%vk2=Co$_tb@%3ak(YweYmP6D24GAle#o; z1uMLJBwlBo=2AV&_bw}EaA*mb*B(YLk#sxQm=1|MF6|96eEUYXgC~QAK@}T!m5`fG zGLgZ>>T5^|F#9;zT5|C0U|@uS6;|X}cX1vcJX|woA&G7&a1p7`o5iX zRZIMJWG5@i-qQP+<&zFs@eA!Xa^|Zia)jaRlAl zono%E@5s@is07CarwJ~$d~j9lh2-<=$VZ)_Kcx5eT+E(O_AvMc{|Is_jSj#8Ja~sV zB2Zv}z#$ejI8&AP1Dd*hYm0L8jUG3lH-@mG$#!4>+l?pCDEhgN>pz zC3NAe2WgX@r=D0Q=9dxn%^dpyOs23~Ir33V_o5VnQ3h3XxwMYnhY+C7p)tka9E7u) zVJK$B1x|_hlWI!4kDOoAVrUy|H%2S+uAtEL?v@&|<_VXJ%21EXY4zHy} z3y5+aRQ4)?L|Q8nw*)I{1w{rESp^wr+8`bU?Ap7O`B93kzEFy6$N)z$WN!>Rb~vT+ zrWMr0yZ~oH?4kNFYTTrNEUJq)tug8vFU^NMHKq#w?(+iO>4G;;G9XI|&gAT!*}W3) z3%+V`aitN`Cc-&M@KdUa;I2GE36`izhXZ`Dz=nyg4hM2pbLnZ|z6KhJfStUM1)i#k z9t??b0`|M(@HqiUp!@^U9<1OLgKq%_v$U|2v1mKwONi4{i4)iryTPn?xaWhlcrqm+ z*@HuzMj#=Hawcw0mv&B@t@q}tHrvg2oL6BhP`(djNyr0tUU%$i1!wjxjDCSn3}VDg z@npSts?S>X){n5ax8SC8+*>jlJW7rEz-85+y=AcGbn9(G04j9D`w23Ofrt})4Sd-( zpuo2utHX#Q9G4C-N@9qf!fj72RSPy~nEW49jfEqjDXs~hK-Cz(K<3IptYm7iU8N?o z3(C1j+95$47d6?npv6L_`RICv7<<7Hg9bTD^!;}I`|Y$miBhamy9vs` zwV0cGOu^CPGwHd6Nc=@{F>#r}*qqGZGXt8;R{Gs)WD>@cOtM%KVc;;pUK5$46$$yi zwZ*aZ`|sa#w8w8;=RG?kx-dg4%QsIiM=8H3q1u5F`8A{8KH7i$;}2*|b%tZuff9eZ z7s&C;bBW8V(K`D+e$n;8Bo<0~XLDX0eBh1MX)-@o!h5cyx?>J^>Qc?e5A?%N70KGb zof*P=1IkQKa9c4v3F8gTA#_Tc-I^1Oe7T7jrN7~YT;n1s$Lz#9!PE+CJ~AdOA(L)Q ziXuOn7(!y+;^bgUj?3@I!qkSj4I`1kI6X}BOUrX52WLK(ypFvQuKc$5QlDO~7(%ytSRn8|9=k%evI2UVdE&7o-^Yv-RdA>39!`Paq37ZX(6%6Ndc18)5Ii`d zcF=y#KX=YTyOYYmHFQ0y(+3Bl2|U^da=Uw+*SB9tQ0Gf30l+zP0A)H?TY;M%@vl_? z5g6Dok*Fd8Um*SkZ~^MBwgrJu3}`pLlHEp3>#S>of*c?*K@TxZTUk?H0`>Ko(qbAT zhHJxJHQHJ`16@J7K5Pmm8+2&ruGNKUSmg*9}Nhp^ZNsF%8u0yVQ>t zY1zZThT_M>^}v~R^f^9z7qQ*00F8w&25Z~f-yMJj!e@&<=zv!Em-QcD(aOJl2U6q> z4H-ILs4Il3N6Y<4XX+tzMi7J?cFU&?6M%yO5Det+Fnt7;>{I|GDHFZ}@r$Ug4C~am zZ2a>|{Nf}+7r%kUj3nIBzeX8Xi%!r|f4IdDK#cnXux>*_04P?jB8niHYtTk&8nL&_ z`~JEPR5)MfgM1uP*6np~ecRBP3J0QM!L2?KRJI~Oat)+sr*A=_4DHlVQmeBAL+paL zq!qfDojX{mwKcf(=h`5&tnmhMT+Seu3GWH$FLwnd5FT^*Fm{(o5X1*WJowKkUn_tG zD{R?NXy|*3=K*Jx*|H7nKASvan>=fkpj^@wTC_u<5E2se;JgeUDPJX!vr;%1u`t7= z*#SM9F~p@X@MRSfQ4fwqjEV|<@fs(ZvBQHf^8rq=Y=;L;LfLlH7UT63jl#dZ-0I)@ zvuA4~?{(Zv4Gsitmo+&%tlH!#*(fQ|8u$=1c;Oez-RqC)Xb)B2ts*UhL17;Rp1Ks% zHVi$PGwbEhWI0k>(}Z8n_VvcrdV?(Onf3bhC;@@&fw|?62^3Dp z-V%Z)jPWX0QM>`o7{eG}96^Z?wM2N$MRpfY5pe$y!YP)zIM>gqGK$xVC%pL97qoVx zR;Ku{<<*wgy(>$10hT86)ij`1KgDaL$sp)R{r&cx%ZC)mwnIP_k4+NU2zkhmsWlSv zkcFTmulb5ekTd@k<7NDaR*$I&@H@D)=v4+Ztrtrya_9x|%_2QA`qx)9Q^wB^5v^av z?#HWzbH?9&-^Dn)`43d95H1UP?}3F%MRz;jDr|rFC6S0D(G{kRvVn3Il#W!VCQOGL(K&Z=UVFGc0HBa`SvC6P<7a$ebi-*C{V899ds{1p#a$A z2oD05f%a8sH;N8CW|;5+p&n}LK)W(9Q7sC0D^O;u;;dYWSp$>{g3d$j3oUKn$m&EB z_f-Srs~X52#?Tlxg)r1Z+#dF0Sk<@m&jj1s+wPv=esmOeW4LM8kAbt8<%ZXAI{f)I zA0_}sS--f$()dhwX4S-}TV|^4J!nx`{c!QcR0f-F zV#(OVl)!00lQ?C~ljruIT>X8e`RgB5qrtH0xY;1~NC~b@h7r^BkMd_&e`#pKU7}}Q zRAz1d)IS27w}pO|PNlNe&)=egd{42Sw{|rKHhAuL0B*^Whu*0C#_x~voS#3HlyY9@ z;M$U|sIW`oBk`O;uP?B1z_xKQ5@L_!vN4Ganw{gKaRm7^&BGj|vanS1v3m&vH@95yZULJISYi-E)+w6R3GyMBXliR z&qotM1Vp0{LI~KF7oqXDQFQ)%G{hC4i__z-p_?xXG6%3lLu5f!ngSJCh$0|FUxV_| zh#PCoC3r(Yumo^101K(x1u3~a^Lgr0g>e-Ynxje1^#D@fCpg##$%4ypqH8#ib= zY!6KdVFT#Dto^tmqrcYI*H?M|**sE{J0w%6mw8#DCWu=;3*uU*@fneY*&w;@qkMDn zAwg^xO+C}daV9r`pFoMjx2#EDHOU?05<(Gp<%3{gMca^DNFNQk!V=l=*#cxKV7krC zmya9T(9^S;Dr)*+=KG3G#WAip0>2gmzVtMsDhr4(@y6-T&3qV`OWXXz_`cs}1_S%D zf&GF=4QFTt&eu8N!EzI7k}yZbg_KCvMUybj>&FkB1MY?nw)fQ~tD36YwWle^zMs9K zj&x^BnMGe;gddu|a3OU%8y~6J6%Nzb_$H1WnKpq?dzj+#{cL594NQQ8GQ%+<{>i&8 zfRk`xd6q;(LOBc=^fVWXaFQVHI%qg1Ko*5dxEb6VlRlXwL>Pk_j#dUP1YT-a^lbKz zs)=h{PwpJu#d5Ah9)wHUJ2);{pm7eQs>_lh)w>@A*SL^IRy5rQv_`Z*3YMg?LxxrJ z^*A4yNNORih@Yf+WtQtDKw+5f--)cHR6EG{FIU?Hj1MZ&NJbS6Yivc#33iP*J0S zzkwfZ=T~8kxaR?oHxDERpHkPqYxsyIcx_N?r3#F{F6o@fMxY}oOd^apv<8pWTjz^G zOab9=xk;gs42nepHU7m|RdHW{u$dd?IatWT-c1XCQwUu>PO9h{66Hkk%LF5A(@sSE zQ)bw;?Wpn5E&X5@e!6Z)qLsZZcjLnp7|4R=Vzmmhff^=T;&d%y>NRwvq$Gi$2@toC zT%3mURS{fvpvcn_>rKUox>o#*UTy_B|hCk%I#}b++w=uIPu&L-||~RLTTEEPr8qI z7mSpjuswU1{~p@3>x_~#A2N-$?~SBCBt8);zDI(4F#V&XPU1kE2QeT*`gg)V8(p9Q z1!_<#UpM?;>b>p6KihZ?Ts<`7!4=}?@G;Mq;>}#b`>6c_nBL>ccrD7+a1g|y{t?=2 z*YGfuk;Me^LhNA<3!59Xzj01DPI@-o;F`JlBi%j8-Nn;8(-P z2Gw)7T<(C&I(Ph(Yl*RTaJ6%SHiY*bZ(Lnj3$u&4Ec%iQ9!doC$f|%Q2m9_Kofo}X z6@$-rj~yrKKoqcQqMVulP6eC;k`eVlSs;p_okCX6LGKLx^#lXb2uDgCpj{KF`88j38^&P= z^+|5K2L3u|NgT7gMAr@R2CUzlOGi$3$^sZZXu1{9jI3~-tZlY4Gqd60;Wvk$`h#XT z%n1T!D8$RcZ9yP)Nd-oNe$yE^pdOj`6)xNxQ4t401PxmDCuVO@*Yqo-tqdYQgU6`U z6ZowN?gd?f`1gDG{fpffes(dq&P=Z!d38lGi^&Bx8rp}pGxe0S_U|qZ zO5`0}&SiwTRy!Faw3A7qZ7=G-;sf8WeZ>bsNQ=L6sCt58wP`nTjQ0KMQOnZZkOS!X z6xG>YigNgW%TIxM=!Hb=2TK%E7&21I=JT~L11;}VJ2 zAJi1vYvq|4tfWOBM<&VZ ztJ7EX!rLO&IzfZX7E%YtV5C%b2AE28FRVc&6Rmhb>V;7gh&|5mJT1f2L=%+DS6?7t z1{lFb&WoHGzfMIx>W@tSDHxr0PcYKkxumnhwg6JXSvI-p)Cf>5s}7Pw!S)e)htnGL zO_QRdF{@LA*{f@94BEkI^{{PAYNr}W<@VsK^`5Li0@<=6P!tkJS>&co6BB8i(LTiB zIN~viR~+*eRxM9Bz=URq-5+9O8XdGh!}JIh?9V`z{QHvb8P0}ye{z5et=lufNcT&V z&Oe#|cE5C6)UWAwd`%`*uGTy6x{d`dV}B$KRXCS+hX&S}9Wv6tLHXivWq z`?riv$?BD%pSudZPs!NK^9ON8%=3prbtnJo>9Ni?u3?s;wlm344KMA%kBCMQp~YLm z!mC4&&%oNQFja97E)jC{`>$w%wC(vt_973p4Be3AF|&U>MvGj;ctsWFY@==v+uQm1 zX%+|&c#9rA2cT3#4aAD4eqKO|N%U{kJ&Q^M)XJ4`CtA#~2%dO=KVH3K4HU`*P*g&o zW$54D34RBmH)0TJ_}@ahD8LhX(KPuZb!h@7LySU}840z6uELUV5x}fc0iKAte;cr! zfSahd*3|{URy05=V|(4A4Lej-l@MhGKs#A09a&LW-9@l@1Am&juo>f>Usd_q4&*?S1#fY3t?oBQT@^6j>LRXzg>y3e$pl+N*IhM@ZAg*ZCb< zG4rvLEJRNXf#`2wDP3wiKEvx9q@9LB_3#J5=Nt4SrIZNXSRd?JnlZeMKmi1=lk+JU ztjKPHF8K+`TttX0CL*NC3`{e6dKRPn(|FLLJE0$E5r;8I&Sd4~WKSdUOpD0fA5@Uf z;+NOs@eY-@pEFaq8u~!gQPQ`CLAnKIBw!zNMgZJs^zJC2h^CcGUQbYPko7GuT(NKK z%s|Wr?yAS?Qy6x1W;}Ata`&cEHq^ZHtcLBF9+1vZ2k>em zZ1$2V#Df|pKKKu1In6-bL^36#-njQV*LFMX19@*-`JlY9fkQVeZ?Vy)f7q zYdVOC4FpvdsX-OkzAwvQfepRHs7F(V-aS4NA2hMuC9H@`0-_-gY09a+0em%KZh{=l zT@;2d4Kurt#fiDX@fVS`{V_dhP@SDVvHL0!2CuRALxzc_wZdX3n2+f4Qgdw*yy3MA z5UEhX4ciL?Cs|>2&9*l4d+VQZJcEJ=#0#J6sIviR)7wV72FYlu1k<%SNx3M{`xq7~pb1_x1DaN7d@{lYi^xCb~OM+Fp6$Y)4Q zMWOgY`C7~YhSK8>GGywo?>}OQLS_OGyo$!{iB%zhLD>ymqaU}rgW+Y`@?N?`2YRet z%K&~NT50r8&Ypsy6v*mfJ`eS(Pyxp8X#@YivaDy<$nXY)x7ku*+Th^my3YcNfrU20eApc)f3GoVHWu0NA} zNJ5QEQYX8Z_He0RSUQC5<4VLV-#n&$SpjJirvC2NE^oW1ki$BuS|RO5lwk z*MP)&{(_k%0E;s{1^u<)Iy>ON0Z;%G3G6LFGXNbKLowC-X)#d)d58oZcoT|9hf{!Q zT~x3Om589xgyarD#hw)=-@CAu8}`z;_(19A)WU) zTm`%pw(=0@4|*v-N3J!Xb*?|~mxEg5K$J>k$Ty{}Q#b8jhMc--7Wx^qQ_Ue>rK>z` zQ-iA)dP4Na+^T39l`eJY_McQCor!Y{5TfXI*F%u6H;#h*l>3k5$p#BcA8q3pSd2@R zFg-Ld>H*UU10Qx1nhcLn&j%3CL6!Ev4sl=H0mA24Hs+$Zq4D5@|LnUJ}1$fJmTs_OkWYF~O=QM@sO=ce96M zQ&0c%{qJqm4)Ei0TmcfS6$yx)9V+Wi;pC0nhW31F>s}VVBY5x!%PD#W0J~9 zPRxW9@T=*nMAlU{jPYp;SmmIRC^`a+a^s7;-#y2loGBp)-EJi0O@{mp#(u!y58w*N zf;I4ZFL$2_t~&;rtY}As1FQt7$FN5tdJA;NsrzXi@QuMl3g$sFAC`t8j6ee@iVDgb zk-jN^!xN8f+ztSDyd5>rQoH1>??}}atA+Fzwb^xKQSgKUeiS8v@&J+_XhGk>d=#)1 zs(qjgxF?XP3luo`O{iuP(Vz$=BFy9j$Oi~2fti#^!mf00YYU|-aDbI~zi@O!SXd24 zAXgI*whiE;w#@f$ciOVXv;$-uejFNF;{+90l$D?=?49jlovrXaGrT|$`bJqWxHLO3 z5&&NSey^W2}jfQI{62~XQ_7L2PC+6NDsX0*dS~;YHZr+%3>Mq{UIJd z8zUF~+~4$AUj_eg`!itgElk7ulHjz?q$P0}KC;^6wp z@X}p)RXWmLu!Hg7lI$LFvn4qdDzYc8j{Fw9MBKG?x_s%_bN_jWT{owPFscHvHgCTmLToxzySy+ZV1b<^Fzf-v^7L>r>D8U>d7{Uyjl>n{JXE)Z$ zqmZAiz1;eys7=pQmM#*|-5*D1iDxQdmTlO*Yv03cMQgVl-vWeEbMN>=(oJL7Sjr4kufoDYMnp8j4M-{$yHJYylz;zjJqha!H&_+UxS zdq~{AhU1j=TY0^L*QVAbFjh-E1`NnC~R#fyX3B&y(&?e^8I(5kjN!EuE{gUHo3vF2OeK& z$W1C!D5QPlgcX9UcHDu}S4qvx$E;EvdpS;k<))`d_jM5Hzz9wq zjJ1-h4hdp_Uo#6)<@9+*JGJ|&3>SsNls*$DhtE_G_S1{OUc-uGQ?Q>CrH5Ed*)xU6 zoHjz5>}&#LKU^s^CNV^q<}4DI8CFd6!Mwin_2+Ih3}Oe6xK%GJW@UF^)*THhvtgoU zQzs_Lc+9fzCMyWVDhg1TqT0J&L#ds#r)}1G?d#9NI?S!lU+((650@|6;D_;Xfv)IU zm}^=rS~~(+tHzjXZparNvB+xbz%)6-D2h~s9Kxa57zfT>tM0r9vppcUfLY~lfP{79 zJsRZQEj|~j>t~5Zp#0k)yLer|TT2G2jZh@=gqE7u)iY8 zX!rG9eB# zRl^eHt=H}YRuVZGsB;3C4VGY&8?ZfPWri9%fNzab5RmW#XLIIER0Umd1Mkf@OfTlX zra{eAw^$QeW5s(zpk)RUPC)XhqRQ%nc{zM7I=AhMpuY<`I95o+fEt~l*<8s~QMq=g zgFFORBXVzxjZ~iiPkrAE3Fha}c|*SdSbScSy(|dwz0Kg$yKZvdqcmub4EPMdep^}Q zg65Bo2&*<^;j@GD$eg8 zuv3FCZ=ra5!}SK(D8S3pNv?b(w-+(V&A5?8=CsC0freGPukt@R&Wi4ErQct=@@DTD zrlA5Zpv^_#3R`4muY%8McC#c?%0OhqBPU(I1%74iLe6I$p=I!8uc0Ip6DE$-}(i}CzTy@tks;b z|LuVWOfxQHc|iJ42I2*~RP5 zoD_dN0{NhCQHMY2e;SORWq58-`^Kcq!0KR3q+v{C5Z!D$R|y*o@4+RX#m4W(8s6^i zZ>D3#GYJebN^k%mh>$*yJBbIrh6%}Ausi-Fp0kvYs%iQxIO`McQIX8~`6IWxKTy&g z<1H!W`tcS4az5QxZk|}gD+9q25y@c9$U%MyIp(|PHx8$PXP_PrU|at008_cXtw;kV z1br~&egS|Gix~8U2y^xYc(K5OA*=Dzs;&fsP$oqE$W#EbZw=6Wx@F{qkg+tjPYa`n zKgbH`+OTlp0OE71-Vr7To1XTgO!F=ZCm*A^i{Ow32I42b!2!h4qG-*HLMt$!|7x@d z&KNv-X)2YVcM%fIET%7*TNKeS!2H)K6|4vtWsV9Z3~&Ay{Ds z@(M{ff8&z~#g1NeBno$l@8>F~%N_N%w2#8Wrf6Qce5}SEObsbGqIWe8bTDHK%|P8a z<{(~mayQAoyMF2*roQ49tI(YAO^=>uN^Yu9bdA4>50t*)tAriG%&!7DPD?~+UnZLf z(*Qk3H(|b8UcY<{M58$7eMOcC%+}IEG-LEuS|ecsjB5IGW4KF^vvUUlh3IxrvEj1b zVawVoQy%jg9$ON5zK$MhY;NNY5nN*&P6s10d}Q${nUvAl*?;iso11R>Kun0@&^;E} zF&DD_w^gYYYF-2tx@wS~YLpe~gT;zH{Ym1oNqZ(xe8^lf9eUDJ8 zX$~5(xA2QdGSmM(Hr8O=D^UuEOUV4tdjKmE?6Y`)RgWuQ@gocpjb{tHEQ`IGq?M^f zNgq@fc!iZ`#mDI}f@+C6R(g8v^M-V17s_l7xoYUMG+j7YDiadO47Bsz_uJQxkSs3( zIu?6*{B%(q&_Xz10xGMuG?QLV%;991ML`qBs1MIeUJ`@psE-GY2=SO%oET6YdJM)t z)0Hx@=zpr9*n~X%lo`A?U%(cq zMId=K043@qoxfFKLjrhuS5sBjCUho+`R9^9&I0Dnb#;36NRz>gntnEL1+gw1nz39v>l5p zF`ohE35YtFQGrIiK$epRDUS~Lq4U~o$XY2!nA~+_<2P~{4uc1>;7->Z7DTDeHk+qW zm^XQ$(Hbz`ja1{$@p_?QnfvhzC}%dp)Qm=lb{L%j+Yil$2+7nwH`qv64B1KF*hy~$ zjhFS2PunBI7=y&ykm(@X0^=DLM6+R*^|c(K+%{r&|h<6TT+~Z@`WnekQizGOtK{W_k00B_n7N4p5O*hR`*BcGl{5+mo1 z6%GRqk!Y-~4^z3G?f0G&y5NjBDQe%;BHh`0_DsSq&Kt&6S9;MESE+>a=c4SmIf9*5 zDs`AGb(;3!YZaiYZ_VPzhD6BTR$lM<)4QuTa#FjC^}LR-^+up!H|TyKS@FOy_<|ZI z2#bW;C}D!my?#poBposJ`b>37FmCmU^`-Yn6XY62*jf^-%0ro`lW)4iguFN3l(%At zrecNW>OYziJ3Qk#4={+l!n4xTJu2eU2zGc8zxZ|iL;4Wk!SAn~bFBOedd(m_9A+Pp`sHfgR6XsXle-V#w zcy63b!w0P*4VgyZjCnvXXsu+PMfpY6I=wm{-g&b4JO|;bl>)KmiOUvFh zRTC&L^WXjw^AG^oKB59qs?nm!gS7+dW`Z7wEA2HtZ?fG7huXqN3ypu{oc{?O!0Lhm zR-t?!2PY|yyC=$qCZFn-untT>_bg+-Vq6a80a-8#uogH9#VjwNqT0kZCr$%eFMtYJ zfo~b1syx`z<93ePe^G)d7f>}o2)%_3{L{$`KqR;h0U{5a336CXM!ka!6cgGvMZk0o zRs-Jz77r6GO6?UmA&!GsPD4S^FaY8*%1oh5f47$Hc9;sT*DkdYt_xT|U`itjyg&s) zBvmmiyb-`ql}|weZ|%dv>5X~F?|~^P_v;OV_Q(k}p^xw;QUl?pf3D{+Q-jCMBm86?1l5Auo0lcEDFyf&24P5vvVt?Zn9ew@(yTN7N3iSW)3ZFfja`N}5ULRZ|Tw*=CvU=#kp+EIdMB4te z?Ct7m?cfuG6FS${+HZei)N|#3A6rdrtu1_J@Cm}5`q|lBthGTOA3DLuhpzJ9FY*`v zyHs?Y=KtqX=|0xOilH7@%rjaHM%S8-`W=J5G0)*dLM)?Hwz*={uwv7QdM^ucf~3Cq zNc{;$b1_46gH4C_q2}U4EZZ1neGH4!*27^8m$dg`IDYZ6jeTJo`z_8sY5mLS&!gY_ z*n8N1>9aq51mhC+pEdl#vtQb9X}_@HhC0VDEq03auNe0JF)Vwx^)Ds(?hE?>$FCIj zzOi58@I37IFX*%Pj{Txz8~fG4exKtPD|e>I566a9jozQJHJr944z0G;Kacj|IQI8p^x3Vyvs2iAF=E)^2{=BmjcqJp z4ExyhK6B`O#^}?I8TL}(Hx2vXhwPXwb}Wt!vq;v*aKMB8EgbtW?0TQs^>7^ev=8C= z^*&Mb79Z-&vF&dj)1&>Vxx}IQi44E5^XVZL$Du>}NQZU|o(=OEqc_K{GY9{QtoLb5 z3&Rd3p@m~d4?bmph@s}96|$C37t|N6)Zqb~Co*N=^!mxiPT9~SLiA~$1t4N5FYw;zzs;jCDVes@)8&r zt`|_$5p@4p_0LO8NcH>Jl`65$`flJ`$#~(R+9AzR9Q^xSit69TpKq;h{kgY=86Y`dz<5G0 z6J{R${Ii7_+WdR=<=?}1x2{D0!Ne~YFijE1q_s}Owq76ODXNPPbflR3^u`AX1Y>{N z`y`~^WOt~;DW1a=TUOTOGRx)GtCHB{F4{hbR=qqMJACm*=q>K_=S5YRaOs5tbFWy1 zA;n8sL%Sq~cBye4<_SH*fs5FiDECCtGhcOpD9|`6=sC%p|COb24P)$A&(UZfvnbll z%E6M32$9fft2exU( zJ}qbWiDr-6Xq%OLMjU~O^H$Wpd|MC#X8rZgDRO8;71 zuNDi}`LwwsT4#Fllhu^(vx&^Y3!PIj#bUpHhy8W?_p`r#?*AGQu4WTpUN)I)US=i~ zBc;i07^9<^dmzOk>Z182>A0h!uETXdZjIglsuG?4ms+H!m?z&*`l0;3x1Op?D%$x^ z8a!>5c59PIY7K3c)RYZXw@)g{p4=TQ2lM;Zw|~O@N=5hJp@NB5E#J4k9N&7r^@Ze| zVvh~7izGQG&w`l2*6h}WyN9ID&seWjvQAk{`ARx0$OefAjpNrOg2wGfD}!<@n%!&P zJPq^f-0dpVka5(c<3&xA_i3*OvPX6nzp!1F_}C$MNiDP})4bxWi={!?F~t;TnO=)l z;S;?Ulis<#ER(K=w1H!O-r7$`jdhj-9`gOdbLB8tPPA@8_PDuO#jxr~vtk+Chj%tB!V+t}q%<7XlAYzVBAR1XKJMfz zJF(L8q|h?&agcK!JXK!ya^5AyVb$S-c`IwkbXvX^O!%(su9_HkGU-#)HBfej>ZZY~j^y|~eT>jp2pliSA#Dj`ZdDt51&CS06hm@g*6S zj*YY8|JFb7=1WQQ=X3i?9=>i-GgJRR#$(!NpPB{m1SP)ItT&${a?HFhpK$cfbMy^p z9d?3?{v45-Wg~Bw62YSTZqtXkPD^1CfUxu{yJ-}7|(x;6Q( z*}UepKvue!=FTpYjA;M874ce8T%C{Kga?Kx+x1-D6A0gZ!9 z+)+!+SH{x8>g0=yhuV@w6>asdA5;A>kbXBvD5_(T?OdX$V(92pvvHu~lc!E{o_;kg zN}hhU4|r$lpUWjRr#~%{5;l%%QW#XtPHvT#5YpE<$@77gP@t3&K+`Vc;vQCOK(lhx zW4SKb?{00(@uQIu%*yZAyImi?U3O~-DYjChgO`3dUny7m0T$cl+50oAbXr=DiN|j}!N_>td9P^x0fi2j(@(BqYnR zmX6u5;uFVgcCf{gebm*H49mu*ly+Qo?=NU}tlLxc(D4Bx06d!pYg(DEhkF~<2*dA1 zYlCmJYD4z-zIy$o6?m@ye3oohaE4fnQwyuHaB!i-{( zKXqGg?`{2>6)unP-+g)H)fx`i)Sr&U zY<}_mN(DFgR(qJ(S+Ms&#bdCeJaB8`9;|c((1K@6J5W|(n>jWvWLOTF-mvPZ4A?5z z6gV^R#}^Km!W(eFv|hTh*`O3WEP;iW9K8?wr;rDY6_^L*% z?(`-Ww~nVy+6*0TwaWN%;(hbck(uv>S0rtgJoa#XSn$xX7>Eg93BC1Y_=f+b<1U>) zmY+XYzT1)TO(20XA{V;xT+THuXBVZ6pC;eM+%rVsuaA|!%ZDn>T~8@Q*ZMl%p04RH zJfyx><=QgrTRGX!tM))HeP^w^vAyNq%hI2uuBd8#kh&z{7%G`zl&xbX86urQN#$vu zT61x_hxIECIs1vUq|Ef({Q1G7hWwNFzp6#2yE@$eByiUgIVp6~Cii`3d4L?5O$W;` zc?6x1Bdgi|2Ato&UQM+o{ZRHqhtl2>Y>?#fEj#K4N_A~^bA0oge{XF?Zf*Ykdu#KL z#xr%NwVt*h-p+rN&X?$ZZ%^qmb#94idHi+az;sJ^OLzYSz2MD|Li)=Agoc4113w4- zK3dsZhO4H`=Kgw6JyIJfaamQWF~D@OFMAJ{W2kJ#U~NtOY8AJdyMj{1TA}%LfbwWU zz?A)Lg5{LWY^Bna^^~t+L{8_F^}7%lyr5K-+vav6x}$g9(ix1Sb{zE-1ZDol4Ff=Zin z8%&F;{?~7vf>;oKu=4r$&$jiKowIkZz`YoOx&Mt6;nCZm8JZb`8<;k(8(UjjH^90K z-u*vRy$3v%|NB2~%goMBviFYgF5{5x*vCrdF|)OlD0Hl{ci9{xjzdPnh&V<@WWFm! z%BUoLqVc=#)BF2){QpO1bK<`5>-D^@=k5jCGvHzY|FQ`!S z1J-)2^3nuW^~cX&!p|XwK583BWXEXx1#K0N`^oJA>>($eyhl_;l}|1pAz>mfURf!p zYrG4;cY*;n@+3d10@7J-Q6#SJO|1KKK@~S;VE{bau)?S1}O9e-<&FVwyA{Z_OY{1Hn^pPjzc#B1kb)9TfI zA0@~|Q2aai>0^#p;3sOaRVbUDa;8p=b5K3Z9%jxO@|Aua&v1`ce8eLvvc5C2zSOlX zl+)URx>^3ly~0Bxr4+ID7Wg;z76%laG2xwy3NZpD*Hyv_ZwKP*zYg@TwpW5Y$$JEuLUJiYuwcf{Ws3@M!!iq zw50M`#I@Bh1k>u-$gb=_$@;AM^fP5`!QNc0IAdkvpN`FHdk>HO?#{YS%OiZ00CMIP z>YVPk18ze@7%#&wq6(NXQd6sv<8f`clyS=An&)!N6_W3Q3Y${dSOobHri88J?Z|` z{bUmB&zcCeku4k~HUb7`)VKh2g2i*4kpyv`3}<9qJ3cvugjwYj+NZL71PMp6N@qsB zG9o`L@s-Hg4&X!J7=zl%LL&3d0)l)tx;%-u0n6fVFUXqs6goqEBGLFkIK}u(BtHvF z8BqfXNjQ>)sM#?4+D1;EqrOsue(JsrGlgSoUoVcXmW)Hn2(B4OAfXyVPTuzT|4O#) zzu^e5_UcL069`y{NTgOng7$$6)I5-RevIDgpzTQW;922@fOL#=Nt?L_=MR8dz@0Kg zI68fDbd`V17d!5!Y^2g9OWNs{85tcbF4+84`W&;MO@_MSitGrj;@0_n-FtsmkTIch zqFQVcb~a$_eZ;gLR_>R`1T05Lf$0q4y&IW=Dyuxn2oZ_I_FjTP`4l<&a1f5LUXe>f z2+b`C3`D6JlDB5wS-OLC= zU`e)Bfol_LHB4Dp{A~|jknv>)cmH+g{Z+H6%$sVJ1!i2C(l3v@=N&(LU39Ng^gESP zs6-M+@)zk0j@l)&u40F+RmCdPvk%L5cl=tOhSacYU*z1XOt0Z+FSJ}dXP|(K_TC-M z=oafDXe|wkkK)Xee+G!IYf#nN(X!Pt9t-8VABcMs%A@~UKCz?g2<4C~{kZ|>Zvh_y z@Vxbd=UYJ$M>Ztc*r z25ioYiC-^X|CoJqys0pv4BQ;tH)anmR65N`GjxL#*T*C${RjuOPe84%8?)S zKST%?Z(dy$)v~)KZX=d9lvISa_fbkKI#ggzE)C&EW6`7}STeYy zj5rm&Eg8KM6CxG4Uvwgvobndv!Et&P4Ji~7%rJHcqq(8}S$o}F1}O@}tTrXHyf1o($uPN{F;u$&n`k2u|Ir__4Xc>ie}leq!OINjZ@#0iu|n(EuyY zdNpklr1DdM2kF2iW zmnlc&s8SVDB$XmX-?bR+l5s!Pg3;~p=a>V%k_vNW6vi#T71J=o55G`*jCN`3J_{=u z+T?jsOdv>hA)|y~0?e-DiGTk7>->gpX~m06>F-_?O{r z7@F;0nd1Y71}~Yrid8;uy|t=I)6op=cb_TdZSw<5JCnQ8tk&2e^9cTD#A9uvX)5to zFJJ9rUey@8NL?VE@~&K@hU;@AXAjrC(i1eFY1OCo;e+ktu|^CltoK});<4025=k_l z*`{UotkVl@tF7g_AHVl#e;+&E8%(@5hiX^5QhH&@OUFaOB;t1}J;_sL$0oFuZ zq)e+As6Oc1!wcdJc5g&5npW9jOx_Ri*0)horZs%A*PsrET09nRfhWmah7+pHygK^_ zMihUC^QwHoKL}`~H@9yH7^Br_c-iKVAc23`=1Aq`5XfJzCr^41Fiu^c8w8K*-G^I7 z>0XdZwBr8#wLHr8>5YBDNay%lk?UHPjDKND=_o7y3RNsQFj=t z*Hj5;oLi%7h!A^b9sW#3ZB*ya&wmb{JfC8rJw^l|f`cORB;#ND0%(NzjQ8umuVzes z)HSaCCe+%wxfi2bGCscu>DAIjAbc=)c*@RmR7j-HN&It>u&{3|5bAdNi#>Inqesi-Gce;qXL{@NwekAPdJ zka#3hlILq&KFlJd3As|c|K~U4mA@gsJdTIJgDbvA{wZnmvEPZ}iUQIJquLq1(aF@u zXJtw2O*lf4GznXcQ@L_ia(KN+a(J_Jcqizt6sh69ENSz;BDB9>q@f@F8}1jheObHo z`50Y-9%4{bi_e(<`Rg9h0ifywH!whveEUfGSBqq%6)zx$E1)g}NQ6+%j?nf)w&-PK zJ03tX0GmGv*@Utt2;{+nc7}-I)L>W1*B`44&NAV{C|;Dr9K{@s5G^rJbRF`uJ(lw{ z-kx$jRQP7k#n`Y_IUAiC*VxN8r)zBVA9phDc5>`>^8Y;avV)^9PweLDOr103L${yZ zVh#}7{?~FpO#4CB$7FsCu7;|c{0zjWY^hjR7D;Z@@ZCn#Mt8Oy9W_3w!%QOar7yUCNkn2}m-Y&rFn z*NM@9D}#Qve0P-#mJ)qz`16j{h4beO`PwW0y}y#^Gvw=<=wr*5r(9q+=wr)U0&gBG z2R6K?`}5m8u=0!OTv`>VxcCq`ey=?C9GP@KtLU@yBSoR_ z2M!S@sH%AZZp=4~Fr#f5RZ?qYkfV6yFZme!0%7GF0jM6F2eux9Y4_J`<0&BWe;s`P zv0M6+<@SVZPUz|ZQ zTRhzT%)LUIPz&nM7HqtZrj=749FHjEM406&(vBQa>#`p@V%pg@)kLY$8SviGf~r>H z`u`-Zn{)PZ*`a9cp0=BMQ-0`YJyfjnS|@ZQUNTja<~y^d(M%yzF;d6$C~7${PuJ}( z#GZ^R9-R3~bkuf#AJ?sUhF~^SDmyHgefqFSq2x-bSf~}}guE;5%!ng2)gkZ{G z_ZYV@`{DGVhZ(J zYI2n2fzt`R)v{Ezl{!P`?4wd(UTy223R7Nm(>zBb9K7LrFu$M{g8~ly^OrCjYp^btKxpn=K6Mukv%PEo z^zTI_t}hF==0*UBy$=E!58l0$@qYKD5ODo|ALz(r-beBhza5^AfzSrbtjG=-Q~G;= zNHvng2^xkwHu_P(SLhu-yrXIgC5%qly6aIe>>)& z?YVu_&?vrttgRBe1MG=^9PVUAaT8S>ABz9HOM$2Pc1JSw54}37xHP2$}vb?kA4`@ zaK0hrK=7{e{L-_Uh@)Aex~$ZnI}Z1)oO~oLd=_BN_2MO)lht_wwoQs>UELowDY^%y z^#f^0-TYdY_4v-pDdFRj@AS8xDl8d(45O~=-(JvJ?r*G4*C>_`R&pMTpLL<#oRhC! zDXQl_>seIKX_Cn?a=Xy=#vO0!Av@|0JL>#UmX}riK3kzHoN-Z1aZ#+4OPcgyuZ5n$ zLozdIKh-vU(AM2{pZry03!qi-6|fGl?Jv-s32;rU8iE@i8@`+~0CbY!e0hLwd^zTx zSCA(;XFTndZ-qmYZFK$l18kQe(8=)V;LoO3NY82!bu~;KbfHcRW+`e`3*_fhPh)l= zDhGF{1`{=c76eaVL&wVcqv_>~4BB0&2VJP!gE&;w#PR*x&EFgTd4KETN>Mkr+g#I+ z6iKa=nusIM^Ov^0X6$s`SZA!akeg*&+BS0@m3;YNqSGR_vwiY%a7FNf##VpGlIBL} z+Xt-Lp>G@en;sn2#%}mmq%CMHVh@5VHs?-{-Qb>NabtJ9J>z| zV*|ak7M}KAZteVuVuXiy2+>vC+Bu3mZ;d>!Zd41!KfFG2!dSH(VF!pYT7KAVa#Ud< z>Y!m2(H@;XzXYf_|4|D*V|@&&qE<+nJaKc5IjcJmJ&q_XOLVpmpE`$9mKecVe7Lqq zf^b=qkRnM^xhyrjbEWiFZJzirAy9&VgMusg#d1T)@(UQswisg@47@)%K}4!DB&hcP ztJS`rM+gvv?AMOoda(r%2;X-0>@N?V&8V|LVg2#`q0TWW&w-ZDoLA49he$$enD&`x z9Up2)PbSD58^R`t3Ve6w|3!&!j=&OqSEve`t z<$_kNdR3#Z5FXL#NO89%1o`2r0F;@S2H;f+D)>?#k)y6*He_rP5@(38*+58Gv%}MU zH&+Fb&?56Kn}CAv$y={?LwM0EpS`6aSUqklt*Jmy$o^Ua%*W43m>+a46S*j^yi!Uj z$k`9oQ5!VZazdlK?B_Z?Z%0?Q#75R9R88H7QjHyHwG~qQh@2?4J1v3B*Oz@NpL(3n z=p4(4dK0EsH8*0ZHQuOUw$mY@9Y3q?kl?FT#NT66Z5vR_d3kZXS7PKTdDA(4QBpG&Y zT=#w>`?p*(dk$IulYK~3_J8jqEt@A#K7N9G(WO_N1j%E2q*kBL%I1`j(eH zRwI0DN$Is+X#WG|4na+y#Y9)eCcemGrPmkUBw6&c&^KXP!y6f#_AD}Bpm{;$0;6@u~%5z7cAEs`(Xsg~;Qt7rRavA+!KAyoyxerg%J1)u>g29CHn` zzNwRi>Tq~dr11Anday z|FJUsfyzRwb9xiave5Ebn19Us%rlM;)g~PqBFG`fz1Xl^=5TmWkz|39Ei|jiUl4TN zb?wV9kmebgf`mj8HlQ%2#`f+)k9S}2^`Is@8)u0#l;b%j>94uX9KKTDHwAe!koO1H35G!Xx)BS zy1vYE6dj9G%&)$3Q{|m>2D{w_#Q5=t#Wtj<@#?^RXTU_j^b5@9`KUyRd|I2~z#fm73SpKVO#-3lQ5#{z|o6Q@%2&m_NGxR}!L%wAEfTA#F7>;b_yzV*3A6 zkQi{*rIJZW(kenbdho2N|APG`4T7GWKM39UTX4quyt#+J`Mt3my#zkJK;8snB=5 z?-z1Eak|Y_Zx6&o@VL$2AC1cUS?_DrDpqa%do;XAe*w>}oXR<)X1-h=J#9F?BpKCV zxz!gF!r2{KHXT~F`^M}6qg#jF2DXtn=@lHm79`+949+u1ozod9+g^|FQZh>h7!R<*pIIwq5!J!Ptv=;XrZ;TN8yJ(Y4ID#`V3MPgH5+<3!aN;Lq&L)J_3s7!H zoh(7}MQFAGcmK-j6)=s6?h3vvA&|Ba<<3$8Xgf+EE3}Vu!I6bmRj+y8 zs-OMy+r&HDB-1_)_~6NN4;byIct= zYQ)UjlWPL!3KdaM_(4R%jn73l*tGE24YK1DW%5S#g`#yfWE?Z11=zR%Ddl^l$5+x5 z?Ui3IVC9t$vb~7vX?)$x%&)kt?v8QQ_k7ivJCu^*$|#yI9TL}}fkvCTifAHt++^N6 zns#u$sJi}bs_9Pn%w$t3g?oHHPw$12RI%#teDQHx_i$p2bYDdCG3RA98eRo6htJJ^ylf%+K|O~v|N?Q3eEbf1Y>^=XbfXfAd%WwIpHfv(gqIQ3{a z^_47WtSuQ_V>wAIiVaHR&#OoIyI(n|>FRhBbt{gt#JeuMqf)2H$&F zbS_Eq5y(2n0%*AD+akqVJ_QXFWqCO!7sWGosDjGG2=3;YJ7!X6s5bL5{qHUjGM8)6;fDNW`OoriN|To})+l?sLF+@1 z`3+9Udijq=oEGC-l%WcJJNT?~T8H(;vRy5ZG8G#q`V8KbzfFdUt^; zg}*nkvs~j*AHB?Hj!(Q7ZoOr-e`^Ir@@FPv<__+TbJL;y@siAH^t1RkoZOy?x(Vh{ zl%^$Sw*Km>jt#SbU)V>yt!j`mU3mmi2geJUF(9o!_DlhM0=j(X$Cby9sINTksc__6 z0lprC*i_(g@mNWwtQ@g3xN0OEM33PM7XGck!x{5JDg`JxmOnCi3F2A?4qIT_rK*9K zkQ}Zp945E|u~rfaW)llw^e@-2d&#AwBW`qWKk)XTEKN zb+ZcgR-8-W*&mQ;N*LdHXO1M6N1wHP6ncg|FEFsHIJkM%;KFLUSN@uoSFTpN7ZL8X zGpx5VoPM7&1TaLi-0{|8x&6)oCM;p1`zxpq zVKVzG_TQe4Y}|VJl1nj+XVB(owl7+GbaYiUVl6zj__3d4baZSwp-_|L(OE=0R*joC z=W5B8@RB-JZGG9izqI*nJxfS~YWo?bJf$wV+b%N6_N;oW%yDR8%9B5-E`&0??4bGl znzKLImMP94i4Cu#Klg>%Pb+acyT8uT)1{T{g?T-Dm3VHIcqaayJEnr#!0|@dV>5nh6h6AJM=o1Zu;>9cX zWk@>@n}EiXEw7g))!vsS;AIKG-jg8s9`O=(ef=ua{Xtcn`5}B+!NsTDB^UI^xuD$* zPk%49THKm@{zM^UQEI^SKjNNr>pZ;M&zT3A?^RZg{8SRih_IEa1x z3TYHfBiSV)I6?AEvaAx?+FOh87{n+*lPpGW>;tnr1v?7%(AWfY3>kro;3G3bSm?tk zJ>r_wQL4d=~u(_eB)2@6pui^820#sSX&OSF` zVar2$A;96L4)7uwCmxDw$TJcAgPYtK?f5_ei)tl~x(0k8rA(3ePxgb2hwQ)KYnijx zFuZu9WQ@!IVnuN#9;vT598DiJ6@+?s`Mh*H`FfktvsA|W2#Etk_`1b@e1o0^r1x4* zgw+@=a~CbE&bgCb`FrYdm4nmyvs4lMgSJxa__{ywN47sv8HKkssZ#wDmIZKUY+`tp z>ob)MZSxf-4;ph&Y?^nl*Vo(-DHri@Gq)YSaJ|WFSm&*hS+Q^7s#0)RVZnHxOAhJ1 z60XS6;@&ySI^|L7S*<&rb4Qn#T{jPJ$BeVnsoW^iH0K%TL<&1lnv5PXxrnsn%tk;# zIYn;CLEFu2h-dgB=qSC*6wHRWhc6O9SeY#ue&aDBx&t{Llyo*vV22`g9m1eMWe1cr zqN6-?;_@~6C*2RZPsO|*?{av^AzL#o#r7dJRwa%!*b)#((Pc{;KD5awM?g@ zZEh%caclW%A#M93LcloX$r=2?7Qq+!cro;5Wiu^CZdxB!?S{ zB+CP(NOFKuJ3w~GRmj|_yPGKw9q#{HwOQZ=1I4bie6Ed)S=AVsen+iCCm9Qjd?EZ) zfLOWN@uAI>W95QLfGQhs-MlPN)-71p4yJDTfsO}9oSJT4xX-;Za^%ca?{FyyIN)o5 zoPbJk18GLI?k(>g#MWE2!Pw!(;2_W3L1motpmM73pnSmJ==XCB8RjP5+g=tA;5YZr-0%rlTw1C_N#{&04WKrv@=9&izblwOEQDAH^4v?Ql z0s=xgJP1jC|5moJquy$ykfYwnN!ClvuRi~~!SaNqW=Q?6(yVI&#?=68NA2WFjdi8I z5SXM?Z1BH9{SS3_xGF#%L6RJ;z5+7ArYj@Q3od?DzB2ks^+a^Q0e4HbG`>vTo_=?b zezclC$|-D?KNwugEV(=uS&V)|l6RF7c%B~Zy~A+Kntr0HcjX&Jx@xkS^l9mAF+LK< zVM&Htt6C}I(kbsp!()^eH!p2_eV?aYzWvI}eBD2{ms;Zxrdgllk%mG8153gj9jLXlMY z6&MH=ZYnmcqQTY-Iop??mxan6h9rK8O`CXpa}Q8M*IQMhz%^}cbGZm=MM$79z@Mkj zFKYkS>$-O8?km%&?r#uUaB1+&ZEHyjt9XD9 z)LhF&giXnF;%wGihsgxXJk8K%hS+crQrumJc3m~8Q69vmxp`(LSi~(s$h3jDnw&B- zK2yg7DyJejL1r~j)%7USw+}#Mao9N0FT9S zKLl4)sv3h_1f6sPrGDXn(*mED)1XS6>bMGYga~E>YIaW(Y3s{uobPpg6vc2WQ-CP4 z43~Uoz}$M+P(Qy0cc|tT4Orc5dnmRU?t#b=N1%x3CrZ>x)knsmyY)11dMv zNX`YPX-`ByS}yCJUaA%xP_sg*L7$NBo>L{ofC|^@beXkA8Gk~685b?yR$7;4<2FhM zzJ-FOF4dt(pY`Aq|EIg~(}SxXRN?MEgd6E#rOVvm88Anq3{A_+rB=#CsGyKU+j3l} z#Yxr1o#$ppakER3g`aVZ1BPfl9aGVADbMm_L_3tA-4H-|ri?cgFfBq(v>l;LP&RyK zx(2{^E%wi~KXDJB*t_-$Is0fFKVpNEnGjcZq3lfs&9r0 zv`zdM7`FJZ^4O8nO3IsT)4WU{i0T&isPMtcXOqT47m$mjm1?gxK}7JG$Z$1 z+rl@hU3Wg*Gp3n11szJ)mWYum8;UE>lmbdlx1@Va3-*Y&jPeEML;4AIG=)asoZ7Qy zUgb@GuQ{rE;ofSkxaeoi{uv&WMedW;G867ELD{K9tD%l-X<(oB4+y5YIP)dV!XSFMk?D%@&{B)1(nM*_Qbh0MiUSR%xDFZz#IPSM4 zn4*FJs9Ne@Y>@d6BDmo&-V!Q*t~A1!Z%Zcg0U0(QyQi9u3E=p6e6len{Lo3?ZTfp@ ztPfatQO`Xy)7Fye#XAeg=;E9^sNRy|;^L4yQ`Oei7#!^E;yg1mGuuYK_y;;V#>&>8 ze`VDpKPt0<0OV_^CSp$0tE-B{C2sZISJ+h zGKCBMljnX!cKD@jk(gKqBi%)?ES%w9g$Xroz$N8ti!EwU`ygHA4Pfd~{U88t2tfw+#{Q{V_C_1$NL|`Lwl6Vu8SD!;e48mKl1Mo@^?>{7F5487-rd$8 zKfy;f3!MQFW04hz!=)3$I(7>o`b9vnQF->ll?M=FV1`4iIYe;q5Ejgk!mn@| z6MWoLh&2fybT!LDY#)a<*&WrN-UTg~6D<7WfJXso=+2UgujD8@335bmC-9``yp@+a zrwe?&MfR#1^!Zd}5Y<(F<{?Pq+yt!D{tX|89>Rm^Z&6Wo0gjFiGi||cE{@JQ5Ke7T zQEjzI#3`o*|GfmdAQwl6TzIRxt+75ZV5*A7Uz;W3rOh%BH7nGD|vA)Dey~u zoi-86&b$MdX1s9j=?`5_w1QdYJY0bpHvo=kcEae?zWi)Y`r=zG@k|HFA$_x$L?^vJZ4Q6p%{9{`i`&dd+a;jH@f=Ww zmP)UjhktR?=3zKVRL{kO6HgY${6s1nID zZgx6$G(RpM%st>xK`7tnYpzy3NO zsnf?unC^S3Y(VNmRz-V~pwerb(0ucO!T2bI-L`!8v1>3gTAC-M|UvG0@4 zs60zq#h9*|s(wGBEW>UIj?a&NDJ|Iq2Q5eYFcnZGP;~_Yj1TodN|v zO8s-Wh)Bf=a!9C9f#4{VB83-Mr}XTaA+8w>;d2lFJ+D<<(Fx~;n*Q$G^`f!9(afg3 zvEKCK$AvC<+Gx7)qN!0n;NwOha4wvQd}DomBSdC8}SS&Dm1^(I$;jX~Fnx`id_>T>R3mm^?ZZWio z%Qx-Q$v8gjYhkzpNqILc9nihOq>he(0kEi5K{8B-`ROl2t?4XJ7SUnVY~>2Uu|c*^ zp?xv_V9%HWBSr?|i_#U(1rIBX&w=cJM6T7$2QptUxB`7jSXR%S0tdOgrv>D^<&|Ke z@?mMu)+jVzu1u}wBv{CLuQwHBf6rN3^V}Y@++Ih&whTZHo&h>`P zif9Hq*M;PYF!pE3>4Ja3&sYG#L3C|$1wi6$oXvl4WUw>yvC{;I9{K`%3mlScNNI@c z`dcH0DX&eVwwDy5G@Umtyj|Hb9;@71FrRI{p61bl2ixirf9Duei3OAEGuree-jg9L zvdx1Z`vpGFmkNdE#|qrew8<~Ma+9Nzu}YJ%qDk_`iejoKiuY+DVmY`qZw|sshv_qm z#1ewPi|@32JFjowCgLKW50VX5s_SNSAy&2e+Xh!Hn#=n3wFfC|C1Qfq#u5vHPPni- z8V9sqmcuXl@Qg^7%vK7{ zpdaG~mOLP9#@%l6T_`PNp#{TFB00vO5`<4k(7OlP*4adV2}~6M?1`0N>;*T}l(U66 z5Lb=D>35vTeuF6tkfSin0ZApmi&ze8)|oj#PhunvGFo9Ua`e1-Mm#;^H2A2(Jc5!k z-LoN31{~Li#uj7gIzU?`4(AjERj&rnBK}(rn^i900Da1vqrOL~tz02X2;&iXt z;hwh0W<*a)A)}{uSWitHsZ7}@O$!J78_<>>1FDoRKbE#$Y7MR`ac?6AyKr~t<(=mB zu7M@@U#=TDtuu(z-(ton_P#}tjqQ+KU7{yabyKih{~c2 z(J1q48+a%oEbww`r z7Bu~kO01clr!zq=kbkiGTsoGOIap=;z{maqYwUL|3&B-&)zs4o@jGZK^LJ%jleQwt zs0+EMi(=%)B%9MLvvNZqXf<{3#Sb{Ey$5?be?SwB27Z#-eOTQg*}4AoJLn{x}soLJ{g z07>S0qfjn}+{A)e9sc2?1c*sUrC`j5PoWtym;u7k43!Hyd{s~bqd%SkM;T%VFC*H) zfdmswDswXsqCy64!0-SX{W_M4DP?L)bTy*78uTOqr8B$^EbL`~yeklqDg_01K8Q|Y zoh~L8LTeH6C=`M72J~78bpsqHH1)1F%+ActR@J!$Iy%qHRzX%84D}wAdyUS{v$M!O zIVBBrL=sZ?mYJ%kC|_lW;Xs>q$Vh)dOyYpK5r=%#2SU>k2}$^HvUsj&%(r2H7cnP% zRn;mbg6b3s;lF06V*f<0Nh5odgQKq$9;cEDr0^}l){6}T{C6ILh}!(u(MrVA6bx}( zPK-q06B`LiSHE>oaDq?oqxRiGAz^Y)!a}@~h&Woo_VbtVBEXh~dKl6NX(16<*l5A( zfe=05KZbAGl1L{BG?#QU!1CM8PzSAaG9#|+udPIjg<;sNxXZwMRRVAbw~534Ix6`&+TrX`?(FB4A0@EB=M&qa&ZLa zIJ^$6^=p|VN^eQZNX@jt*V+QfyM7$JOGcQ9X_>@=X8qxnQ%@a+lh3zsee{%FJDxLy zlDUnuKPK3bT!m&gDnFigj4MD?^E3OiIHcz5NPZi}-k*$vn(sn#l?}TQ`cRoQd*8id zX*~wQfOyC(fDLFo=tI8`3U>g%dT94O`6J>xxz>`d^I5Ey ztIVMeG@Un>@{-EQ?Q_N-#}8dQUO$Y#cq$qloBhhiZQc>ae;_71WTC%<^#{WbFd@J} zK7S8{;jgknZP@V;SaJlCNv@5VT=|#)o6=X-`9&>b5FSGL1A(Z<2j&&9nIT729k&=z zfWql8gvBl$xIciwGjbrc24+7zt$8+jd~!qYZbdd?@rjPclFjVblX!h@?)-4eBkXx8 z7mT5cK_!DhL^OWL|8VWp`DOTe^#sBP;s^Q-&W=E&%+9p6{f#8vHn{jBJqT%dA(T`wT8pfUTj9-QT{B=$kKK^C4`p~(VdEXY!eD(w7}eN}#3fnFwf z?#hcRWC{vOiQqE?0|sI=xJPuBr?yn;W~_afIywtKFg8C5z6|3=ginD;WPv{&F@m2V zY9v8tl5ZcR-@i)7CpXEm&g_sh43elLUMK|Pz>#ha6PoOnlV zL^905N9hVxPMu3}A8vD?3$oAjY+#WtlBre1&)e(8K-WyJxMtje*VT`q?_9Cn2rfS{ z%!=-GTWDMO%rey+jrxdV)rbdIubL#y1mjB!hF%@&Ly|Xp)eH{RqzxGA|F0&+v-DW& zpj(GeZ~x#~EB?@+)#8_O6OZcE$1%MwxqRiyL?*XKj8OI2|f66PdsqIC2%B@)0z-kDxs1B0+Jnpy5@o+SoIKXdB@==uGh1%q! z1BNm(qVz3L#U)?gv?HO>Z2us2>uCmMG~IwU{9F&c2Pn~x5KJZpmxW% zgpuyzw;~BzmbTe_!-Jv4V!Y62bl1C)4P#vN_q4LS=6ID~44#aieU$1o$JH_#DBM$U z-$#Ax5X|q7eHbCxnal&GJF6l4aX63_EyB=0yRo7y4 z{ThDVC2|^^k!MYuSl~YeKEtBc+)EP+P#jN8G5-<)X97SPNXm@?nZalXnh zeLy%tzXgrx(fzRBN(+Ae2H!Xn`NV>@#^uNs#1ggkPkE(PvuZ5pZ1_`GPHEV4*iTAM z9>pASFwiiM2RhS1`^qyPn}DXfnOAKGOG6!2P9A66Lxb{hLscn>~p~sCYv~ zGpKm&=wA=9^xgpxrd-<7*u|vf5Rur2XSqxoY|@jsbT9{IAu|`upUy_8xhUq zpDWeXa$?2*E5~pqrx|z=3@2-GUSZs%cd{Aav`g^{J7OHy4*16GdZt@MxbL2DUnrk% zZ*>rx%7TbbGs@mmwwwK|GWXu`$NE~~?4)V{GQhOAPmP5|HNPN5oU6Xn3o0o)DCLf) zJvHVdzY)eZSbhu&JwHl8O$68s;u3YPL5D94_le?xWfpn8*)FPIh6thLWtpur&HAl}`A8sWYwzv>k; zbm`z|cgsOt#`rrui8Ima$A;~U#lv}8JvzJT`GSu6G+zg|9o*2*n+y5&&Q2RGnjg_9 zln;616~nklv|GT|715@(r_48lHF3})VQlX7d~;&cE!lGCF7f-~_rY&3P=B<<>DM0Y zcqwGJw`zp=RbPeiIWRy0yg64h=0BbSf_!Q35(w>cBY+5q2Et-|o}>*pvji?5;|B1f ztV`31JfB=p>*x9}!z)BmJFsSBR|SC0d%hq9y#i!10a%3os>l!xc8aQz%C6_A&rY`@ z(x`@hwNVgQe!x-64~_GSxkt)#IlX7Cz*}RRJ?{YhIxrmo)n5-Z$Slm(B^PLosWx+i z?aE#}%8&~ph1=YKJfwwzfzAu?J#F%VP|^{b$fX=K7MkuO^BB@0RSbj9&$8nW#Ia++ zg$6;kizK05Sv5LPwV*-^1eQBLF3XY#)!aVdmoVH#EE9;qN6QY8%-t#gN<`h4jJ5Nd zzprVLe`DWGpmJa>2pK~o5?FMKav?+*U=%DpB^6**h(H9>^(R0=4ThgqJAiBWkWKg$ z#QO8C^!Wlzwx~qe)aiZy!(hsMV`3z~_)OqQMXd?Cu;h zUsZoEUDq+%F5_v>t!&J#Lb1p-p-nR(1lG6fL3H0t8L5KmKB_)L#Fj7EqE-f_r?hCf_)597XtfCC7c`eL zngfe8^-{`9p@ApXg66VDvr)`R;&^Lsso9~xI0!0HHVdjVlJNl1$Z)r=DiCoZ&AeC3 zzbWp`IEf$)OAInhQU`{Ts5``emwUsR8%h=7-~qEscv~C}In{Fq&K>ibqYu7p$Pz)p z<)4a4_fV*wzW;0kzt4BjT@t5Y2@2P2#2qLhUo24$zCT5=DO(XbU#$e@2pZ-HI^MlQ z`ADyhHrO5+P01W&4@SNoj{&D+0gYMYAt{Foks&GfSeXBBt|i;_+@1T_5%(U?XUe`B zaVLTn2{(kI{>?h*e!LpiIr?rK4ZiBHcE~U+Oz{BJRXF8>0+{jwQ1=`S=_6vjgXTAR zX$I<%Y;}d#LsAiS7&zfBxP2v%r6b6=DmXTY2Q~x^YW-@$W$^wsy8kZ?@3nQd1Nv>t?LY?C)5N1+!#L?`kdbPpgn|F#d{9h-$0?e~#6 zmZ}hsP1zU=u2t|UOoEs|9-In7?A}_e26w<^XWj$>htR1F;D4RSzebI=+r zWZ;jQ0b2sO>G0Jd#1Fd((KdeoqH_#h*+`Y^zlkuuU$eo9*SZ^hBfb4rQ83rZU~Y|k zY2RM^Na=mf8SA13uqtdjC>C#qT)8>9qL{&cS9Du8t}T1qrwMTaH!z z-~LCx@tH&awL}u7nkK_JYmWZ7Yjme|(hMy(Ld#~qxNNOF2;n)oBpW?x=HC~+1(Q)E ze3~ssJnFJMnu>6W14mYhHZ3I1m?`L+*d_draBPW>Vu3l%kCif2z5h@sb44i2aZS4V zsW;`{DaM&ymE7uY2EL%fH2Y)&(t#*IWq59ERy{T?Hd$fQKtZ1`g54@VJtA2)?Wt%E zxnrk86S{I7I(Ir$QZHzrV@D=2-&(U9lN)sbqP$Bqp|3@gD7iFW^StAZb17K{{reji z--*svtmg-?*Qu$5Obiew9(C&vw)DD0-)wA8WGOOm81C&4E*sIHmzxu6pA(*$xG?;My z-x}{(P})1#W=-m5O&ZzeVC-|?Z4@G-hC~oYD3mOB76Zo`5d7Vs5tAnIqE(8UM%H`- zRgtkL;NC_iks!iG6`Vx*WuX2W?kl3~&{^+hEewe$Fx=?fey3sJjp5G3NPy#}-7E|7 z4{+)9k_1~8g`PEBS_XB>)&0vt-H3DriL?Vphn$(28AutCj1daD795gVI?v8PIoF2t z@F2Bxb|km<+S=*@oO62QU(>H&O2URGet8)FY%>x3%3|d@DWc_qiAkIBNi83R%N7Km zN$7g>z%K#@hFJ(h5SC`65ZUORcR*Ddwn_{)Ak-?TSJ&}4ENnbykcxq_Weu!FU=hkT z$(l#yVBE?6bv!H((qtnc0ny=YR!9+G!PxmxsGJAxc07(8!HCy^0Ge1BT>(+tt-gDMT-(_Kb1AcOzW}L8qK`xY@3~#{0;QCAzG#pMJ zgEg)PYkYcmWO;e%vvzlPwggQ9*bhYhDHad2W%~zL;A;2u@Jjg!nlIGu~DFndxMY<@JKsppWnEc^K1PaZ>6&IUQ=&S$33zk@G(ng%fDmrvto zoCg~wWYis?MZg$hKRZ)MqirAD=6fAof5LN&s@^_muAU+-a2{qU%eQR8>=f4;yZi;J zfAIG|D_>il<7;}aHSXcxIsRUniutXUsS1sjzHPDCp`bwCXVwC|Yqo+tdVvKkn>2K~ zVDLM{V&83#6=`#Dali`j*EiOyu`RR)SFq3+%Pj;n(iq|A!SXk7Ke+7${YhY(Pe)XL zpFMPN>a+3hgJx66h#b&aAR2`5;&|7Im~@1V4I@#8cE;Yh7TM<2BrF_D#Q->|-Vm)T6gnI;BQ`NA81!- zi2{w}dBJDcXo$uk6{c83LxeQ@7vQf+DT(79jw1v1a1s&hSr+V4fvT2!t(*T(4BX40iEy)8pj= zqUB~{1Vox0R7z4wMer35r@@R|;A>yvf8c=~!D7d*m)O(E%^k5n7xMl=`Bm2uBw%zMdLW_B}hEVTUyMIUFJ4=ZJ{0%fsg zqICxydPVT$l3>@8;K@RPu3~|1EOu5+C0I=%ke|C1Ye%|QjgJ>NdFa|rHz(WJ8(-Hr zNtJ9BHVmHYH}2HZ1QIAda#Msqp@?8~73_O`_?Ra3x+~>RKZ;yIDknP_MMnR*mPKVw zZ8<^ChuP6Uu7u^P`kqL43+wq%)nDVMF}6{k`dLkGeo2;J;tn} zQeOZ9ae$7s$z^D^XUYGMz4!2HYU}!i6B2q0y(1zZT|hvp(kvhyLJ`n}CS3$U6!nDO ztDvD8PDvn(!Vad5^~>i1v15(wYi-t1<)Z7b*+`N^p8&O{Iondem@?JsE!LiQ+2e|h(X8@1` zj;jp0C=H2LCyAEBCGqPuLHkO0I^@Te=-W^drVYV*fJtu5`Q)r?=a5>X1twoJp<3GIg?+NR?;a_+) zzVL=`56tu1|B3PgdnPfT1A-p(Cl50585i`oh*cNo+bYlHH?F|+LvofpN3S$r zjF<(@lwI*Ln5g(vdAOvfUU^_`V%Tw#&9g1h*1aDTN_fKD2W*Iytjg2WZOWZzn$ym* z)z0f%+zWFh1$|!qfxdSrx(BW8EsZQR?QrjHFe0utI3#X%rTG$b14XO(SU2-SSI2I@ zC+g)GZkWKqr3ILNwW$K4+l@0Vjlse`0nFmT5-+9SosDK{ddc2@x>TV&oXYVr69z4N z(~E>H&tcjaFwZWS3f82uh}Oh2dVB=PmM-ZrFrn3AU%td%iH&DpPFMC3t&L|>NP+l_ zBL3&sqVU@Eum6Dd_eG@0sMFFIDc*`5Gli^9FM$8}8Q2%5(wp#zJ9s4}Tdpy=9s7WlS8FMCLoY3LlGQiE(Mef}L zv+$+??u07=7SqL;?djrOK64f6?WVRgHmfME$usj&L5)nizFaE*(a<9W-}!{ucXX6a zv3U zy8Pg5iNNf2!R1n7dZWA9L*dzObQXx&1U9X4HvO!`h$6)BE#ZlqLf*xKZr23hP)}D- zZt+8Go}o|bLsRM`h|W9!a%nmx z=3Gjr^z0wr)|TEOc6UKN6Cl^0-U15ybKo(TLR2q>!7IShf&p+gjkt8gI#%X|L!2albVP!9cTF@VIQ1KJ!x9VB1$&Bn5-A5 z@z=oZl&)CvzdL5H^1EH-Up~g~?P-(Naxh)h0WN9p)fGsWdf&&*NG*-0xSb<^PE)n? z_7GTxl>wT>=`%xLUo%d7XZ8Sjslt!rJ(1(|A%zNE`9bO*DN{RUFAJcp-8$6OBjN_( zx@UL|PE(im3_+};v~7N7&(M@A2~KO3iQBtdY&fb_VB0 z8|lc5#x6e%sYy|uVA?5bS|~B$_?Ba*o8r$tvv2W<>n2Y<<4R)^j=aDY|HPImh5O#^ z(mLTOw#UlUIM!3(S@Gg{EJg8VIJ2UsspCEZF>{$`MK59Y(N4LropR@x)oSpYK4t=S z6)J(WZ;b&4KB7F(tZ>naGtH#gy~Q=C;2+Vg7Bmi*%}Ty{jvXZuEOJ0sA{VdcY%+Hb zqdVeBaP8=Q&PkEj8ID)<#4K^9N>=E_TkIwr%^DQ&(Zea8W^t&^+86LpDS>NtuX7*B z^Zg*4@aAn{jox`plj~dR$w&l^F|vrLO?`bIK|%o?s+YPncvw6Y0Y#x{=xkvR*qCrM z*%adAQik>*VfZwkc?#m%nkiV!2UZCyv=;8|PjLVx05StHWIyjG+c&^QDT^-Nq->cg?%gW-#q$1aQ$hVe% z{R~&Vn_>jb`L)UFKde`yd7C$Oyx5Ryj{C=%H?V-Gu7LYZ0e4_Khu{oOL6Z{Yr@@n1 z9q$tz?-5A5vOp_X=%v1C7m(=U$$r7!R1&8%HDP;Zj;o|gd>=_sH;koeO+qV#RkaW| zT81xFX45%CsNcF)F6cFTQ`p+e`-kN4TG;UWZV~(Lq%Me}J46`%nU%sZsm6X9LK6Jis+mMZ7?uo!?7S0dpwNB}ZHfG28$=lLPt5S4>fpi{?dG1;r`qKn!ZTfgz zx!A)h74m6~HfC15RERdam)#8Z{FhVH zHIR7Qn}4{#v=kNqXnR4d!UFw9MhG)PxvB$t`^O-#QJ|lF+SxcgeTQk`rvd%Lz&!7J zwX^_B)6cA3=Tc&#QbbQB&xR%!h%FVesB&)Xp>@ZvbE>NLk8&z1_cw5C-Q-jdws$9o zCVeF*>-iA^xj`7BoeD&+yTk8CfyKBH3n$`kkqPFbz*}o)(gY9AZAylZyYnz6t-gBN zp6!o+?y$@!&g)sTJTS9PPo>xo83nN~;;i|br=Rw+6h0*DOsX@9Sq6Oors2Li>pL

}jfSZ6#|yjS8)rl^l7 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

yjBEeCMv#o=0wa&5V?{bNNZ0APdzGFVNd7cCqC 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 literal 0 HcmV?d00001 diff --git a/Assets/Spawn And Move/Scenes/SampleScene/ReflectionProbe-0.exr.meta b/Assets/Spawn And Move/Scenes/SampleScene/ReflectionProbe-0.exr.meta new file mode 100644 index 00000000..79df4c90 --- /dev/null +++ b/Assets/Spawn And Move/Scenes/SampleScene/ReflectionProbe-0.exr.meta @@ -0,0 +1,140 @@ +fileFormatVersion: 2 +guid: ac8c51176350b4a4092854b908c441fe +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 1 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 100 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 79fce987..7ecc6375 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -114,7 +114,7 @@ "url": "https://packages.unity.com" }, "com.unity.services.core": { - "version": "1.12.5", + "version": "1.12.0", "depth": 1, "source": "registry", "dependencies": { diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index d971767b..2e7bb8a6 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2022.3.28f1 -m_EditorVersionWithRevision: 2022.3.28f1 (6bae5ce6b222) +m_EditorVersion: 2022.3.15f1 +m_EditorVersionWithRevision: 2022.3.15f1 (b58023a2b463) From e8c52618c1c88608bad39ddc2451b28b00c32833 Mon Sep 17 00:00:00 2001 From: Cristian Fleita Date: Sun, 1 Dec 2024 14:33:58 -0300 Subject: [PATCH 2/4] chore: add models --- Assets/Spawn And Move/.DS_Store | Bin 0 -> 6148 bytes Assets/Spawn And Move/CameraFollow.cs | 2 +- Assets/Spawn And Move/GameManager.cs | 8 ++++---- ...ns-Moves.gen.cs => dojo_starter_Moves.gen.cs} | 2 +- ...en.cs.meta => dojo_starter_Moves.gen.cs.meta} | 0 ...ition.gen.cs => dojo_starter_Position.gen.cs} | 2 +- ...cs.meta => dojo_starter_Position.gen.cs.meta} | 0 Assets/Spawn And Move/Scenes/SampleScene.unity | 13 ------------- 8 files changed, 7 insertions(+), 20 deletions(-) create mode 100644 Assets/Spawn And Move/.DS_Store rename Assets/Spawn And Move/Models/{ns-Moves.gen.cs => dojo_starter_Moves.gen.cs} (95%) rename Assets/Spawn And Move/Models/{ns-Moves.gen.cs.meta => dojo_starter_Moves.gen.cs.meta} (100%) rename Assets/Spawn And Move/Models/{ns-Position.gen.cs => dojo_starter_Position.gen.cs} (96%) rename Assets/Spawn And Move/Models/{ns-Position.gen.cs.meta => dojo_starter_Position.gen.cs.meta} (100%) diff --git a/Assets/Spawn And Move/.DS_Store b/Assets/Spawn And Move/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ae988fd78d050cacc439474f9fc2b8a1020c3c70 GIT binary patch literal 6148 zcmeHK%}T>S5Z-NTO(;SRiXIod7OZH|;w8j-^kPI0Dm5WNgE3p0)*MP9SA8Mh#OHBl zcXJ2^k0Lq)yWi~m>}Ed5{xHV4w}|!`a~NY5G(?U{gP^(5)iS||T+NZPJS_5Qn98tW zqTgu3Z||~mCRxN{R{#F@aGEChd@%Unt#)UvyKY%l&${y;W#P|*`6Bm%*$s{^rA)(0 z55lV?E+)?Asm$gWk4})fda7 z(XcO$4~DCiZEfxDom@wpfg&*<+UqJWNX2}EJgHCSo{4+z(( zfI5|%CkEH)U>7FNHCSrY>5QwDVIH$`^?2cGb+8K+&bX_QdSZYWs58*kLkG|QGx%j1 zANlnZ8W97;z#n6PcgFtMgQCpY`lUQPYX!7>Xebz0q5=YX?GgY3+(&klQ~L$#5a${! VHR3F2SLuLs5m1CsM-2P`1D}N4OV0oR literal 0 HcmV?d00001 diff --git a/Assets/Spawn And Move/CameraFollow.cs b/Assets/Spawn And Move/CameraFollow.cs index 27ef36d3..5d94fd7e 100644 --- a/Assets/Spawn And Move/CameraFollow.cs +++ b/Assets/Spawn And Move/CameraFollow.cs @@ -13,7 +13,7 @@ void Update() { // all entities with the position model, // we only want to consider those for "follow" - var entities = worldManager.Entities(); + var entities = worldManager.Entities(); if (entities.Length > 0) { diff --git a/Assets/Spawn And Move/GameManager.cs b/Assets/Spawn And Move/GameManager.cs index 39aec22b..01b23758 100644 --- a/Assets/Spawn And Move/GameManager.cs +++ b/Assets/Spawn And Move/GameManager.cs @@ -44,7 +44,7 @@ void Start() burnerManager = new BurnerManager(provider, masterAccount); worldManager.synchronizationMaster.OnEntitySpawned.AddListener(InitEntity); - foreach (var entity in worldManager.Entities()) + foreach (var entity in worldManager.Entities()) { InitEntity(entity); } @@ -75,7 +75,7 @@ async void Update() if (hit && hitInfo.transform.parent != null) { var entity = hitInfo.transform.parent; - ns_Position position; + dojo_starter_Position position; entity.TryGetComponent(out position); if (position && spawnedAccounts.ContainsValue(entity.name)) @@ -84,7 +84,7 @@ async void Update() if (previousBurner != null) { worldManager.Entity(spawnedAccounts[previousBurner.Address]) - .GetComponent().textTag.color = Color.black; + .GetComponent().textTag.color = Color.black; } var burner = spawnedAccounts.First(b => b.Value == entity.name); @@ -123,7 +123,7 @@ private async void Move(Direction direction) private void InitEntity(GameObject entity) { // check if entity has position component - if (!entity.TryGetComponent(out ns_Position position)) return; + if (!entity.TryGetComponent(out dojo_starter_Position position)) return; var capsule = GameObject.CreatePrimitive(PrimitiveType.Capsule); // change color of capsule to a random color diff --git a/Assets/Spawn And Move/Models/ns-Moves.gen.cs b/Assets/Spawn And Move/Models/dojo_starter_Moves.gen.cs similarity index 95% rename from Assets/Spawn And Move/Models/ns-Moves.gen.cs rename to Assets/Spawn And Move/Models/dojo_starter_Moves.gen.cs index d7a23c83..853e54ab 100644 --- a/Assets/Spawn And Move/Models/ns-Moves.gen.cs +++ b/Assets/Spawn And Move/Models/dojo_starter_Moves.gen.cs @@ -25,7 +25,7 @@ public record Down() : Direction; // Model definition for `dojo_examples::models::Moves` model -public class ns_Moves : ModelInstance { +public class dojo_starter_Moves : ModelInstance { [ModelField("player")] public FieldElement player; diff --git a/Assets/Spawn And Move/Models/ns-Moves.gen.cs.meta b/Assets/Spawn And Move/Models/dojo_starter_Moves.gen.cs.meta similarity index 100% rename from Assets/Spawn And Move/Models/ns-Moves.gen.cs.meta rename to Assets/Spawn And Move/Models/dojo_starter_Moves.gen.cs.meta diff --git a/Assets/Spawn And Move/Models/ns-Position.gen.cs b/Assets/Spawn And Move/Models/dojo_starter_Position.gen.cs similarity index 96% rename from Assets/Spawn And Move/Models/ns-Position.gen.cs rename to Assets/Spawn And Move/Models/dojo_starter_Position.gen.cs index 4d427ae7..83092197 100644 --- a/Assets/Spawn And Move/Models/ns-Position.gen.cs +++ b/Assets/Spawn And Move/Models/dojo_starter_Position.gen.cs @@ -23,7 +23,7 @@ public struct Vec2 { // Model definition for `dojo_examples::models::Position` model -public class ns_Position : ModelInstance { +public class dojo_starter_Position : ModelInstance { [ModelField("player")] public FieldElement player; diff --git a/Assets/Spawn And Move/Models/ns-Position.gen.cs.meta b/Assets/Spawn And Move/Models/dojo_starter_Position.gen.cs.meta similarity index 100% rename from Assets/Spawn And Move/Models/ns-Position.gen.cs.meta rename to Assets/Spawn And Move/Models/dojo_starter_Position.gen.cs.meta diff --git a/Assets/Spawn And Move/Scenes/SampleScene.unity b/Assets/Spawn And Move/Scenes/SampleScene.unity index f6942f7f..41edb65f 100644 --- a/Assets/Spawn And Move/Scenes/SampleScene.unity +++ b/Assets/Spawn And Move/Scenes/SampleScene.unity @@ -1555,7 +1555,6 @@ GameObject: - component: {fileID: 1603019350} - component: {fileID: 1603019349} - component: {fileID: 1603019348} - - component: {fileID: 1603019352} m_Layer: 0 m_Name: Plane m_TagString: Untagged @@ -1650,18 +1649,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &1603019352 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1603019347} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: ab13a05e740f84a6d9c745e33f5bd407, type: 3} - m_Name: - m_EditorClassIdentifier: --- !u!1 &1621275503 GameObject: m_ObjectHideFlags: 0 From 1e311a422cbfc5af27e105e56d4c7830205f0e67 Mon Sep 17 00:00:00 2001 From: Cristian Fleita Date: Sun, 1 Dec 2024 19:37:14 -0300 Subject: [PATCH 3/4] chore: spawn tx --- Assets/Scenes/Forest.unity | 485 ++++++++++++++---- Assets/Scripts/DojoSpawnAndMoveExecuter.cs | 44 ++ .../Scripts/DojoSpawnAndMoveExecuter.cs.meta | 11 + Assets/Scripts/PlayerController.cs | 5 + 4 files changed, 454 insertions(+), 91 deletions(-) create mode 100644 Assets/Scripts/DojoSpawnAndMoveExecuter.cs create mode 100644 Assets/Scripts/DojoSpawnAndMoveExecuter.cs.meta diff --git a/Assets/Scenes/Forest.unity b/Assets/Scenes/Forest.unity index f30b43e1..328b13a4 100644 --- a/Assets/Scenes/Forest.unity +++ b/Assets/Scenes/Forest.unity @@ -76709,6 +76709,103 @@ Transform: type: 3} m_PrefabInstance: {fileID: 959617412} m_PrefabAsset: {fileID: 0} +--- !u!1001 &963724778 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 184210, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_Name + value: UnityMainThreadDispatcher + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_Pivot.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_Pivot.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMax.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMax.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMin.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchorMin.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_SizeDelta.x + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_SizeDelta.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchoredPosition.x + value: -50 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_AnchoredPosition.y + value: -50 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 22414968, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: c3c54c612cab04d86ab0ee8c4125943d, type: 3} --- !u!1001 &966790546 PrefabInstance: m_ObjectHideFlags: 0 @@ -83105,6 +83202,11 @@ PrefabInstance: value: objectReference: {fileID: 11400000, guid: b345018373c2141dda9d01eb80d61222, type: 2} + - target: {fileID: 114833591496082952, guid: f8a1d1084ca0ab244baa90accde134b6, + type: 3} + propertyPath: dojoSpawnAndMoveExecuter + value: + objectReference: {fileID: 1140016769} - target: {fileID: 212754941309248394, guid: f8a1d1084ca0ab244baa90accde134b6, type: 3} propertyPath: m_SortingOrder @@ -92570,6 +92672,205 @@ Transform: type: 3} m_PrefabInstance: {fileID: 1138161981} m_PrefabAsset: {fileID: 0} +--- !u!1001 &1140016764 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: relayUrl + value: /ip4/127.0.0.1/tcp/9090 + objectReference: {fileID: 0} + - target: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: worldAddress + value: 0x28f5999ae62fec17c09c52a800e244961dba05251f5aaf923afabd9c9804d1a + objectReference: {fileID: 0} + - target: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: relayWebrtcUrl + value: /ip4/127.0.0.1/udp/9091/webrtc-direct/certhash/uEiCAoeHQh49fCHDolECesXO0CPR7fpz0sv0PWVaIahzT4g + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3269270482660702203, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: models.Array.size + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: models.Array.data[0] + value: + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: models.Array.data[1] + value: + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEventMessage.m_PersistentCalls.m_Calls.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.size + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_Mode + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_Target + value: + objectReference: {fileID: 11500000, guid: 043ae0b8f2d5246499b92dea35147ab6, + type: 3} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEventMessage.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_CallState + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_MethodName + value: + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_TargetAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 4477060482053654553, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: OnEntitySpawned.m_PersistentCalls.m_Calls.Array.data[0].m_Arguments.m_ObjectArgumentAssemblyTypeName + value: UnityEngine.Object, UnityEngine + objectReference: {fileID: 0} + - target: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + propertyPath: m_Name + value: WorldManager + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + insertIndex: -1 + addedObject: {fileID: 1140016767} + - targetCorrespondingSourceObject: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + insertIndex: -1 + addedObject: {fileID: 1140016769} + m_SourcePrefab: {fileID: 100100000, guid: d2e25933f4d69473a8994ee7470b2610, type: 3} +--- !u!1 &1140016765 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 4900589733936057544, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + m_PrefabInstance: {fileID: 1140016764} + m_PrefabAsset: {fileID: 0} +--- !u!114 &1140016766 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 1648136030876143075, guid: d2e25933f4d69473a8994ee7470b2610, + type: 3} + m_PrefabInstance: {fileID: 1140016764} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1140016765} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 85bbcaeafdf5e41c6a2f48ff65820b7d, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &1140016767 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1140016765} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c4fd9ad215c314bb1944a6d6b467f464, type: 3} + m_Name: + m_EditorClassIdentifier: + contractAddress: 0x058b83bea84766c5725c12e239c1ec9e1fde679ddf709b772fe7a8fdfd3cda27 +--- !u!114 &1140016769 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1140016765} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c4903969972cd43ea95e8c1fc824e0bb, type: 3} + m_Name: + m_EditorClassIdentifier: + worldManager: {fileID: 1140016766} + dojoConfig: {fileID: 11400000, guid: 1d6a5fa48aab79f0084b213f6fc768c5, type: 2} + gameManagerData: {fileID: 11400000, guid: 22f53d4a93d2d44199b824f3780fe0ad, type: 2} + actions: {fileID: 1140016767} --- !u!1 &1145074930 stripped GameObject: m_CorrespondingSourceObject: {fileID: 6358416819729956247, guid: d5abc895c284ea44aaf79bc56af78601, @@ -125702,7 +126003,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -4, y: -24, z: 0} @@ -125807,7 +126108,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -9, y: -23, z: 0} @@ -125822,7 +126123,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -8, y: -23, z: 0} @@ -126047,7 +126348,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -7, y: -22, z: 0} @@ -126467,7 +126768,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -13, y: -19, z: 0} @@ -126602,7 +126903,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -15, y: -18, z: 0} @@ -126767,7 +127068,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -17, y: -17, z: 0} @@ -126887,7 +127188,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -23, y: -16, z: 0} @@ -126962,7 +127263,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -18, y: -16, z: 0} @@ -127052,7 +127353,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -12, y: -16, z: 0} @@ -127097,7 +127398,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -24, y: -15, z: 0} @@ -127247,7 +127548,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -14, y: -15, z: 0} @@ -127277,7 +127578,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -12, y: -15, z: 0} @@ -127292,7 +127593,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -11, y: -15, z: 0} @@ -127457,7 +127758,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -16, y: -14, z: 0} @@ -127502,7 +127803,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -13, y: -14, z: 0} @@ -127577,7 +127878,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -26, y: -13, z: 0} @@ -127742,7 +128043,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -15, y: -13, z: 0} @@ -127757,7 +128058,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -14, y: -13, z: 0} @@ -127772,7 +128073,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -13, y: -13, z: 0} @@ -127832,7 +128133,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -27, y: -12, z: 0} @@ -127922,7 +128223,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -21, y: -12, z: 0} @@ -128042,7 +128343,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -13, y: -12, z: 0} @@ -128162,7 +128463,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -24, y: -11, z: 0} @@ -128372,7 +128673,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -29, y: -10, z: 0} @@ -128402,7 +128703,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -27, y: -10, z: 0} @@ -128432,7 +128733,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -25, y: -10, z: 0} @@ -128462,7 +128763,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -23, y: -10, z: 0} @@ -128552,7 +128853,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -17, y: -10, z: 0} @@ -128687,7 +128988,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -28, y: -9, z: 0} @@ -128747,7 +129048,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -24, y: -9, z: 0} @@ -128987,7 +129288,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -28, y: -8, z: 0} @@ -129212,7 +129513,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -32, y: -7, z: 0} @@ -129257,7 +129558,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -29, y: -7, z: 0} @@ -129452,7 +129753,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -50, y: -6, z: 0} @@ -129602,7 +129903,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -36, y: -6, z: 0} @@ -129677,7 +129978,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -31, y: -6, z: 0} @@ -129857,7 +130158,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -19, y: -6, z: 0} @@ -129977,7 +130278,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -40, y: -5, z: 0} @@ -130037,7 +130338,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -36, y: -5, z: 0} @@ -130052,7 +130353,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -35, y: -5, z: 0} @@ -130202,7 +130503,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -25, y: -5, z: 0} @@ -130277,7 +130578,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -49, y: -4, z: 0} @@ -130397,7 +130698,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -37, y: -4, z: 0} @@ -130427,7 +130728,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -35, y: -4, z: 0} @@ -130622,7 +130923,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -22, y: -4, z: 0} @@ -130757,7 +131058,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -38, y: -3, z: 0} @@ -130787,7 +131088,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -36, y: -3, z: 0} @@ -130862,7 +131163,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -31, y: -3, z: 0} @@ -130877,7 +131178,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -30, y: -3, z: 0} @@ -130997,7 +131298,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -22, y: -3, z: 0} @@ -131027,7 +131328,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -49, y: -2, z: 0} @@ -131222,7 +131523,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -32, y: -2, z: 0} @@ -131462,7 +131763,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -42, y: -1, z: 0} @@ -131852,7 +132153,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -28, y: 0, z: 0} @@ -131882,7 +132183,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -26, y: 0, z: 0} @@ -131912,7 +132213,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -24, y: 0, z: 0} @@ -131957,7 +132258,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -21, y: 0, z: 0} @@ -132017,7 +132318,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -28, y: 1, z: 0} @@ -132242,7 +132543,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -25, y: 2, z: 0} @@ -132347,7 +132648,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -30, y: 3, z: 0} @@ -132422,7 +132723,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -25, y: 3, z: 0} @@ -132617,7 +132918,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -23, y: 4, z: 0} @@ -132662,7 +132963,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -20, y: 4, z: 0} @@ -132737,7 +133038,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -26, y: 5, z: 0} @@ -132902,7 +133203,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -26, y: 6, z: 0} @@ -133007,7 +133308,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -19, y: 6, z: 0} @@ -133097,7 +133398,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -24, y: 7, z: 0} @@ -133142,7 +133443,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -21, y: 7, z: 0} @@ -133217,7 +133518,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -28, y: 8, z: 0} @@ -133232,7 +133533,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -27, y: 8, z: 0} @@ -133337,7 +133638,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -20, y: 8, z: 0} @@ -133472,7 +133773,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -23, y: 9, z: 0} @@ -133487,7 +133788,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -22, y: 9, z: 0} @@ -133562,7 +133863,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -17, y: 9, z: 0} @@ -133622,7 +133923,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -25, y: 10, z: 0} @@ -133697,7 +133998,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -20, y: 10, z: 0} @@ -133712,7 +134013,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -19, y: 10, z: 0} @@ -133772,7 +134073,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -26, y: 11, z: 0} @@ -133907,7 +134208,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -17, y: 11, z: 0} @@ -133982,7 +134283,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -23, y: 12, z: 0} @@ -134027,7 +134328,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -20, y: 12, z: 0} @@ -134357,7 +134658,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -16, y: 14, z: 0} @@ -134372,7 +134673,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -24, y: 15, z: 0} @@ -134492,7 +134793,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -16, y: 15, z: 0} @@ -134537,7 +134838,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -22, y: 16, z: 0} @@ -134582,7 +134883,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -19, y: 16, z: 0} @@ -134627,7 +134928,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3.0000002 + m_AnimationSpeed: 3 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -16, y: 16, z: 0} @@ -134717,7 +135018,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -18, y: 20, z: 0} @@ -134852,7 +135153,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -23, y: 22, z: 0} @@ -134927,7 +135228,7 @@ Tilemap: - {fileID: 21300104, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300110, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - {fileID: 21300116, guid: aaa735c5fdc695d4691e911ab4338879, type: 3} - m_AnimationSpeed: 3 + m_AnimationSpeed: 3.0000002 m_AnimationTimeOffset: 0 m_Flags: 0 - first: {x: -18, y: 22, z: 0} @@ -239300,3 +239601,5 @@ SceneRoots: - {fileID: 400464115} - {fileID: 1602895920} - {fileID: 1862593183} + - {fileID: 1140016764} + - {fileID: 963724778} diff --git a/Assets/Scripts/DojoSpawnAndMoveExecuter.cs b/Assets/Scripts/DojoSpawnAndMoveExecuter.cs new file mode 100644 index 00000000..9e90510b --- /dev/null +++ b/Assets/Scripts/DojoSpawnAndMoveExecuter.cs @@ -0,0 +1,44 @@ +using System.Collections; +using System.Collections.Generic; +using Dojo; +using Dojo.Starknet; +using UnityEngine; + +public class DojoSpawnAndMoveExecuter : MonoBehaviour +{ + [SerializeField] WorldManager worldManager; + [SerializeField] WorldManagerData dojoConfig; + [SerializeField] GameManagerData gameManagerData; + + public BurnerManager burnerManager; + public Actions actions; + private Dictionary spawnedAccounts = new(); + + public JsonRpcClient provider; + public Account masterAccount; + + + void Awake() + { + provider = new JsonRpcClient(dojoConfig.rpcUrl); + masterAccount = new Account(provider, new SigningKey(gameManagerData.masterPrivateKey), new FieldElement(gameManagerData.masterAddress)); + burnerManager = new BurnerManager(provider, masterAccount); + + //worldManager.synchronizationMaster.OnEntitySpawned.AddListener(InitEntity); + //foreach (var entity in worldManager.Entities()) + //{ + // InitEntity(entity); + //} + } + + public async void SpawnCharacter() + { + var burner = await burnerManager.DeployBurner(); + spawnedAccounts[burner.Address] = null; + var txHash = await actions.spawn(burner); + } + + + + +} diff --git a/Assets/Scripts/DojoSpawnAndMoveExecuter.cs.meta b/Assets/Scripts/DojoSpawnAndMoveExecuter.cs.meta new file mode 100644 index 00000000..13eb5c72 --- /dev/null +++ b/Assets/Scripts/DojoSpawnAndMoveExecuter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4903969972cd43ea95e8c1fc824e0bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/PlayerController.cs b/Assets/Scripts/PlayerController.cs index 56d01120..d20eb264 100644 --- a/Assets/Scripts/PlayerController.cs +++ b/Assets/Scripts/PlayerController.cs @@ -63,6 +63,8 @@ public class PlayerController : MonoBehaviour /// public static Vector3 lastHouseEntered = Vector3.zero; + [SerializeField] DojoSpawnAndMoveExecuter dojoSpawnAndMoveExecuter; + ///

/// Called when the script is instantiated. /// Initializes the singleton instance and ensures the GameObject isn't destroyed when loading new scenes. @@ -91,6 +93,9 @@ private void Awake() /// void Start() { + + dojoSpawnAndMoveExecuter.SpawnCharacter(); + joystick = GameObject.FindGameObjectWithTag("Joystick").GetComponent(); #if UNITY_STANDALONE_WIN From cb4bfa35cff90df0036a5ed5b5f7d6fe3885e727 Mon Sep 17 00:00:00 2001 From: Cristian Fleita Date: Mon, 2 Dec 2024 14:01:30 -0300 Subject: [PATCH 4/4] chore: get position from torii --- Assets/Scripts/DojoSpawnAndMoveExecuter.cs | 26 +++++++++++++------ Assets/Scripts/PlayerController.cs | 29 +++++++++++++++++++--- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/Assets/Scripts/DojoSpawnAndMoveExecuter.cs b/Assets/Scripts/DojoSpawnAndMoveExecuter.cs index 9e90510b..634d0f09 100644 --- a/Assets/Scripts/DojoSpawnAndMoveExecuter.cs +++ b/Assets/Scripts/DojoSpawnAndMoveExecuter.cs @@ -1,3 +1,4 @@ +using System; using System.Collections; using System.Collections.Generic; using Dojo; @@ -17,6 +18,9 @@ public class DojoSpawnAndMoveExecuter : MonoBehaviour public JsonRpcClient provider; public Account masterAccount; + private Vector2Int currentPosition; + + public Action currentPositionChange; void Awake() { @@ -24,11 +28,7 @@ void Awake() masterAccount = new Account(provider, new SigningKey(gameManagerData.masterPrivateKey), new FieldElement(gameManagerData.masterAddress)); burnerManager = new BurnerManager(provider, masterAccount); - //worldManager.synchronizationMaster.OnEntitySpawned.AddListener(InitEntity); - //foreach (var entity in worldManager.Entities()) - //{ - // InitEntity(entity); - //} + worldManager.synchronizationMaster.OnEntitySpawned.AddListener(InitEntity); } public async void SpawnCharacter() @@ -38,7 +38,19 @@ public async void SpawnCharacter() var txHash = await actions.spawn(burner); } + public async void Move(Direction direction) + { + await actions.move(burnerManager.CurrentBurner ?? masterAccount, direction); + } - - + private void InitEntity(GameObject entity) + { + if (!entity.TryGetComponent(out dojo_starter_Position position)) return; + if (position.player.Hex().Equals(burnerManager.CurrentBurner.Address.Hex())) + { + this.currentPosition = new Vector2Int((int)position.vec.x, (int)position.vec.y); + currentPositionChange.Invoke(currentPosition); + } + + } } diff --git a/Assets/Scripts/PlayerController.cs b/Assets/Scripts/PlayerController.cs index d20eb264..64741541 100644 --- a/Assets/Scripts/PlayerController.cs +++ b/Assets/Scripts/PlayerController.cs @@ -84,9 +84,15 @@ private void Awake() } DontDestroyOnLoad(gameObject); - - } - + dojoSpawnAndMoveExecuter.currentPositionChange += Handle_positionChange; + + } + + private void Handle_positionChange(Vector2Int pos) + { + transform.position = new Vector3(pos.x, pos.y, transform.position.z); + } + /// /// Called when the script starts execution. /// Initializes the FixedJoystick component based on the platform. @@ -139,6 +145,23 @@ void Update() } } + if (Input.GetKeyDown(KeyCode.W)) + { + dojoSpawnAndMoveExecuter.Move(new Direction.Down()); + } + else if (Input.GetKeyDown(KeyCode.A)) + { + dojoSpawnAndMoveExecuter.Move(new Direction.Left()); + } + else if (Input.GetKeyDown(KeyCode.S)) + { + dojoSpawnAndMoveExecuter.Move(new Direction.Up()); + } + else if (Input.GetKeyDown(KeyCode.D)) + { + dojoSpawnAndMoveExecuter.Move(new Direction.Right()); + } + transform.position = new Vector3(Mathf.Clamp(transform.position.x, bottomLeftLimit.x, topRightLimit.x), Mathf.Clamp(transform.position.y, bottomLeftLimit.y, topRightLimit.y), transform.position.z); }