Guest User

Untitled

a guest
Aug 21st, 2014
361
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.41 KB | None | 0 0
  1. // Conductor.tjs - KAG シナリオ進行処理
  2. // Copyright (C)2001-2005, W.Dee and contributors 改変・配布は自由です
  3.  
  4.  
  5. class ConductorException extends Exception
  6. {
  7. // ConductorException - Conductor がタグハンドラを処理中に発生した例外を
  8. // 投げる時に使われる例外クラス
  9. function ConductorException() { super.Exception(...); }
  10. function finalize() { super.finalize(...); }
  11. };
  12.  
  13. class BaseConductor extends KAGParser
  14. {
  15. // BaseConductor - シナリオ進行処理のベースクラス
  16. var timer;
  17. var oneshot;
  18. var _interrupted = false; // 中断中か
  19. var timerEnabled = false; // タイマが起動中か
  20. var pendings; // 後回しにされたタグ
  21. var inProcessing = false; // timerCallback を処理中かどうか
  22. var reentered = false; // timerCallback 中に 再入したか
  23. var nextTimerTick = 0; // 次にタイマーが発動されるはずの tick
  24.  
  25. function BaseConductor()
  26. {
  27. // コンストラクタ
  28. super.KAGParser(...);
  29.  
  30. timer = new Timer(timerCallback, '');
  31. // Timerの第二引数に空文字列を指定すると
  32. // 第1引数に指定した関数を直接呼び出すようになる
  33. oneshot = new AsyncTrigger(timerCallback, '');
  34. // これも同様
  35. oneshot.cached = true; // イベントのキャッシュを有効に
  36.  
  37. pendings = [];
  38. }
  39.  
  40. function finalize()
  41. {
  42. // finalize()
  43. invalidate timer;
  44. invalidate oneshot;
  45. super.finalize(...);
  46. }
  47.  
  48. function clear()
  49. {
  50. // clear オーバーライド
  51. pendings.clear();
  52. super.clear();
  53. }
  54.  
  55. function timerCallback()
  56. {
  57. // 次の要素を得る
  58. nextTimerTick = timer.interval + System.getTickCount();
  59. var obj;
  60. try
  61. {
  62. if(inProcessing)
  63. {
  64. // 再入
  65. reentered = true;
  66. timer.interval = 0;
  67. return;
  68. }
  69. inProcessing = true;
  70. for(;;)
  71. {
  72. if(pendings.count > 0)
  73. {
  74. // 後回しにされたタグがある場合
  75. obj = pendings[0];
  76. pendings.erase(0);
  77. }
  78. else
  79. {
  80. // 後回しにされたタグがないので次のタグを得る
  81. obj = getNextTag(); // 次のタグを得る
  82.  
  83. // getNextTag() の中で、pendings に追加された (iscript など)
  84. if(pendings.count > 0)
  85. {
  86. pendings.add(obj);
  87. continue;
  88. }
  89. }
  90.  
  91. if(obj === void)
  92. {
  93. // シナリオ終了
  94. timer.enabled = false;
  95. timerEnabled =false;
  96. onStop();
  97. inProcessing = false;
  98. reentered = false;
  99. return;
  100. }
  101. else
  102. {
  103. // onTag を呼ぶ
  104. var step = onTag(obj);
  105. if(step === void)
  106. throw new Exception("onTag が void を返しました (" + obj.tagname + ")"
  107. "( おそらくタグハンドラの戻り値を返し忘れた )");
  108. step = int step; // step を数値に
  109. if(step == 0)
  110. {
  111. // ウェイトを掛けずに次へ
  112. timer.interval = 0;
  113. continue;
  114. }
  115. else if(step < 0)
  116. {
  117. switch(step)
  118. {
  119. case -5: // いったんイベントを処理(現在のタグは後回し)
  120. pendings.insert(0, obj);
  121. oneshot.mode = atmAtIdle;
  122. oneshot.trigger(); // トリガ
  123. timer.interval = 0; // タイマは停止
  124. inProcessing = false;
  125. reentered = false;
  126. return;
  127. case -4: // いったんイベントを処理
  128. oneshot.mode = atmAtIdle;
  129. oneshot.trigger(); // トリガ
  130. timer.interval = 0; // タイマは停止
  131. inProcessing = false;
  132. reentered = false;
  133. return;
  134. case -3: // 後回ししてブレーク
  135. pendings.insert(0, obj);
  136. timer.interval = 0; // タイマは停止
  137. inProcessing = false;
  138. reentered = false;
  139. return;
  140. case -2: // ブレーク
  141. timer.interval = 0; // タイマは停止
  142. inProcessing = false;
  143. reentered = false;
  144. return;
  145. case -1: // シナリオ終了
  146. timer.interval = 0;
  147. timer.enabled = false;
  148. timerEnabled = false;
  149. onStop();
  150. inProcessing = false;
  151. reentered = false;
  152. return;
  153. }
  154. }
  155. else
  156. {
  157. // 次へ
  158. if(timer.interval != step)
  159. {
  160. timer.interval = step;
  161. nextTimerTick = step + System.getTickCount();
  162. }
  163. inProcessing = false;
  164. reentered = false;
  165. return;
  166. }
  167. }
  168. }
  169. inProcessing = false;
  170. reentered = false;
  171. }
  172. catch(e)
  173. {
  174. // Debug.logAsError();
  175. timer.enabled = false;
  176. timerEnabled =false;
  177. onStop();
  178. inProcessing = false;
  179. var msg = "エラーが発生しました\n"
  180. "ファイル : " + curStorage + " 行 : " + (curLine+1) + "\n"
  181. "タグ : " + (obj === void ? "不明" : obj.tagname)
  182. + " ( ← エラーの発生した前後のタグを示している場合もあります )\n"
  183. + e.message;
  184. if((typeof e.trace) != "undefined") dm("trace : " + e.trace);
  185. dm(msg);
  186. throw new ConductorException(msg);
  187. // System.inform(msg, "エラー");
  188. }
  189. }
  190.  
  191. function onTag()
  192. {
  193. // オーバーライドすること
  194. return -1;
  195. }
  196.  
  197. function onStop()
  198. {
  199. // (シナリオの)停止時に呼ばれる。
  200. // stop() から呼ばれるわけではない。
  201. // オーバーライドすること。
  202. }
  203.  
  204. function startProcess(immediate = false)
  205. {
  206. // シナリオ進行開始
  207. // immediate = false の場合は非同期で実行を開始するので、
  208. // このメソッド内でタグハンドラが呼ばれることはない
  209. // 次のイベント配信のタイミングで最初のタグハンドラが呼ばれる。
  210. // immediate = true の場合は、このメソッド内で初回のタグハンドラが
  211. // 処理されるため、呼び出し側はこのメソッドの実行が終わったら
  212. // すぐに吉里吉里に制御を戻す(すべての関数から抜ける)ようにするべき。
  213. resetInterrupt();
  214. timer.interval = 0; // 初期インターバル
  215. timerEnabled = true;
  216. if(!_interrupted)
  217. {
  218. timer.enabled = true; // タイマー開始
  219. if(immediate)
  220. {
  221. timerCallback();
  222. }
  223. else
  224. {
  225. oneshot.mode = atmExclusive;
  226. // イベントが配信されるまで他の非同期イベントをブロック
  227. oneshot.trigger(); // トリガ
  228. }
  229. }
  230. }
  231.  
  232. function start()
  233. {
  234. // タイマ開始
  235. timerEnabled = true;
  236. timer.enabled = true;
  237. }
  238.  
  239. function stop()
  240. {
  241. // タイマ停止
  242. timer.enabled = false;
  243. timerEnabled = false;
  244. }
  245.  
  246. property interrupted
  247. {
  248. getter() { return _interrupted; }
  249. setter(x)
  250. {
  251. if(!x)
  252. {
  253. // enable
  254. if(timerEnabled)
  255. {
  256. timer.interval = 0;
  257. timer.enabled = true;
  258. oneshot.mode = atmExclusive;
  259. // イベントが配信されるまで他の非同期イベントをブロック
  260. oneshot.trigger(); // トリガ
  261. }
  262. }
  263. else
  264. {
  265. // disable
  266. oneshot.cancel();
  267. timer.enabled = false;
  268. }
  269. _interrupted = x;
  270. }
  271. }
  272.  
  273. function assign(src)
  274. {
  275. // src の状態をこのオブジェクトにコピー
  276. var t = timer;
  277. var st = src.timer;
  278. t.enabled = false;
  279. t.interval = st.interval;
  280. nextTimerTick = src.nextTimerTick;
  281. if(st.enabled && st.interval != 0)
  282. {
  283. // タイマ interval の調整
  284. var delta = nextTimerTick - System.getTickCount();
  285. if(delta > 0) t.interval = delta; else t.interval = 1;
  286. }
  287. t.enabled = st.enabled;
  288. timerEnabled = src.timerEnabled;
  289. _interrupted = src._interrupted;
  290. if(src.pendings.count > 0)
  291. pendings.assignStruct(src.pendings);
  292. else
  293. pendings.clear();
  294. super.assign(src);
  295. }
  296.  
  297. function store()
  298. {
  299. // store オーバーライド
  300. return super.store(...);
  301. }
  302.  
  303. function restore(dic)
  304. {
  305. // restore オーバーライド
  306. super.restore(...);
  307. pendings.clear();
  308. }
  309.  
  310. function loadScenario(file)
  311. {
  312. // loadScenario オーバーライド
  313. pendings.clear();
  314. dm("loadScenario: "+file);
  315. super.loadScenario(...);
  316. }
  317.  
  318. function goToLabel()
  319. {
  320. // goToLabel オーバーライド
  321. pendings.clear();
  322. super.goToLabel(...);
  323. }
  324.  
  325. function enqueueTag(tag)
  326. {
  327. pendings.add(tag);
  328. }
  329. }
  330.  
  331.  
  332. class Conductor extends BaseConductor
  333. {
  334. // Conductor - シナリオ進行処理
  335. /*const*/ var mStop = 0; // 停止
  336. /*const*/ var mRun = 1; // 動作中
  337. /*const*/ var mWait = 2; // 待ち
  338.  
  339. var owner;
  340. var handlers;
  341. var status = mStop;
  342. var timeOutTimer;
  343. var waitUntil = %[];
  344. var lastTagName = ''; // 直前のタグ名
  345.  
  346. function Conductor(owner, handlers)
  347. {
  348. // コンストラクタ
  349. super.BaseConductor();
  350. ignoreCR = global.ignoreCR;
  351. debugLevel = tkdlVerbose;
  352. this.owner = owner;
  353. this.handlers = handlers;
  354. timeOutTimer = new Timer(onTimeOut, '');
  355. }
  356.  
  357. function finalize()
  358. {
  359. // finalize()
  360. invalidate timeOutTimer;
  361. super.finalize(...);
  362. }
  363.  
  364. function run(immediate = false)
  365. {
  366. // 実行の開始
  367. // immediate=true の場合は、
  368. // このメソッドを実行したらすぐに吉里吉里に制御を戻す
  369. // (すべての関数から戻る)こと
  370. status = mRun;
  371. startProcess(immediate);
  372. }
  373.  
  374. function sleep()
  375. {
  376. // 実行の停止
  377. status = mStop;
  378. stop();
  379. }
  380.  
  381. function wait(until)
  382. {
  383. // 待ち
  384. // until = trigger で用いるシグナル名とコールバック関数の
  385. // 辞書配列
  386. status = mWait;
  387. stop();
  388. (Dictionary.assign incontextof waitUntil)(until);
  389. }
  390.  
  391. function waitWithTimeOut(until, timeout)
  392. {
  393. // 待ちを行うが、タイムアウトがある
  394. // タイムアウト時には 'timeout' がトリガされるので
  395. // ハンドラを定義すること。
  396. if(timeout == 0) timeout = 1; // timeout が 0 の場合は 1 に
  397. status = mWait;
  398. stop();
  399. (Dictionary.assign incontextof waitUntil)(until);
  400. timeOutTimer.interval = timeout;
  401. timeOutTimer.enabled = true;
  402. }
  403.  
  404. function onTimeOut()
  405. {
  406. // timeOutTimer がタイムアウトした
  407. timeOutTimer.enabled = false;
  408. trigger('timeout'); // 自分自身で timeout をトリガする
  409. }
  410.  
  411. function trigger(name)
  412. {
  413. // waitUntil 内にシグナル名 name が存在すれば、実行再開、
  414. // 同時に waitUntil に登録されたメソッド(リスタートハンドラ)を呼ぶ
  415. // シグナル名に _arg がついたものが waitUntil 内にあれば、
  416. // それを引数としてハンドラに渡す
  417. // waitUntil はクリアされる
  418. if(status != mWait) return false;
  419. var func = waitUntil[name];
  420. if(func !== void)
  421. {
  422. var arg = waitUntil[name + '_arg'];
  423. if(arg !== void) func(arg); else func();
  424. (Dictionary.clear incontextof waitUntil)();
  425. run();
  426. return true;
  427. }
  428. else
  429. {
  430. return false;
  431. }
  432. }
  433.  
  434. function onTag(elm)
  435. {
  436. // タグの処理
  437. var tagname = elm.tagname;
  438. var handler = handlers[tagname];
  439. if(handler !== void)
  440. {
  441. var ret = handler(elm);
  442. lastTagName = tagname;
  443. return ret;
  444. }
  445. return onUnknownTag(tagname, elm);
  446. }
  447.  
  448. function onStop()
  449. {
  450. // BaseConductor.onStop オーバーライド
  451. // 停止時に呼ばれるのでステータスを mStop にする
  452. status = mStop;
  453. if(owner.conductor == this) handlers.s(); // ハンドラの s (停止) を呼ぶ
  454. }
  455.  
  456. function onScript(script, scriptname, lineofs)
  457. {
  458. // scirpt を実行する
  459. try
  460. {
  461. Scripts.exec(script, scriptname, lineofs);
  462. }
  463. catch(e)
  464. {
  465. throw new Exception(scriptname + " の 行 " + lineofs + " から始まる"
  466. " iscript ブロックでエラーが発生しました。"
  467. "\n( 詳細はコンソールを参照してください )\n" + e.message);
  468. }
  469. return true;
  470. }
  471.  
  472. function store()
  473. {
  474. // store オーバーライド
  475. return super.store(...);
  476. }
  477.  
  478. function restore(dic)
  479. {
  480. // restore オーバーライド
  481. super.restore(...);
  482. lastTagName = '';
  483. }
  484.  
  485. function onScenarioLoad()
  486. {
  487. return owner.onConductorScenarioLoad(...);
  488. }
  489.  
  490. function onScenarioLoaded()
  491. {
  492. return owner.onConductorScenarioLoaded(...);
  493. }
  494.  
  495. function onLabel()
  496. {
  497. return owner.onConductorLabel(...);
  498. }
  499.  
  500. function onJump()
  501. {
  502. return owner.onConductorJump(...);
  503. }
  504.  
  505. function onCall()
  506. {
  507. return owner.onConductorCall(...);
  508. }
  509.  
  510. function onReturn()
  511. {
  512. return owner.onConductorReturn(...);
  513. }
  514.  
  515. function onAfterReturn()
  516. {
  517. return owner.onConductorAfterReturn(...);
  518. }
  519.  
  520. function onScript()
  521. {
  522. return owner.onConductorScript(...);
  523. }
  524.  
  525. function onUnknownTag()
  526. {
  527. return owner.onConductorUnknownTag(...);
  528. }
  529.  
  530. }
Advertisement
Add Comment
Please, Sign In to add comment