Prove generic Unity movement and fire
This commit is contained in:
parent
100dfea51a
commit
38dcdc6d3a
3 changed files with 80 additions and 16 deletions
|
|
@ -162,6 +162,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
}
|
||||
|
||||
[UnityTest]
|
||||
[Timeout(300000)]
|
||||
public IEnumerator GenericCultMeshClientLowersAndMovesAdvertisedWorld()
|
||||
{
|
||||
var endpoint = Environment.GetEnvironmentVariable("EVEUNITY_PROVIDER_ENDPOINT");
|
||||
|
|
@ -244,6 +245,40 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
Assert.That(runtime.ActiveVersion, Is.GreaterThan(initialVersion));
|
||||
Assert.That(Vector3.Distance(FindMarker(root, playerId).transform.position, initialPosition), Is.GreaterThan(0.01f));
|
||||
|
||||
var movementVersion = runtime.ActiveVersion;
|
||||
var focus = runtime.SubmitFocusIntent(playerId);
|
||||
var focusDeadline = Time.realtimeSinceStartup + 12f;
|
||||
while (Time.realtimeSinceStartup < focusDeadline &&
|
||||
(runtime.LastReceipt == null || runtime.LastReceipt.CommandId != focus.CommandId ||
|
||||
runtime.ActiveVersion < runtime.LastReceipt.SourceVersion))
|
||||
{
|
||||
yield return new WaitForSecondsRealtime(0.1f);
|
||||
runtime.Refresh();
|
||||
}
|
||||
Assert.That(runtime.LastReceipt, Is.Not.Null);
|
||||
Assert.That(runtime.LastReceipt.CommandId, Is.EqualTo(focus.CommandId));
|
||||
Assert.That(runtime.LastReceipt.State, Is.EqualTo("accepted").Or.EqualTo("reconciled"));
|
||||
Assert.That(runtime.LastReceipt.SourceVersion, Is.GreaterThan(movementVersion));
|
||||
|
||||
var focusVersion = runtime.ActiveVersion;
|
||||
var action = runtime.SubmitActionIntent(playerId, "0");
|
||||
var actionDeadline = Time.realtimeSinceStartup + 12f;
|
||||
while (Time.realtimeSinceStartup < actionDeadline &&
|
||||
(runtime.LastReceipt == null || runtime.LastReceipt.CommandId != action.CommandId ||
|
||||
runtime.ActiveVersion < runtime.LastReceipt.SourceVersion))
|
||||
{
|
||||
yield return new WaitForSecondsRealtime(0.1f);
|
||||
runtime.Refresh();
|
||||
}
|
||||
Assert.That(runtime.LastReceipt, Is.Not.Null);
|
||||
Assert.That(runtime.LastReceipt.CommandId, Is.EqualTo(action.CommandId));
|
||||
Assert.That(
|
||||
runtime.LastReceipt.State,
|
||||
Is.EqualTo("accepted").Or.EqualTo("reconciled"),
|
||||
runtime.LastReceipt.Message);
|
||||
Assert.That(runtime.LastReceipt.SourceVersion, Is.GreaterThan(focusVersion));
|
||||
Assert.That(runtime.ActiveVersion, Is.GreaterThanOrEqualTo(runtime.LastReceipt.SourceVersion));
|
||||
|
||||
var light = lightObject.AddComponent<Light>();
|
||||
light.type = LightType.Directional;
|
||||
light.intensity = 1.4f;
|
||||
|
|
@ -263,11 +298,16 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
}
|
||||
}
|
||||
var playerMarker = FindMarker(root, playerId);
|
||||
var playerRenderer = playerMarker.GetComponentInChildren<Renderer>();
|
||||
Assert.That(playerRenderer, Is.Not.Null, "The provider-authored player prefab has no renderable visual.");
|
||||
var playerBounds = playerRenderer.bounds;
|
||||
var cameraDistance = Mathf.Max(8f, playerBounds.extents.magnitude * 4f);
|
||||
camera.transform.position = playerBounds.center + new Vector3(1f, 0.8f, -1.2f).normalized * cameraDistance;
|
||||
var playerRenderers = playerMarker.GetComponentsInChildren<Renderer>();
|
||||
Assert.That(playerRenderers, Is.Not.Empty, "The provider-authored player prefab has no renderable visual.");
|
||||
var playerBounds = playerRenderers[0].bounds;
|
||||
foreach (var renderer in playerRenderers)
|
||||
playerBounds.Encapsulate(renderer.bounds);
|
||||
var halfFovRadians = camera.fieldOfView * 0.5f * Mathf.Deg2Rad;
|
||||
var cameraDistance = Mathf.Max(8f, playerBounds.extents.magnitude / Mathf.Tan(halfFovRadians) * 1.35f);
|
||||
camera.nearClipPlane = Mathf.Max(0.01f, cameraDistance * 0.001f);
|
||||
camera.farClipPlane = Mathf.Max(1000f, cameraDistance + playerBounds.size.magnitude * 4f);
|
||||
camera.transform.position = playerBounds.center + new Vector3(1f, 0.65f, -1.2f).normalized * cameraDistance;
|
||||
camera.transform.LookAt(playerBounds.center);
|
||||
target = new RenderTexture(640, 360, 24, RenderTextureFormat.ARGB32);
|
||||
camera.targetTexture = target;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ namespace GameCult.Eve.UnityScene
|
|||
private readonly List<AssetBundle> _assetBundles = new List<AssetBundle>();
|
||||
private CultMeshNode? _node;
|
||||
private CultMeshSnapshotEndpoint? _snapshot;
|
||||
private CultMeshSnapshotSession? _assetSession;
|
||||
private CultNetDocumentRegistry? _networkRegistry;
|
||||
private CultNetShardDescriptor? _replicaShard;
|
||||
private EveProviderAdvertisementDocument? _advertisement;
|
||||
|
|
@ -148,8 +149,10 @@ namespace GameCult.Eve.UnityScene
|
|||
_assetBundles.Clear();
|
||||
_prefabs.Clear();
|
||||
_node?.Dispose();
|
||||
_assetSession?.Dispose();
|
||||
_node = null;
|
||||
_snapshot = null;
|
||||
_assetSession = null;
|
||||
_networkRegistry = null;
|
||||
_replicaShard = null;
|
||||
_pendingCommandIds.Clear();
|
||||
|
|
@ -215,6 +218,19 @@ namespace GameCult.Eve.UnityScene
|
|||
RudpMaxFragmentBytes = 2048
|
||||
}
|
||||
});
|
||||
_assetSession = CultMesh.SnapshotSession(
|
||||
_endpoint,
|
||||
new CultMeshSnapshotRequestOptions
|
||||
{
|
||||
ShardId = RemoteShardId,
|
||||
ShardEpoch = 1,
|
||||
ConnectTimeout = TimeSpan.FromSeconds(5),
|
||||
ResponseTimeout = TimeSpan.FromSeconds(10),
|
||||
MessageIdPrefix = "eve-unity-assets",
|
||||
RudpRuntimeId = $"{_runtimeId}.assets",
|
||||
RudpMaxFragmentBytes = 2048
|
||||
},
|
||||
_networkRegistry);
|
||||
}
|
||||
|
||||
private void ResolveAdvertisement()
|
||||
|
|
@ -294,7 +310,7 @@ namespace GameCult.Eve.UnityScene
|
|||
foreach (var group in selected.GroupBy(selection => selection.Variant!.Uri, StringComparer.Ordinal))
|
||||
{
|
||||
var variant = group.First().Variant!;
|
||||
var manifest = _snapshot.FetchDocumentsAsync<CultMeshCdnArtifactManifest>(
|
||||
var manifest = _assetSession!.FetchDocumentsAsync<CultMeshCdnArtifactManifest>(
|
||||
recordKeys: new[] { variant.Uri },
|
||||
schemaIds: new[] { CultMeshCdnSchemaVersions.ArtifactManifest })
|
||||
.GetAwaiter()
|
||||
|
|
@ -332,20 +348,26 @@ namespace GameCult.Eve.UnityScene
|
|||
private byte[] ReadBundle(CultMeshCdnArtifactManifest manifest)
|
||||
{
|
||||
var bytes = new byte[checked((int)manifest.SizeBytes)];
|
||||
foreach (var reference in manifest.Chunks.OrderBy(chunk => chunk.Offset))
|
||||
var references = manifest.Chunks.OrderBy(chunk => chunk.Offset).ToArray();
|
||||
for (var index = 0; index < references.Length; index += 2)
|
||||
{
|
||||
var chunk = _snapshot!
|
||||
var batch = references.Skip(index).Take(2).ToArray();
|
||||
var chunks = _assetSession!
|
||||
.FetchDocumentsAsync<CultMeshCdnArtifactChunk>(
|
||||
recordKeys: new[] { reference.RecordKey },
|
||||
recordKeys: batch.Select(reference => reference.RecordKey).ToArray(),
|
||||
schemaIds: new[] { CultMeshCdnSchemaVersions.ArtifactChunk })
|
||||
.GetAwaiter()
|
||||
.GetResult()
|
||||
.FirstOrDefault();
|
||||
if (chunk == null)
|
||||
throw new InvalidOperationException($"Provider asset chunk '{reference.RecordKey}' was not available.");
|
||||
if (chunk.SizeBytes != reference.SizeBytes || chunk.Payload.Length != reference.SizeBytes)
|
||||
throw new InvalidDataException($"Provider asset chunk '{reference.RecordKey}' size did not match its manifest.");
|
||||
Buffer.BlockCopy(chunk.Payload, 0, bytes, checked((int)reference.Offset), reference.SizeBytes);
|
||||
.GetResult();
|
||||
foreach (var reference in batch)
|
||||
{
|
||||
var chunk = chunks.FirstOrDefault(candidate =>
|
||||
string.Equals(candidate.ChunkHash, reference.ChunkHash, StringComparison.Ordinal));
|
||||
if (chunk == null)
|
||||
throw new InvalidOperationException($"Provider asset chunk '{reference.RecordKey}' was not available.");
|
||||
if (chunk.SizeBytes != reference.SizeBytes || chunk.Payload.Length != reference.SizeBytes)
|
||||
throw new InvalidDataException($"Provider asset chunk '{reference.RecordKey}' size did not match its manifest.");
|
||||
Buffer.BlockCopy(chunk.Payload, 0, bytes, checked((int)reference.Offset), reference.SizeBytes);
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ $daemonArguments = @(
|
|||
"--client-cultmesh-host", "127.0.0.1",
|
||||
"--client-cultmesh-advertise-host", "127.0.0.1",
|
||||
"--client-cultmesh-port", $Port,
|
||||
"--tick-interval-ms", 250,
|
||||
"--fixed-delta-ms", 20,
|
||||
"--no-odin-announcements"
|
||||
)
|
||||
$env:AETHERIA_TRACE_EVE_SNAPSHOTS = "1"
|
||||
|
|
|
|||
Reference in a new issue