https://linen.dev logo
任意のレールから「長さ」と「ID」を取得しよう。ついでに隣り合うレールエンティティのデータを取得しよ...
# forum
u
【⓪:まえがき】 当方、デジタルATCの開発をしています。列車の加速度を閾値として、擬似パターンを作成し、ブレーキ動作を行う事を目的として、開発を継続しています。 その過程で、「前方にあるレール」の距離を連続的に取得し、「制限区間」までの「残り長さ」を取得したいと考えました。 この仕組みを実現するには (❶:あらかじめレール情報を登録したデータベースにアクセスする仕組みを作る(車上主体) (❷:レール側に「各軌道回路に対する制限情報」を送信する装置を設け、これを軌道回路の数ぶん用意して列車に送る(地上主体) (❸:前方に開通しているレールの長さを順に検索して、車上に送り返す(車上主体) などの仕組みが考えられます。 本ギモンは上記のうち、❸ に該当する、「開通している線路から連続データを取得し、レールの長さを取得してパターン生成の参考とする」ような制御を実現したい、と考えました。 ーーーーーーーーーーーーーーーーーーーー 【①:到達目標】 取得したいデータがいくつかあります。 ・任意のレールの長さ ・任意のレールの「隣のレール」の長さ ・任意のレールの「 ID(一意な符号)」 ・任意のレールの「隣のレール」の ID IDのデータ型は数値かstringが良い このように、任意のレールに対して長さとIDのデータを取得でき、隣のレールからもデータが取得できると望ましいなと考えます。 何故なら「RTMのワールドはレールの状態が頻繁に変化する」ので、「レールの状態変化に対し、車上の距離検索と計算で対応したい」と考えている為です。 後述しますが、レールデータは設備更新毎に仮想化すると検索しやすい為、ワールドにあるレール全てから「長さ」と「ID」のデータを抜き出して仮想化し、「検索しやすい場所」に保存し、「列車から情報をリクエストし、【検索しやすい場所】からデータを取得する」仕組みを考えています。 ーーーーーーーーーーーーーーーーーーーー 【②:現状】 当初は、車上データベースを使わない代わりとして 「車上の速度基準の【停止までの距離】を閾値とし、この最大距離に該当する軌道回路を都度全て検索する」事で 「最も近くの軌道回路から順に「停止(制限)点」を検索し定義して、停車(減速)パターンを作成する」ような制御を目論んでいます。 大まかには、車上で「停止距離」を演算してから、地上に指定距離までの軌道回路を検索させ、レールの距離や接続を取得し、少なくとも「減速が終了する軌道回路」までの距離を、列車へ送り返したいと考えています。 この方式には、いくつかの障害があります。 ・「全てのレールチャンクがアクティブである」か、「レールの情報があらかじめ仮想化され、データとして検索・更新ができる」ような仕組みが無ければならない ・前方に開通している軌道の状態が複雑になると、検索データ量が増え演算が困難になり、列車走行に悪影響を及ぼす ・検索に伴うアルゴリズムの作成が難しそうで、連続的なレールデータの取得を仮想的に行う為のMODやメソッドは今のところなく、既存データをワールド内に保存し、検索する必要がある。 等々、この方式は実現性に乏しいと考えています。 このような「車上主体の距離検索方式」を避けるには、少なくとも車上データベースを定義するか パターン生成地点を「地上子」基準のようにした、いわゆる既存のATSのような「最悪の車両に合わせた保安装置の採用」が必要となってしまいます。 実際の鉄道運行における「デジタルATC」の仕組みでは、エアセクションや分岐器制限等の情報の編集や変更、参照を容易とするべく、列車に「車上データベース」を搭載し、これを参照して「減速までの距離」を導き出して、パターンを生成しています。 ーーーーーーーーーーーーーーーーーーーー 【③:対策】 【②:現状】にあるように、車上から軌道回路の情報を検索するのは、あまり現実的と言えません。 計算量が多く煩雑で、現状のMinecraft環境にそぐわないからです(特に1.7.10のような、チャンクが凍結される環境下では) しかし、地上主体で軌道回路の情報を検索、計算すると、設備更新の際に都度内容を更新する必要があり、非効率と考えます。 そこで、「距離の計算は地上が行い、距離を列車へ送信し、ブレーキ動作は列車で行う」ように、地上と車上の計算を分担する事で、軽量かつ確実に、かつ応用の効くデジタルATCが開発可能」と考えます。 その為には、レールに一意のデータが割り振られ、レール間で検索が可能で、隣り合うデータを参照でき、向きが把握でき、なおかつ送受信が可能な構造が必要です。 これら「レール間のデータ共有」を実現する為、【①:到達目標】を実現したいと考えます。
色々書きすぎた、①と③だけ見て♡
h
Copy code
js
//###  レールの取得  ###

//--リストから取得する--
//リストをぶん回すため比較的処理コストが高い
//走査を実行する車両数x存在するTileEntityの数だけ重たくなる
//有効チャンク内すべてのレールを調べられる
importPackage(Packages.jp.ngt.rtm.rail);//TileEntityLargeRailCore
︙

var world = entity.field_70170_p;         // entity.worldObj
var tileEntityList = world.field_147482_g // world.loadedTileEntityList  返り値は配列ではなくList型
for (var i = 0; i < tileEntityList.size(); i++) {
    var tile = tileEntityList.get(i);
    if (tile instanceof TileEntityLargeRailCore) {
        //このブロック内のtileはレールコアのTileEntity
        //処理
    }
}

//--座標から取得する--
//座標がわかっているならこちらの方が良い
//凍結チャンクのレールを取得できるかは調べてない
importPackage(Packages.jp.ngt.rtm.rail);//TileEntityLargeRailCore
︙

var world = entity.field_70170_p; // entity.worldObj
var railTile = TileEntityLargeRailBase.getRailFromCoordinates(world, x, y, z);
if (railTile) {
    var tile = railTile.getRailCore();
    //処理
}

//--車両Entityから直下のレールタイルを取得する--
importPackage(Packages.jp.ngt.rtm.rail);//TileEntityLargeRailBase
︙

var world = entity.field_70170_p; // entity.worldObj
var x = entity.field_70165_t;     // entity.posX
var y = entity.field_70163_u;     // entity.posY
var z = entity.field_70161_v;     // entity.posZ
var railTile = TileEntityLargeRailBase.getRailFromCoordinates(world, x, y, z);
if (railTile) {
    var tile = railTile.getRailCore();
    //処理
}
Copy code
js
//※ ここ以降はtileがTileEntityLargeRailCoreである前提で記述します ※


//###  隣のレールを取得する  ###
//レールは0~4つの隣接するレールを持ちます  個数が可変のため、例では配列を使用しています
//分岐による隣接の無限ループにならないような対策が別途必要です(追跡深さを制限するなど)
importPackage(Packages.jp.ngt.rtm.rail);//TileEntityLargeRailSwitchCore TileEntityLargeRailBase
importPackage(Packages.jp.ngt.rtm.rail.util);//RailPosition
︙

var connectedRails = [];
if (tile instanceof TileEntityLargeRailSwitchCore) {//分岐レールの場合
    var railSwitch = tile.getSwitch();
    if (railSwitch) {
        var pointList = railSwitch.getPoints();//分岐は3つ/4つの根本を持つ
        for (var i = 0; i < pointList.length; i++) {
            var rp = pointList[i].rpRoot;
            connectedRails.push(getConnectedRailTile(rp));
        }
    }
}
else {//通常レールの場合
    var railMap = tile.getRailMap(entity);
    var rp0 = railMap.getStartRP();
    var rp1 = railMap.getEndRP();
    connectedRails.push(getConnectedRailTile(rp0));
    connectedRails.push(getConnectedRailTile(rp1));
}
connectedRails = connectedRails.filter(function (connectedRail) {
    return connectedRail !== tile && connectedRail !== null;
});

︙
function getConnectedRailTile(rp) {
    var x = Math.floor(rp.blockX + 0.5 + RailPosition.REVISION[rp.direction][0] * 2);
    var y = rp.blockY;
    var z = Math.floor(rp.blockZ + 0.5 + RailPosition.REVISION[rp.direction][1] * 2);
    var tile = world.func_147438_o(x, y, z);
    if (tile instanceof TileEntityLargeRailBase) return tile.getRailCore();
    return null;
}


//###  レールの長さを取得する  ###
//分岐に対する挙動は調べてません おそらく車両entityに対して有効なRailMapの長さになると思います
var railMap = tile.getRailMap(entity);
var railLength = railMap.getLength();


//###  IDを取得  ###
//TileEntityは一意の識別子を持ちません 代わりに座標を連結して文字列にします
var x = tile.field_145851_c; // tile.xCoord
var y = tile.field_145848_d; // tile.yCoord
var z = tile.field_145849_e; // tile.zCoord
var id = x + "_" + y + "_" + z;
もしコードをTileEntityのスクリプトから実行する場合、worldの取得は以下のように書き換える必要があります。(照明モデルなど)
Copy code
js
var world = entity.func_145831_w(); // entity.getWorld()
u
めっちゃ参考になる!! レール座標をID代わりに生成するのめちゃくちゃ良いな
しかもコードまで載せてくれてめちゃくちゃたすかる ありがとうございます🙏
3 Views