タートルだけで、工業化! Part03 を投稿しました。

MOD 一覧などのシリーズ通しての情報はこちらです。

ネタで画像を挟むために、初めて MMD を触りました。 今回の苦労は大体そいつのせい。

今回紹介したコード

shaft

-- make a shaft for mining
-- usage: shaft <Current Y Axis>
--        Ladders must be placed at 14th or lower slot,
--        a watter backet must be placed at 16th slot, and a sign 15th.
--        Blocks at 1st or higher slots are used for wall.

local WATTERBUCKET_SLOT = 16
local SIGN_SLOT = 15
local MINING_HEIGHT = 11


local yAxis = tonumber(...)
local depthCount = 0

function shaftDown()
    selectWallSlot()

    turtle.digDown()
    turtle.down()
    for i = 1, 4 do
        if i ~= 1 then
            turtle.place()
        end
        turtle.turnRight()
        suckAll()
    end
    turtle.dig()
    turtle.forward()
    for i = 1, 4 do
        if i ~= 3 then
            turtle.place()
        end
        turtle.turnRight()
        suckAll()
    end
    turtle.back()

    selectLadderSlot()
    turtle.place()
    suckAll()

    depthCount = depthCount + 1
end

function selectWallSlot()
    for i = 1, 14 do
        if 0 < turtle.getItemCount(i) then
            turtle.select(i)
            return
        end
    end
end

function selectLadderSlot()
    for i = 14, 1, -1 do
        if 0 < turtle.getItemCount(i) then
            turtle.select(i)
            return
        end
    end
end

function suckAll()
    turtle.suck()
    turtle.suckUp()
    turtle.suckDown()
end

function waterCushion()
    turtle.up()
    turtle.dig()
    turtle.forward()
    turtle.turnRight()
    turtle.turnRight()
    turtle.select(SIGN_SLOT)
    turtle.place("")
    selectLadderSlot()
    turtle.digUp()
    turtle.up()
    turtle.placeDown()
    turtle.digUp()
    turtle.up()
    turtle.placeDown()
    turtle.select(WATTERBUCKET_SLOT)
    turtle.place()
    turtle.digUp()
    turtle.up()
    selectLadderSlot()
    turtle.placeDown()
    turtle.forward()
    turtle.turnRight()
    turtle.turnRight()
    turtle.place()

    depthCount = depthCount - 4
end

function comeBack()
    for i = 1, depthCount do
        turtle.up()
    end
end


for i = yAxis, MINING_HEIGHT + 1, -1 do
    shaftDown()
end
waterCushion()
comeBack()

mining

local SLOT_GLASS = 14
local SLOT_TORCH = 15
local SLOT_FUEL = 16

local lightLevel = 8


function isValid()
    if turtle.getItemCount(SLOT_GLASS) <= 1
        or turtle.getItemCount(SLOT_TORCH) <= 1
        or turtle.getItemCount(SLOT_FUEL) <= 1 then
        return false
    end
    for i = 1, 16 do
        if turtle.getItemCount(i) == 0 then
            return true
        end
    end
    return false
end


function refuel()
    if turtle.getFuelLevel() < 10 then
        turtle.select(SLOT_FUEL)
        turtle.refuel(1)
    end
end

function onestep()
    local function fillSide()
        turtle.select(SLOT_GLASS)
        turtle.turnRight()
        turtle.place()
        turtle.turnLeft()
        turtle.turnLeft()
        turtle.place()
        turtle.turnRight()
    end

    turtle.up()
    fillSide()
    turtle.placeUp()
    turtle.dig()
    turtle.down()
    fillSide()
    turtle.placeDown()
    repeat
        turtle.dig()
    until turtle.forward()
    lightLevel = lightLevel - 1
end

function suckAll()
    turtle.suck()
    turtle.suckUp()
    turtle.suckDown()
end

function torch()
    if lightLevel < 8 then
        turtle.turnRight()
        turtle.turnRight()
        turtle.select(SLOT_TORCH)
        if turtle.place() then
            lightLevel = 13
        end
        turtle.turnRight()
        turtle.turnRight()
    end
end


while isValid() do
    refuel()
    onestep()
    suckAll()
    torch()
end

タートルだけで、工業化! Part02 を投稿しました。

MOD 一覧などのシリーズ通しての情報はこちらです。

金曜日夜に投稿する予定を立てていたのですが、Part01 のコメントなどを見て、思わず舞い上がって気合入れすぎました。

今回紹介したコード

tofu

-- cube house building program
-- usage: tofu <witdh> <depth> <height>

function selectNonEmptySlot()
    for i = 1, 16 do
        if 0 < turtle.getItemCount(i) then
            turtle.select(i)
        end
    end
end

function floor(width, depth)
    -- build floor
    for w = 1, width do
        for d = 1, depth do
            selectNonEmptySlot()
            turtle.placeDown()
            if d < depth then
                turtle.forward()
            else
                if w % 2 == 1 then
                    turtle.turnRight()
                    turtle.forward()
                    turtle.turnRight()
                else
                    turtle.turnLeft()
                    turtle.forward()
                    turtle.turnLeft()
                end
            end
        end
    end
    -- come back
    if width % 2 == 0 then
        turtle.turnLeft()
    else
        for i = 1, depth - 1 do
            turtle.forward()
        end
        turtle.turnRight()
    end
    for i = 1, width do
        turtle.forward()
    end
    turtle.turnRight()
end

function rectangle(width, depth)
    for i = 1, depth - 1 do
        selectNonEmptySlot()
        turtle.placeDown()
        turtle.forward()
    end
    turtle.turnRight()
    for i = 1, width - 1 do
        selectNonEmptySlot()
        turtle.placeDown()
        turtle.forward()
    end
    turtle.turnRight()
    for i = 1, depth - 1 do
        selectNonEmptySlot()
        turtle.placeDown()
        turtle.forward()
    end
    turtle.turnRight()
    for i = 1, width - 1 do
        selectNonEmptySlot()
        turtle.placeDown()
        turtle.forward()
    end
    turtle.turnRight()
end


local args = { ... }
local tofuWidth = tonumber(args[1])
local tofuDepth = tonumber(args[2])
local tofuHeight = tonumber(args[3])

turtle.up()
turtle.forward()
floor(tofuWidth, tofuDepth)
for h = 1, tofuHeight - 2 do
    turtle.up()
    rectangle(tofuWidth, tofuDepth)
end
turtle.up()
floor(tofuWidth, tofuDepth)

matrix

length = 10


termWidth, termHeight = term.getSize()

function getRandomChar()
    local r = math.random(33, 126)
    return string.char(r)
end

function generateChars()
    local chars = {}
    for i = 1, termWidth*termHeight do
        chars[i] = getRandomChar()
    end
    return chars
end

function showAt(col, row)
    if 1 <= row and row <= termHeight then
        term.setCursorPos(col, row)
        write(random_chars[(row-1)*termWidth + col])
    end
end

function generate()
    for col = 1, termWidth do
        if math.random() < 0.05 then
            table.insert(lines, { col=col, row=0 })
        end
    end
end

function update()
    for k, v in pairs(lines) do
        v["row"] = v["row"] + 1
        if v["row"] - length >= termHeight then
            table.remove(lines, k)
        end
    end
end

function show()
    for k, v in pairs(lines) do
        for i = 1, length do
            showAt(v["col"], v["row"] - length + i)
        end
    end
end


random_chars = generateChars()
lines = {}
while true do
    term.clear()
    generate()
    update()
    show()
    sleep(0.1)
end

デストップキャプチャの負荷軽減

Part01 のフレームレートが低いのが気になってたので、何とかするべきですよね。

まずはどこがボトルネックになっているか調査。 まあ、予想通り CPU でした。うちのデスクトップにはグラフィックボード積んでいませんので。 付加的には Minecraft 50%, キャプチャソフト 50% というところでしょうか。

コーデックの見直しをします。 Part01 録画時に使っていたのは Ut Video Codec Suite です。 色々と気にして探したので、今回見なおしてもこれでいいと結論が出ました。

しかしこのコーデック内にも種類があるみたいです。 色空間の話ですね。YUV と RGB 。 何も考えずに YUV を使用してましたが、デスクトップキャプチャだと画面に表示されている RGB の色を YUV に変換する必要があるので、そこに負荷がかかっている気がします。 というわけで種類を変更しました。

次に Minecraft 自体の負荷です。 F3 のプロファイルを見ると、Render 1/2, GameRender 1/4 ぐらい占めてます。 これ、グラボ買ったら一気に fps 上がるでしょうね。 まあそこはお金がかかる問題なので、もう少し慎重に考えて……。

別の PC をサーバーにしてマルチプレイするのはどうかな?とも考えましたが、あまり効果がなさそう。 プロファイル見る限りそんなに負荷の割合が大きくないし、ゲーム中の計算の大半であろう大量のモブ (Mo' Creatures) の計算処理はクライアント側でもやってるでしょうし(多分通信は同期のためだけ)。

後は OptiFine の設定の見直し。 といっても既にいろいろ設定していたのでほとんど変更はありませんでした。

あれこれやっているうちに fps が 5 〜 10 ぐらい上がったと思います。 良かった良かった。

タートルだけで、工業化! Part01 を投稿しました。

MOD 一覧などのシリーズ通しての情報はこちらです。

今回は初投稿ということで、ゆかりさんが暴走気味です。

今回紹介したコード

Clock

while true do
    time = os.time()
    term.clear()
    term.setCursorPos(3,3)
    print(textutils.formatTime(time, true))
    sleep(20/24)
end

-- Minecraft → Real
-- 24 * 60 min → 20 min
-- 1 min → 20/24 = 0.8333... sec

タートルだけで、工業化!シリーズ

ここにシリーズ通しての情報をまとめます。

マイリスト

MOD 一覧

システム系 MOD

  • Minecraft Forge
  • NotEnoughItems
  • OptiFine
  • InventoryTweaks
  • MouseTweaks
  • PlayerAPI
    • SmartMoving
  • Rei's Minimap
  • Damage Indicators
  • ID Checker (Part02 追加)
  • Camera Studio (Part02 追加)

大規模 MOD

  • Tinkers' Construct
  • 竹mod
  • 豆腐craft
    • 蛇口 Faucet
  • ComputerCraft
    • Immibis's Peripherals
    • OpenPeripheral
  • Portal Gun
  • Mo' Creatures
  • Better Dungeons
  • The Twilight Forest
  • Project:RED
  • AtomicStryker's Battle Towers
  • Netherrocks

小規模 MOD

  • MoreInventoryMod
  • AdvancedTools (ID: 3000 → 31000)
  • エンチャント交換 MOD
  • ExTools
  • AccessChest