fix(drill): staging 26341433's swap fields; a failed group no longer ends the harness (#20)
The staging drill's run 47 failed on Rust staging 26341433: - Rust added BasePlayer.timeSinceAiming, BaseEntity.ServerPreProcessed and BaseNetworkable.ignoreNetworkLod to the swap's field list (D232): 55 -> 58. On edge now; main at the forced wipe of 2026-11-05. - Harness 0.7.4: place.set.each was refused and the refusal was thrown away; place.spawned failed; reading each[0] of an empty list then killed the coroutine, so the drill waited 45 minutes for a run that had stopped after 10. Place puts its spots on the navmesh, the set checks carry the refusal, a failed place.spawned ends the group, and any group that throws is a <group>.exception FAIL line and the run goes on. - drill.js: rust-staging boots from empty Kits and RunicNPC data, so the write-once example kits match this Rust (s6.examples.fullCondition); the wait ends after 5 minutes without a new harness line; latest.log's tail goes into the issue when the harness did not finish. drill.test.js covers the stall logic. Refs #20, #21 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -45,7 +45,7 @@ namespace Oxide.Plugins
|
||||
/// a made-up user id (11400000001 and up), so <c>IsNpc</c> is false. They take no damage.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Info("RunicNpcTest", "Runic Gateway", "0.7.3")]
|
||||
[Info("RunicNpcTest", "Runic Gateway", "0.7.4")]
|
||||
[Description("RunicNPC stage 2 to 7 tests, the stage 6 spike and stage 9's cost check. A developer tool: never ship it.")]
|
||||
internal class RunicNpcTest : RustPlugin
|
||||
{
|
||||
@@ -753,7 +753,25 @@ namespace Oxide.Plugins
|
||||
continue;
|
||||
}
|
||||
|
||||
while (inner.MoveNext()) yield return inner.Current;
|
||||
// A group that throws is a FAIL line, not the end of the run: yield cannot sit inside a try, so
|
||||
// each step is taken inside one and the value is yielded outside it.
|
||||
while (true)
|
||||
{
|
||||
object step;
|
||||
try
|
||||
{
|
||||
if (!inner.MoveNext()) break;
|
||||
step = inner.Current;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Check($"{g}.exception", false, $"{e.GetType().Name}: {e.Message} at {(e.StackTrace ?? "").Split('\n').FirstOrDefault()?.Trim()}");
|
||||
break;
|
||||
}
|
||||
|
||||
yield return step;
|
||||
}
|
||||
|
||||
Api<int>("RunicNpc_DespawnOwner", Owner);
|
||||
ClearWorld();
|
||||
yield return new WaitForSeconds(1f);
|
||||
@@ -1095,16 +1113,27 @@ namespace Oxide.Plugins
|
||||
|
||||
private IEnumerator Place(Vector3 field)
|
||||
{
|
||||
Vector3 a = field + new Vector3(-40, 0, 0);
|
||||
Vector3 b = field + new Vector3(-40, 0, 30);
|
||||
StandIn(field + new Vector3(-40, 0, 110), 8);
|
||||
Check("place.set.each", Api<string>("RunicNpc_SetPlacement", "t_each", Placement("t_each", a, 3, 20f, "each")) == null, "");
|
||||
Check("place.set.group", Api<string>("RunicNpc_SetPlacement", "t_group", Placement("t_roam", b, 3, 20f, "group")) == null, "");
|
||||
// A roamer's spot must be on the navmesh when it is set (D219), so both spots are put there.
|
||||
Vector3 a = OnMesh(field + new Vector3(-40, 0, 0));
|
||||
Vector3 b = OnMesh(field + new Vector3(-40, 0, 30));
|
||||
StandIn(OnMesh(field + new Vector3(-40, 0, 110)), 8);
|
||||
string eachRefusal = Api<string>("RunicNpc_SetPlacement", "t_each", Placement("t_each", a, 3, 20f, "each"));
|
||||
Check("place.set.each", eachRefusal == null, eachRefusal ?? "");
|
||||
string groupRefusal = Api<string>("RunicNpc_SetPlacement", "t_group", Placement("t_roam", b, 3, 20f, "group"));
|
||||
Check("place.set.group", groupRefusal == null, groupRefusal ?? "");
|
||||
yield return new WaitForSeconds(4f);
|
||||
|
||||
List<Dictionary<string, object>> each = List("placement:t_each");
|
||||
List<Dictionary<string, object>> group = List("placement:t_group");
|
||||
Check("place.spawned", each.Count == 3 && group.Count == 3, $"each {each.Count}, group {group.Count}");
|
||||
if (each.Count != 3 || group.Count != 3)
|
||||
{
|
||||
// Everything below needs both sets alive. Take back what was set and end the group, so the run goes on.
|
||||
Api<bool>("RunicNpc_RemovePlacement", "t_each");
|
||||
Api<bool>("RunicNpc_RemovePlacement", "t_group");
|
||||
Note("place: the placements did not spawn, so the rest of the group is skipped");
|
||||
yield break;
|
||||
}
|
||||
|
||||
// each: kill one; the other two stay, and it alone returns after ~20 s.
|
||||
var survivors = new HashSet<ulong>(each.Skip(1).Select(x => (ulong)x["netId"]));
|
||||
|
||||
Reference in New Issue
Block a user