diff --git a/TestVelGameServer/Assets/Plugins/Dissonance.meta b/TestVelGameServer/Assets/Plugins/Dissonance.meta index accd5b8..701466a 100644 --- a/TestVelGameServer/Assets/Plugins/Dissonance.meta +++ b/TestVelGameServer/Assets/Plugins/Dissonance.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8adda10125f861c4ab834bb9bd2056b5 +guid: b34f6c4b68ec079449bfb4be05fbfec7 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/TestVelGameServer/Assets/Samples/VelNet/1.0.4/Example/test_binary.unity b/TestVelGameServer/Assets/Samples/VelNet/1.0.4/Example/test_binary.unity new file mode 100644 index 0000000..13b93be --- /dev/null +++ b/TestVelGameServer/Assets/Samples/VelNet/1.0.4/Example/test_binary.unity @@ -0,0 +1,323 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 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: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + 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: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &516411417 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 516411421} + - component: {fileID: 516411420} + - component: {fileID: 516411419} + - component: {fileID: 516411418} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &516411418 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 516411417} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 233344de094f11341bdb834d564708dc, type: 3} + m_Name: + m_EditorClassIdentifier: + host: 127.0.0.1 + port: 80 + udpConnected: 0 + userid: -1 + room: + connected: 0 + prefabs: [] + sceneObjects: [] + deletedSceneObjects: [] +--- !u!81 &516411419 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 516411417} + m_Enabled: 1 +--- !u!20 &516411420 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 516411417} + 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_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 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 &516411421 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 516411417} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &756322628 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 756322630} + - component: {fileID: 756322629} + 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 &756322629 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 756322628} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &756322630 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 756322628} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} diff --git a/TestVelGameServer/Assets/Samples/VelNet/1.0.4/Example/test_binary.unity.meta b/TestVelGameServer/Assets/Samples/VelNet/1.0.4/Example/test_binary.unity.meta new file mode 100644 index 0000000..276a764 --- /dev/null +++ b/TestVelGameServer/Assets/Samples/VelNet/1.0.4/Example/test_binary.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2e6e0ddeb76e51b46afc0f0a43386ff2 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/TestVelGameServer/Packages/VelNetUnity/Runtime/VelNetBinaryManager.cs b/TestVelGameServer/Packages/VelNetUnity/Runtime/VelNetBinaryManager.cs new file mode 100644 index 0000000..ec4c4b4 --- /dev/null +++ b/TestVelGameServer/Packages/VelNetUnity/Runtime/VelNetBinaryManager.cs @@ -0,0 +1,775 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using UnityEngine; +using System.Net; +using UnityEngine.SceneManagement; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; +using System.IO; + +namespace VelNet +{ + [AddComponentMenu("VelNet/VelNet Manager")] + public class VelNetBinaryManager : MonoBehaviour + { + public enum MessageType + { + OTHERS = 0, + ALL = 1, + OTHERS_ORDERED = 2, + ALL_ORDERED = 3 + }; + + public string host; + public int port; + + public static VelNetBinaryManager instance; + + private TcpClient socketConnection; + private Socket udpSocket; + public bool udpConnected; + private IPEndPoint RemoteEndPoint; + private Thread clientReceiveThread; + private Thread clientReceiveThreadUDP; + public int userid = -1; + public string room; + private int messagesReceived = 0; + + public readonly Dictionary players = new Dictionary(); + + /// + /// We just joined a room + /// string - the room name + /// + public static Action OnJoinedRoom; + + /// + /// We just left a room + /// string - the room name we left + /// + public static Action OnLeftRoom; + + /// + /// Somebody else just joined our room + /// + public static Action OnPlayerJoined; + + /// + /// Somebody else just left our room + /// + public static Action OnPlayerLeft; + + public static Action OnConnectedToServer; + public static Action MessageReceived; + public static Action LoggedIn; + public static Action RoomsReceived; + + public bool connected; + + public List prefabs = new List(); + public NetworkObject[] sceneObjects; + public List deletedSceneObjects = new List(); + + /// + /// Maintains a list of all known objects on the server (ones that have ids) + /// + public readonly Dictionary objects = new Dictionary(); + + /// + /// Maintains a list of all known groups on the server + /// + public readonly Dictionary> groups = new Dictionary>(); + + private VelNetPlayer masterPlayer; + public static VelNetPlayer LocalPlayer => instance.players.Where(p => p.Value.isLocal).Select(p => p.Value).FirstOrDefault(); + public static bool InRoom => LocalPlayer != null && LocalPlayer.room != "-1" && LocalPlayer.room != ""; + + + // Use this for initialization + public class Message + { + public int type; + public string text; + public int sender; + } + + public readonly List receivedMessages = new List(); + + private void Awake() + { + if (instance != null) + { + Debug.LogError("Multiple NetworkManagers detected! Bad!", this); + } + + instance = this; + + SceneManager.sceneLoaded += (scene, mode) => + { + // add all local network objects + sceneObjects = FindObjectsOfType().Where(o => o.isSceneObject).ToArray(); + }; + } + + private IEnumerator Start() + { + ConnectToTcpServer(); + yield return null; + + try + { + OnConnectedToServer?.Invoke(); + } + // prevent errors in subscribers from breaking our code + catch (Exception e) + { + Debug.LogError(e); + } + } + + + private void AddMessage(Message m) + { + lock (receivedMessages) + { + //Debug.Log(messagesReceived++); + receivedMessages.Add(m); + } + } + + private void Update() + { + lock (receivedMessages) + { + ////the main thread, which can do Unity stuff + //foreach (Message m in receivedMessages) + //{ + // switch (m.type) + // { + // // when you join the server + // case 0: + // userid = m.sender; + // Debug.Log("joined server"); + + // try + // { + // LoggedIn?.Invoke(); + // } + // // prevent errors in subscribers from breaking our code + // catch (Exception e) + // { + // Debug.LogError(e); + // } + + // //start the udp thread + // clientReceiveThreadUDP = new Thread(ListenForDataUDP); + // clientReceiveThreadUDP.IsBackground = true; + // clientReceiveThreadUDP.Start(); + // break; + // // if this message is for me, that means I joined a new room... + // case 2 when userid == m.sender: + // { + // string oldRoom = LocalPlayer?.room; + + // // we clear the list, but will recreate as we get messages from people in our room + // players.Clear(); + // masterPlayer = null; + + // if (m.text != "") + // { + // VelNetPlayer player = new VelNetPlayer + // { + // isLocal = true, + // userid = m.sender, + // room = m.text + // }; + + // players.Add(userid, player); + // if (m.text != "") + // { + // try + // { + // OnJoinedRoom?.Invoke(m.text); + // } + // // prevent errors in subscribers from breaking our code + // catch (Exception e) + // { + // Debug.LogError(e); + // } + // } + // } + // // we just left a room + // else + // { + // // delete all networkobjects that aren't sceneobjects or are null now + // objects + // .Where(kvp => kvp.Value == null || !kvp.Value.isSceneObject) + // .Select(o => o.Key) + // .ToList().ForEach(NetworkDestroy); + + // // then remove references to the ones that are left + // objects.Clear(); + + // // empty all the groups + // foreach (string group in instance.groups.Keys) + // { + // SetupMessageGroup(group, new List()); + // } + + // instance.groups.Clear(); + + // try + // { + // OnLeftRoom?.Invoke(oldRoom); + // } + // // prevent errors in subscribers from breaking our code + // catch (Exception e) + // { + // Debug.LogError(e); + // } + // } + + // break; + // } + // // not for me, a player is joining or leaving + // case 2: + // { + // VelNetPlayer me = players[userid]; + + // if (me.room != m.text) + // { + // // we got a left message, kill it + // // change ownership of all objects to master + // List deleteObjects = new List(); + // foreach (KeyValuePair kvp in objects) + // { + // if (kvp.Value.owner == players[m.sender]) // the owner is the player that left + // { + // // if this object has locked ownership, delete it + // if (kvp.Value.ownershipLocked) + // { + // deleteObjects.Add(kvp.Value.networkId); + // } + // // I'm the local master player, so can take ownership immediately + // else if (me.isLocal && me == masterPlayer) + // { + // TakeOwnership(kvp.Key); + // } + // // the master player left, so everyone should set the owner null (we should get a new master shortly) + // else if (players[m.sender] == masterPlayer) + // { + // kvp.Value.owner = null; + // } + // } + // } + + // // TODO this may check for ownership in the future. We don't need ownership here + // deleteObjects.ForEach(NetworkDestroy); + + // players.Remove(m.sender); + // } + // else + // { + // // we got a join message, create it + // VelNetPlayer player = new VelNetPlayer + // { + // isLocal = false, + // room = m.text, + // userid = m.sender + // }; + // players.Add(m.sender, player); + // try + // { + // OnPlayerJoined?.Invoke(player); + // } + // // prevent errors in subscribers from breaking our code + // catch (Exception e) + // { + // Debug.LogError(e); + // } + // } + + // break; + // } + // // generic message + // case 3: + // if (players.ContainsKey(m.sender)) + // { + // players[m.sender]?.HandleMessage(m); + // } + // else + // { + // Debug.LogError("Received message from player that doesn't exist: " + m.text); + // } + + // break; + // // change master player (this should only happen when the first player joins or if the master player leaves) + // case 4: + // { + // if (masterPlayer == null) + // { + // masterPlayer = players[m.sender]; + + // // no master player yet, add the scene objects + + // for (int i = 0; i < sceneObjects.Length; i++) + // { + // sceneObjects[i].networkId = -1 + "-" + i; + // sceneObjects[i].owner = masterPlayer; + // sceneObjects[i].isSceneObject = true; // needed for special handling when deleted + // objects.Add(sceneObjects[i].networkId, sceneObjects[i]); + // } + // } + // else + // { + // masterPlayer = players[m.sender]; + // } + + // masterPlayer.SetAsMasterPlayer(); + + // // master player should take over any objects that do not have an owner + // foreach (KeyValuePair kvp in objects) + // { + // kvp.Value.owner ??= masterPlayer; + // } + + // break; + // } + // } + + // MessageReceived?.Invoke(m); + //} + + //receivedMessages.Clear(); + } + } + + private void OnApplicationQuit() + { + socketConnection.Close(); + } + + /// + /// Setup socket connection. + /// + private void ConnectToTcpServer() + { + try + { + clientReceiveThread = new Thread(ListenForData); + clientReceiveThread.IsBackground = true; + clientReceiveThread.Start(); + } + catch (Exception e) + { + Debug.Log("On client connect exception " + e); + } + } + + private void HandleMessage(string s) // this parses messages from the server, and adds them to a queue to be processed on the main thread + { + // Debug.Log("Received: " + s); + Message m = new Message(); + string[] sections = s.Split(':'); + if (sections.Length <= 0) return; + + int type = int.Parse(sections[0]); + + switch (type) + { + case 0: // logged in message + { + if (sections.Length > 1) + { + m.type = type; + m.sender = int.Parse(sections[1]); + m.text = ""; + AddMessage(m); + } + + break; + } + case 1: // room info message + { + break; + } + case 2: // joined room message + { + if (sections.Length > 2) + { + m.type = 2; + int user_id = int.Parse(sections[1]); + m.sender = user_id; + string new_room = sections[2]; + m.text = new_room; + + AddMessage(m); + } + + break; + } + case 3: // text message + { + if (sections.Length > 2) + { + m.type = 3; + m.sender = int.Parse(sections[1]); + m.text = sections[2]; + AddMessage(m); + } + + break; + } + case 4: // change master client + { + if (sections.Length > 1) + { + m.type = 4; + m.sender = int.Parse(sections[1]); + AddMessage(m); + } + + break; + } + } + } + + /// + /// Runs in background clientReceiveThread; Listens for incomming data. + /// + private void ListenForData() + { + connected = true; + try + { + socketConnection = new TcpClient(host, port); + socketConnection.NoDelay = true; + byte[] bytes = new byte[1024]; + string partialMessage = ""; + Login("Kyle", "Johnsen"); + while (true) + { + + // Get a stream object for reading + using NetworkStream stream = socketConnection.GetStream(); + int length; + // Read incomming stream into byte arrary. + while ((length = stream.Read(bytes, 0, bytes.Length)) != 0) + { + Debug.Log("read " + length + " bytes!"); + //byte[] incommingData = new byte[length]; + //Array.Copy(bytes, 0, incommingData, 0, length); + //// Convert byte array to string message. + //string serverMessage = Encoding.ASCII.GetString(incommingData); + //string[] sections = serverMessage.Split('\n'); + //if (sections.Length > 1) + //{ + // lock (receivedMessages) + // { + // for (int i = 0; i < sections.Length - 1; i++) + // { + // if (i == 0) + // { + // HandleMessage(partialMessage + sections[0]); + // partialMessage = ""; + // } + // else + // { + // HandleMessage(sections[i]); + // } + // } + // } + //} + + //partialMessage = partialMessage + sections[sections.Length - 1]; + } + } + } + + + catch (Exception socketException) + { + Debug.Log("Socket exception: " + socketException); + } + + connected = false; + } + + private void ListenForDataUDP() + { + //I don't yet have a UDP connection + try + { + IPAddress[] addresses = Dns.GetHostAddresses(host); + Debug.Assert(addresses.Length > 0); + RemoteEndPoint = new IPEndPoint(addresses[0], port); + + + udpSocket = new Socket(AddressFamily.InterNetwork, + SocketType.Dgram, ProtocolType.Udp); + + + udpConnected = false; + byte[] buffer = new byte[1024]; + while (true) + { + string welcome = userid + ":0:Hello"; + byte[] data = Encoding.ASCII.GetBytes(welcome); + udpSocket.SendTo(data, data.Length, SocketFlags.None, RemoteEndPoint); + + if (udpSocket.Available == 0) + { + Thread.Sleep(100); + Debug.Log("Waiting for UDP response"); + } + else + { + break; + } + } + + udpConnected = true; + while (true) + { + int numReceived = udpSocket.Receive(buffer); + + string message = Encoding.UTF8.GetString(buffer, 0, numReceived); + + string[] sections = message.Split(':'); + if (sections[0] == "0") + { + Debug.Log("UDP connected"); + } + + if (sections[0] == "3") + { + HandleMessage(message); + } + } + } + catch (Exception socketException) + { + Debug.Log("Socket exception: " + socketException); + } + } + + private static void SendUdpMessage(string message) + { + if (instance.udpSocket == null || !instance.udpConnected) + { + return; + } + + byte[] data = Encoding.UTF8.GetBytes(message); + //Debug.Log("Attempting to send: " + message); + instance.udpSocket.SendTo(data, data.Length, SocketFlags.None, instance.RemoteEndPoint); + } + + /// + /// Send message to server using socket connection. + /// + private static void SendNetworkMessage(byte[] message) + { + // Debug.Log("Sent: " + clientMessage); + if (instance.socketConnection == null) + { + return; + } + + try + { + // Get a stream object for writing. + NetworkStream stream = instance.socketConnection.GetStream(); + if (stream.CanWrite) + { + + stream.Write(message,0,message.Length); + } + } + catch (SocketException socketException) + { + Debug.Log("Socket exception: " + socketException); + } + } + + /// + /// Connects to the server with a username + /// + /// + public static byte[] get_be_bytes(int n) + { + return BitConverter.GetBytes(n).Reverse().ToArray(); + } + public static void Login(string username, string password) + { + + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + + byte[] uB = Encoding.UTF8.GetBytes(username); + byte[] uP = Encoding.UTF8.GetBytes(password); + writer.Write((byte)0); + writer.Write(get_be_bytes(uB.Length)); + writer.Write(uB); + writer.Write(get_be_bytes(uP.Length)); + writer.Write(uP); + + SendNetworkMessage(stream.ToArray()); + Join("MyRoom"); + } + + /// + /// Joins a room by name + /// + /// The name of the room to join + public static void Join(string roomname) + { + MemoryStream stream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(stream); + + byte[] R = Encoding.UTF8.GetBytes(roomname); + writer.Write((byte)2); + writer.Write(get_be_bytes(R.Length)); + writer.Write(R); + SendNetworkMessage(stream.ToArray()); + } + + /// + /// Leaves a room if we're in one + /// + public static void Leave() + { + //if (InRoom) SendNetworkMessage("2:-1"); + } + + public static void SendTo(MessageType type, string message, bool reliable = true) + { + if (reliable) + { + //SendNetworkMessage("3:" + (int)type + ":" + message); + } + else + { + SendUdpMessage(instance.userid + ":3:" + (int)type + ":" + message); + } + } + + public static void SendToGroup(string group, string message, bool reliable = true) + { + if (reliable) + { + //SendNetworkMessage("4:" + group + ":" + message); + } + else + { + SendUdpMessage(instance.userid + ":4:" + group + ":" + message); + } + } + + /// + /// changes the designated group that sendto(4) will go to + /// + public static void SetupMessageGroup(string groupName, List userIds) + { + if (userIds.Count > 0) + { + instance.groups[groupName] = userIds.ToList(); + } + + //SendNetworkMessage($"5:{groupName}:{string.Join(":", userIds)}"); + } + + + public static NetworkObject InstantiateNetworkObject(string prefabName) + { + VelNetPlayer localPlayer = LocalPlayer; + NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName); + if (prefab == null) + { + Debug.LogError("Couldn't find a prefab with that name: " + prefabName); + return null; + } + + string networkId = localPlayer.userid + "-" + localPlayer.lastObjectId++; + if (instance.objects.ContainsKey(networkId)) + { + Debug.LogError("Can't instantiate object. Obj with that network ID was already instantiated.", instance.objects[networkId]); + return null; + } + NetworkObject newObject = Instantiate(prefab); + newObject.networkId = networkId; + newObject.prefabName = prefabName; + newObject.owner = localPlayer; + instance.objects.Add(newObject.networkId, newObject); + + // only sent to others, as I already instantiated this. Nice that it happens immediately. + SendTo(MessageType.OTHERS, "7," + newObject.networkId + "," + prefabName); + + return newObject; + } + + public static void SomebodyInstantiatedNetworkObject(string networkId, string prefabName, VelNetPlayer owner) + { + NetworkObject prefab = instance.prefabs.Find(p => p.name == prefabName); + if (prefab == null) return; + NetworkObject newObject = Instantiate(prefab); + newObject.networkId = networkId; + newObject.prefabName = prefabName; + newObject.owner = owner; + instance.objects.Add(newObject.networkId, newObject); + } + + public static void NetworkDestroy(NetworkObject obj) + { + NetworkDestroy(obj.networkId); + } + + public static void NetworkDestroy(string networkId) + { + if (!instance.objects.ContainsKey(networkId)) return; + NetworkObject obj = instance.objects[networkId]; + if (obj == null) + { + instance.objects.Remove(networkId); + return; + } + if (obj.isSceneObject) + { + instance.deletedSceneObjects.Add(networkId); + } + + Destroy(obj.gameObject); + instance.objects.Remove(networkId); + } + + /// + /// Takes local ownership of an object by id. + /// + /// Network ID of the object to transfer + /// True if successfully transferred, False if transfer message not sent + public static bool TakeOwnership(string networkId) + { + // local player must exist + if (LocalPlayer == null) return false; + + // obj must exist + if (!instance.objects.ContainsKey(networkId)) return false; + + // if the ownership is locked, fail + if (instance.objects[networkId].ownershipLocked) return false; + + // immediately successful + instance.objects[networkId].owner = LocalPlayer; + + // must be ordered, so that ownership transfers are not confused. Also sent to all players, so that multiple simultaneous requests will result in the same outcome. + SendTo(MessageType.ALL_ORDERED, "6," + networkId); + + return true; + } + } +} \ No newline at end of file diff --git a/TestVelGameServer/Packages/VelNetUnity/Runtime/VelNetBinaryManager.cs.meta b/TestVelGameServer/Packages/VelNetUnity/Runtime/VelNetBinaryManager.cs.meta new file mode 100644 index 0000000..014ff23 --- /dev/null +++ b/TestVelGameServer/Packages/VelNetUnity/Runtime/VelNetBinaryManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 233344de094f11341bdb834d564708dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/TestVelGameServer/Packages/manifest.json b/TestVelGameServer/Packages/manifest.json index 0da73bc..9dde81b 100644 --- a/TestVelGameServer/Packages/manifest.json +++ b/TestVelGameServer/Packages/manifest.json @@ -8,7 +8,7 @@ "com.unity.textmeshpro": "3.0.6", "com.unity.timeline": "1.4.8", "com.unity.ugui": "1.0.0", - "edu.uga.engr.vel.velnet.dissonance": "file:S:/git_repo/VelNetDissonanceIntegration", + "edu.uga.engr.vel.velnet.dissonance": "file:c:/git_repo/VelNetDissonanceIntegration", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", "com.unity.modules.animation": "1.0.0", diff --git a/TestVelGameServer/Packages/packages-lock.json b/TestVelGameServer/Packages/packages-lock.json index afe1934..0a48dcc 100644 --- a/TestVelGameServer/Packages/packages-lock.json +++ b/TestVelGameServer/Packages/packages-lock.json @@ -106,7 +106,7 @@ "dependencies": {} }, "edu.uga.engr.vel.velnet.dissonance": { - "version": "file:S:/git_repo/VelNetDissonanceIntegration", + "version": "file:c:/git_repo/VelNetDissonanceIntegration", "depth": 0, "source": "local", "dependencies": { diff --git a/TestVelGameServer/ProjectSettings/EditorBuildSettings.asset b/TestVelGameServer/ProjectSettings/EditorBuildSettings.asset index ba9b4aa..b07974f 100644 --- a/TestVelGameServer/ProjectSettings/EditorBuildSettings.asset +++ b/TestVelGameServer/ProjectSettings/EditorBuildSettings.asset @@ -6,6 +6,6 @@ EditorBuildSettings: serializedVersion: 2 m_Scenes: - enabled: 1 - path: Assets/Samples/VelNet/1.0.4/Example/test.unity - guid: e4e43899246c941c78acfc59ce2f664a + path: Assets/Samples/VelNet/1.0.4/Example/test_binary.unity + guid: 2e6e0ddeb76e51b46afc0f0a43386ff2 m_configObjects: {} diff --git a/TestVelGameServer/ProjectSettings/ProjectVersion.txt b/TestVelGameServer/ProjectSettings/ProjectVersion.txt index 24993f7..e610e28 100644 --- a/TestVelGameServer/ProjectSettings/ProjectVersion.txt +++ b/TestVelGameServer/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2020.3.23f1 -m_EditorVersionWithRevision: 2020.3.23f1 (c5d91304a876) +m_EditorVersion: 2020.3.11f1 +m_EditorVersionWithRevision: 2020.3.11f1 (99c7afb366b3)