154 lines
4.1 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|