Files
DTrierFlood_New/Assets/Scripts/Networking/Client/SweQuestStreamClient.cs

154 lines
4.1 KiB
C#

using System;
using System.Net;
using System.Net.Sockets;
using FloodSWE.Streaming;
using FloodSWE.TileGraph;
using UnityEngine;
namespace FloodSWE.Networking
{
public sealed class SweQuestStreamClient : MonoBehaviour
{
[Header("Network")]
public int listenPort = 29011;
[Header("Interpolation")]
public float frameDurationSeconds = 0.1f;
[Header("Filter")]
public bool filterByTile = false;
public int expectedLod = 1;
public int expectedTileX = 1;
public int expectedTileY = 1;
[Header("Output")]
public Material targetMaterial;
public string textureProperty = "_HeightTex";
public Texture2D outputTexture;
public HeightmapPacket lastPacket;
private readonly HeightmapInterpolator interpolator = new HeightmapInterpolator();
private UdpClient socket;
private IPEndPoint endpoint;
private int outputResolution;
private void OnEnable()
{
interpolator.Reset();
interpolator.FrameDurationSeconds = Mathf.Max(0.01f, frameDurationSeconds);
try
{
socket = new UdpClient(listenPort);
socket.Client.Blocking = false;
endpoint = new IPEndPoint(IPAddress.Any, 0);
}
catch (Exception ex)
{
Debug.LogError($"SweQuestStreamClient: failed to open UDP port {listenPort}. {ex.Message}");
enabled = false;
}
}
private void OnDisable()
{
if (socket != null)
{
socket.Close();
socket = null;
}
}
private void Update()
{
PollFrames();
interpolator.Step(Time.deltaTime);
TryUpdateOutputTexture();
}
private void PollFrames()
{
if (socket == null)
{
return;
}
while (socket.Available > 0)
{
byte[] payload;
try
{
payload = socket.Receive(ref endpoint);
}
catch (SocketException)
{
break;
}
if (!SweUdpProtocol.TryDecodeFrame(payload, out HeightmapPacket packet))
{
continue;
}
if (filterByTile)
{
TileId expected = new TileId(expectedLod, expectedTileX, expectedTileY);
if (packet.Tile != expected)
{
continue;
}
}
interpolator.PushPacket(packet);
lastPacket = packet;
}
}
private void TryUpdateOutputTexture()
{
if (!interpolator.TryGetHeights(out float[] heights) || heights == null || heights.Length == 0)
{
return;
}
int resolution = Mathf.RoundToInt(Mathf.Sqrt(heights.Length));
if (resolution <= 0 || resolution * resolution != heights.Length)
{
return;
}
EnsureOutputTexture(resolution);
outputTexture.SetPixelData(heights, 0);
outputTexture.Apply(false, false);
if (targetMaterial != null)
{
targetMaterial.SetTexture(textureProperty, outputTexture);
}
}
private void EnsureOutputTexture(int resolution)
{
if (outputTexture != null && outputResolution == resolution)
{
return;
}
if (outputTexture != null)
{
Destroy(outputTexture);
}
outputTexture = new Texture2D(resolution, resolution, TextureFormat.RFloat, false, true)
{
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Bilinear,
name = "SWE_StreamedHeight"
};
outputResolution = resolution;
}
}
}