fix(drill): place spots found up to 15 m from the navmesh; count only this run's Oxide errors (#22)
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in 1m28s
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in 1m28s
Run 49: place.set.each was refused "4.4 m from the navmesh", because OnMesh searched 3 m and returned the unsnapped point; Place now searches 15 m. The drill reported run 48's four error lines again: oxideErrors read the whole day's Oxide log, and now reads only what was added after the drill started the rig. Refs #20, #22 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -1113,9 +1113,10 @@ namespace Oxide.Plugins
|
|||||||
|
|
||||||
private IEnumerator Place(Vector3 field)
|
private IEnumerator Place(Vector3 field)
|
||||||
{
|
{
|
||||||
// A roamer's spot must be on the navmesh when it is set (D219), so both spots are put there.
|
// A roamer's spot must be on the navmesh when it is set (D219), so both spots are put there; the
|
||||||
Vector3 a = OnMesh(field + new Vector3(-40, 0, 0));
|
// wider search because a fixed offset from the field can land a few metres off it (run 49: 4.4 m).
|
||||||
Vector3 b = OnMesh(field + new Vector3(-40, 0, 30));
|
Vector3 a = OnMesh(field + new Vector3(-40, 0, 0), 15f);
|
||||||
|
Vector3 b = OnMesh(field + new Vector3(-40, 0, 30), 15f);
|
||||||
StandIn(OnMesh(field + new Vector3(-40, 0, 110)), 8);
|
StandIn(OnMesh(field + new Vector3(-40, 0, 110)), 8);
|
||||||
string eachRefusal = Api<string>("RunicNpc_SetPlacement", "t_each", Placement("t_each", a, 3, 20f, "each"));
|
string eachRefusal = Api<string>("RunicNpc_SetPlacement", "t_each", Placement("t_each", a, 3, 20f, "each"));
|
||||||
Check("place.set.each", eachRefusal == null, eachRefusal ?? "");
|
Check("place.set.each", eachRefusal == null, eachRefusal ?? "");
|
||||||
@@ -1569,11 +1570,11 @@ namespace Oxide.Plugins
|
|||||||
return floor;
|
return floor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector3 OnMesh(Vector3 p)
|
private static Vector3 OnMesh(Vector3 p, float radius = 3f)
|
||||||
{
|
{
|
||||||
p.y = TerrainMeta.HeightMap.GetHeight(p);
|
p.y = TerrainMeta.HeightMap.GetHeight(p);
|
||||||
NavMeshHit hit;
|
NavMeshHit hit;
|
||||||
return SampleNavmesh(p, 3f, out hit) ? hit.position : p;
|
return SampleNavmesh(p, radius, out hit) ? hit.position : p;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JObject Placement(string profile, Vector3 at, int count, float respawn, string mode) =>
|
private static JObject Placement(string profile, Vector3 at, int count, float respawn, string mode) =>
|
||||||
|
|||||||
@@ -281,6 +281,7 @@ async function live(a) {
|
|||||||
for (const f of FRESH_DATA) await p.rm(rig, f) // already gone is fine: rm swallows it
|
for (const f of FRESH_DATA) await p.rm(rig, f) // already gone is fine: rm swallows it
|
||||||
await p.write(rig, KITS_FILE, JSON.stringify(harnessKits(), null, 2))
|
await p.write(rig, KITS_FILE, JSON.stringify(harnessKits(), null, 2))
|
||||||
|
|
||||||
|
const logMark = await oxideLogMark(p, rig)
|
||||||
log(`starting ${RIG} on ${branch}`)
|
log(`starting ${RIG} on ${branch}`)
|
||||||
const started = Date.now()
|
const started = Date.now()
|
||||||
await p.power(rig, 'start')
|
await p.power(rig, 'start')
|
||||||
@@ -298,7 +299,7 @@ async function live(a) {
|
|||||||
const status = await waitStatus(p, rig, 30 * 60000)
|
const status = await waitStatus(p, rig, 30 * 60000)
|
||||||
if (!status) {
|
if (!status) {
|
||||||
finding('RunicNPC did not load: `rnpc.status` never answered.')
|
finding('RunicNPC did not load: `rnpc.status` never answered.')
|
||||||
result.oxideErrors = await oxideErrors(p, rig)
|
result.oxideErrors = await oxideErrors(p, rig, logMark)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result.status = status
|
result.status = status
|
||||||
@@ -322,7 +323,7 @@ async function live(a) {
|
|||||||
}
|
}
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
finding('The test harness did not load (`rnt.run all` was not answered).')
|
finding('The test harness did not load (`rnt.run all` was not answered).')
|
||||||
result.oxideErrors = await oxideErrors(p, rig)
|
result.oxideErrors = await oxideErrors(p, rig, logMark)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result.ran = true
|
result.ran = true
|
||||||
@@ -337,7 +338,7 @@ async function live(a) {
|
|||||||
}
|
}
|
||||||
for (const f of result.harness.failed) finding(`Harness: ${f}`)
|
for (const f of result.harness.failed) finding(`Harness: ${f}`)
|
||||||
log(`harness: ${result.harness.pass} pass, ${result.harness.fail} fail`)
|
log(`harness: ${result.harness.pass} pass, ${result.harness.fail} fail`)
|
||||||
result.oxideErrors = await oxideErrors(p, rig)
|
result.oxideErrors = await oxideErrors(p, rig, logMark)
|
||||||
if (result.oxideErrors.length) finding(`RunicNPC logged ${result.oxideErrors.length} error line(s) in Oxide's log during the run.`)
|
if (result.oxideErrors.length) finding(`RunicNPC logged ${result.oxideErrors.length} error line(s) in Oxide's log during the run.`)
|
||||||
await p.command(rig, 'rnt.clear').catch(() => {})
|
await p.command(rig, 'rnt.clear').catch(() => {})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -490,10 +491,17 @@ function summarise(lines) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** RunicNPC's and the harness's error lines from today's Oxide log. */
|
/** RunicNPC's and the harness's error lines from today's Oxide log. */
|
||||||
async function oxideErrors(p, id) {
|
/** Where Oxide's log of today ends now, so oxideErrors reads only what a run adds (run 49 counted run 48's). */
|
||||||
|
async function oxideLogMark(p, id) {
|
||||||
|
const day = now().slice(0, 10)
|
||||||
|
return { day, length: ((await p.readOr(id, `/oxide/logs/oxide_${day}.txt`, '')) || '').length }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function oxideErrors(p, id, since = null) {
|
||||||
const day = now().slice(0, 10)
|
const day = now().slice(0, 10)
|
||||||
const text = (await p.readOr(id, `/oxide/logs/oxide_${day}.txt`, '')) || ''
|
const text = (await p.readOr(id, `/oxide/logs/oxide_${day}.txt`, '')) || ''
|
||||||
return text
|
return text
|
||||||
|
.slice(since && since.day === day ? since.length : 0)
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.filter((l) => /RunicNPC|RunicNpcTest/.test(l) && /\[Error\]|Exception|Failed|error CS/.test(l))
|
.filter((l) => /RunicNPC|RunicNpcTest/.test(l) && /\[Error\]|Exception|Failed|error CS/.test(l))
|
||||||
.slice(-40)
|
.slice(-40)
|
||||||
|
|||||||
Reference in New Issue
Block a user