Implement primary judge result passing.

This commit is contained in:
2023-06-02 18:17:10 +08:00
parent 59b4f14fb3
commit d5ba09cbea

View File

@@ -8,9 +8,14 @@ using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using System.Text.Formatting;
using UnityEngine;
using UnsafeIL;
namespace Cryville.Crtr {
internal struct JudgeResult {
public float? Time { get; set; }
public Vector4 Vector { get; set; }
}
internal struct JudgeEvent {
public double StartTime { get; set; }
public double EndTime { get; set; }
@@ -19,6 +24,7 @@ namespace Cryville.Crtr {
public Chart.Judge BaseEvent { get; set; }
public JudgeDefinition Definition { get; set; }
public NoteHandler Handler { get; set; }
public JudgeResult JudgeResult { get; set; }
}
internal interface IJudge {
bool Pass(JudgeEvent ev, float time, Identifier[] ids, int depth);
@@ -52,6 +58,8 @@ namespace Cryville.Crtr {
_numsrc2 = new PropSrc.Float(() => _numbuf2);
_numsrc3 = new PropSrc.Float(() => _numbuf3);
_numsrc4 = new PropSrc.Float(() => _numbuf4);
_jnumsrc = new PropSrc.Float(() => _jnumbuf);
_jvecsrc = new PropSrc.Vector4(() => _jvecbuf);
_identop = new PropOp.Identifier(v => _identbuf = new Identifier(v));
_clipop = new PropOp.Clip(v => _clipbuf = v);
_rs.judges.TryGetValue(new Identifier(_var_pause), out _judgePause);
@@ -113,23 +121,40 @@ namespace Cryville.Crtr {
readonly float[] _buf = new float[MAX_SORTS];
readonly float[] _sorts = new float[MAX_SORTS];
public bool LastHit { get; private set; }
public JudgeResult JudgeResult { get; private set; }
public HitOp() : base(MAX_SORTS) { }
protected override unsafe void Execute() {
LastHit = false;
var judgeResult = new JudgeResult();
var judgeVector = new Vector4();
for (int i = 0; i < LoadedOperandCount; i++) {
var sort = GetOperand(i).AsNumber();
var op = GetOperand(i);
var sort = op.AsNumber();
if (sort <= 0) return;
if (!LastHit && sort < _sorts[i]) return;
if (sort > _sorts[i]) LastHit = true;
if (!LastHit) {
if (sort < _sorts[i]) return;
if (sort > _sorts[i]) LastHit = true;
}
_buf[i] = sort;
if (op.Type == PdtInternalType.Vector) {
var len = (op.Length - sizeof(int)) / sizeof(float);
if (len > 1) {
judgeResult.Time = op.AsNumber(sizeof(float));
for (int j = 0; j < 4; j++) {
if (len > j + 2) judgeVector[j] = op.AsNumber((j + 2) * sizeof(float));
}
judgeResult.Vector = judgeVector;
}
}
}
if (!LastHit) return;
Array.Clear(_buf, LoadedOperandCount, MAX_SORTS - LoadedOperandCount);
fixed (float* ptrsrc = _buf, ptrdest = _sorts) {
Unsafe.CopyBlock(ptrdest, ptrsrc, MAX_SORTS * sizeof(float));
}
JudgeResult = judgeResult;
}
public void Clear() { Array.Clear(_sorts, 0, MAX_SORTS); }
@@ -140,6 +165,12 @@ namespace Cryville.Crtr {
static readonly int _var_tt = IdentifierManager.Shared.Request("input_time_to");
float _numbuf1, _numbuf2, _numbuf3, _numbuf4;
readonly PropSrc _numsrc1, _numsrc2, _numsrc3, _numsrc4;
static readonly int _var_jt = IdentifierManager.Shared.Request("judge_time");
static readonly int _var_jv = IdentifierManager.Shared.Request("judge_vec");
float _jnumbuf; Vector4 _jvecbuf;
readonly PropSrc _jnumsrc, _jvecsrc;
unsafe void LoadNum(byte[] buffer, float value) {
fixed (byte* ptr = buffer) *(float*)ptr = value;
}
@@ -191,7 +222,10 @@ namespace Cryville.Crtr {
var def = ev.Definition;
if (def.hit != null) {
_etor.Evaluate(_hitop, def.hit);
if (_hitop.LastHit) hitIndex = index;
if (_hitop.LastHit) {
hitIndex = index;
ev.JudgeResult = _hitop.JudgeResult;
}
}
else if (hitIndex == -1) hitIndex = index;
index++;
@@ -242,6 +276,10 @@ namespace Cryville.Crtr {
}
}
void Execute(JudgeEvent ev, float time, PairList<JudgeAction, PdtExpression> actions, int depth = 0) {
if (ev.JudgeResult.Time != null) {
_jnumbuf = ev.JudgeResult.Time.Value; _jnumsrc.Invalidate(); _etor.ContextCascadeUpdate(_var_jt, _jnumsrc);
_jvecbuf = ev.JudgeResult.Vector; _jvecsrc.Invalidate(); _etor.ContextCascadeUpdate(_var_jv, _jvecsrc);
}
foreach (var a in actions) {
if (a.Key.Execute(this, ev, time, a.Value, depth)) break;
}
@@ -250,10 +288,15 @@ namespace Cryville.Crtr {
if (depth >= 16) throw new JudgePropagationException();
foreach (var i in ids) {
var def = _rs.judges[i];
if (def.hit != null) _etor.Evaluate(_flagop, def.hit);
else _flag = true;
if (_flag) {
if (def.on_hit != null) Execute(ev, time, def.on_hit, depth + 1);
bool hitFlag;
if (def.hit != null) {
_hitop.Clear();
_etor.Evaluate(_hitop, def.hit);
hitFlag = _hitop.LastHit;
}
else hitFlag = true;
if (hitFlag) {
Execute(ev, time, def.on_hit, depth + 1);
ev.Handler.ReportJudge(ev, time, i);
return true;
}