This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
allquan's profile picture

Minecraft Holodeck

Started by allquan, 07 July 2012 - 07:55 PM
allquan #1
Posted 07 July 2012 - 09:55 PM
Hi i just tested my Alpha Version of my holodeck.

Here a short video of it:

[media]http://www.youtube.com/watch?v=7Ko7ryW6hjw&feature=youtu.be[/media] (Sorry for bad quality! :P/>/> )


I used Computercraft an the operator panel.



Next days i will show you more of it.
bbqroast #2
Posted 07 July 2012 - 10:11 PM
Awesome!
Gotta look up this operator panel thing now. Out of interest, are those blocks solid? Do you collide with them and can you destroy them (and pick up their drops?).
allquan #3
Posted 07 July 2012 - 10:13 PM
Thank you!

Yes thats normal minecraft blocks
LucasUK #4
Posted 14 July 2012 - 05:05 PM
Yeah awesome, did yuo continue the project?
Sxw #5
Posted 15 July 2012 - 05:15 PM
Wow, this could be used in so many ways, like… Simulating a lava enviroment to watch people in there die.
allquan #6
Posted 19 July 2012 - 12:30 PM
Hey guys,

here is a new Video of my new test:

http://www.youtube.com/watch?v=raDAccBWpas&feature=youtu.be
MysticT #7
Posted 19 July 2012 - 03:41 PM
Hey, I really liked the idea, so I made my own version :P/>/>
I'm not sure if I'll keep working on that, so if you want I can give you what I have. I made an api with some functions to make it easier, and it can even build schematic files.
Let me know if you (or anyone else) want it.
allquan #8
Posted 19 July 2012 - 03:49 PM
yes, please that would be great!
MysticT #9
Posted 19 July 2012 - 04:15 PM
Ok, here it is:
NBT api (used to read schematics):
Spoiler

-- NBT API
-- by MysticT

local function readShort(file)
    local r = file.read() * 256 + file.read()
    if r >= 32768 then
        r = r - 65536
    end
    return r
end

local function readInt(file)
    local r = 0
    for i = 1, 4 do
        r = r * 256 + file.read()
    end
    if r >= 2147483648 then
        r = r - 4294967296
    end
    return r
end

local function readLong(file)
    local r = 0
    for i = 1, 8 do
        r = r * 256 + file.read()
    end
    if r >= 9223372036854775808 then
        r = r - 18446744073709551616
    end
    return r
end

local function readFloat(file)
    for i = 1, 4 do
        file.read()
    end
    return 0
end

local function readDouble(file)
    for i = 1, 4 do
        file.read()
    end
    return 0
end

local function readByteArray(file)
    local size = readInt(file)
    local array = {}
    for i = 1, size do
        table.insert(array, file.read())
    end
    return array
end

local function readString(file)
    local len = readShort(file)
    local s = ""
    for i = 1, len do
        local c = file.read()
        if not c then
            break
        end
        s = s..string.char(c)
    end
    return s
end

local function readIntArray(file)
    local size = readInt(file)
    local array = {}
    for i = 1, size do
        table.insert(array, readInt(file))
    end
    return array
end

local function readTags(file)
    local function readPayload(id)
        if id == 1 then
            -- TAG_Byte
            return file.read()
        elseif id == 2 then
            -- TAG_Short
            return readShort(file)
        elseif id == 3 then
            -- TAG_Int
            return readInt(file)
        elseif id == 4 then
            -- TAG_Long
            return readLong(file)
        elseif id == 5 then
            -- TAG_Float
            return readFloat(file)
        elseif id == 6 then
            -- TAG_Double
            return readDouble(file)
        elseif id == 7 then
            -- TAG_Byte_Array
            return readByteArray(file)
        elseif id == 8 then
            -- TAG_String
            return readString(file)
        elseif id == 9 then
            -- TAG_List
            local list = {}
            local id = file.read()
            local size = readInt(file)
            for i = 1, size do
                table.insert(list, readPayload(id))
            end
            return list
        elseif id == 10 then
            -- TAG_Compound
            return readTags(file)
        elseif id == 11 then
            -- TAG_Int_Array
            return readIntArray(file)
        end
    end
    local tags = {}
    while true do
        local tag = {}
        tag.id = file.read()
        if not tag.id then
            break
        end
        if tag.id == 0 then
            -- TAG_End
            tag.name = ""
            break
        elseif tag.id > 11 then
            return nil, "Unknown tag id: "..tostring(tag.id)
        end
        tag.name = readString(file)
        tag.payload = readPayload(tag.id)
        table.insert(tags, tag)
    end
    return tags
end

-- API functions

function readNBTFile(sPath)
    local file = fs.open(sPath, "rb")
    if file then
        local tags, err = readTags(file)
        file.close()
        return tags, err
    end
    return nil, "Error opening file "..sPath
end

Schematic api:
Spoiler

-- Schematic API
-- by MysticT

function load(sPath)
    local tags, err = nbt.readNBTFile(sPath)
    if tags == nil then
        return nil, err
    end
    if tags[1].name ~= "Schematic" then
        return nil, "Not an schematic file"
    end
    return tags[1].payload
end

function getBlocks(schem)
    local blocks, data
    for _,tag in ipairs(schem) do
        if tag.name == "Blocks" then
            blocks = tag.payload
        elseif tag.name == "Data" then
            data = tag.payload
        end
    end
    return blocks, data
end

function getSize(schem)
    local width, height, length
    for _,tag in ipairs(schem) do
        if tag.name == "Width" then
            width = tag.payload
        elseif tag.name == "Height" then
            height = tag.payload
        elseif tag.name == "Length" then
            length = tag.payload
        end
    end
    return width, height, length
end

function getMaterials(schem)
    for _,tag in ipairs(schem) do
        if tag.name == "Materials" then
            return tag.payload
        end
    end
end

VirtualBox api (you can change the name if you want :P/>/>):
Spoiler

-- VirtualBox API
-- by MysticT

local controller
local nX, nY, nZ
local nWidth, nHeight, nLength
local defaultBlock, defaultMeta
local pX, pY, pZ

local function yield()
    os.queueEvent("vb_yield")
    os.pullEvent("vb_yield")
end

function init()
    for _,s in ipairs(rs.getSides()) do
        if peripheral.isPresent(s) and peripheral.getType(s) == "controller" then
            controller = peripheral.wrap(s)
            return true
        end
    end
    return false
end

function setPos(x, y, z)
    nX, nY, nZ = x, y, z
end

function setSize(w, h, l)
    nWidth, nHeight, nLength = w, h, l
end

function setDefaultBlock(id, meta)
    defaultBlock = id
    defaultMeta = meta or 0
end

function getPos()
    return nX, nY, nZ
end

function getSize()
    return nWidth, nHeight, nLength
end

function getDefaultBlock()
    return defaultBlock, defaultMeta
end

-- Blocks

function set(x, y, z, blockID, meta)
    if x < 0 or x >= nWidth or y < 0 or y >= nHeight or z < 0 or z >= nLength then
        return false
    end
    if meta then
        return pcall(controller.placeBlockAtPos, nX + x, nY + y, nZ + z, blockID, meta)
    else
        return pcall(controller.placeBlockAtPos, nX + x, nY + y, nZ + z, blockID)
    end
end

function setChance(chance, x, y, z, blockID, meta)
    if math.random() <= chance then
        set(x, y, z, blockID, meta)
    end
end

function get(x, y, z)
    if x < 0 or x >= nWidth or y < 0 or y >= nHeight or z < 0 or z >= nLength then
        return nil, nil
    end
    return controller.getBlockIDAtPos(nX + x, nY + y, nZ + z), controller.getBlockDataAtPos(nX + x, nY + y, nZ + z)
end

function delete(x, y, z)
    if x < 0 or x >= nWidth or y < 0 or y >= nHeight or z < 0 or z >= nLength then
        return false
    end
    return controller.deleteBlockAtPos(nX + x, nY + y, nZ + z)
end

function isBlock(x, y, z)
    return controller.getBlockIDAtPos(nX + x, nY + y, nZ + z) ~= 0
end

function replace(x, y, z, block, meta)
    if isBlock(x, y, z) then
        delete(x, y, z)
    end
    return set(x, y, z, block, meta)
end

function replaceBlocks(x, y, z, w, h, l, fromId, toId, fromMeta, toMeta)
    for i = 0, w - 1 do
        for j = 0, h - 1 do
            for k = 0, l - 1 do
                local _x, _y, _z = x + i, y + j, z + k
                local id, meta = get(_x, _y, _z)
                if id == fromId and (fromMeta == nil or meta == fromMeta) then
                    replace(_x, _y, _z, toId, toMeta)
                end
            end
        end
    end
end

function clear(x, y, z, w, h, l)
    for i = 0, w - 1 do
        for j = 0, h - 1 do
            for k = 0, l - 1 do
                delete(x + i, y + j, z + k)
            end
        end
    end
end

function column(x, y, z, h, blockID, meta)
    for i = 0, h - 1 do
        set(x, y + i, z, blockID, meta)
    end
end

function wall(x, y, z, w, h, dir, blockID, meta)
    if dir < 1 or dir > 2 then
        return false
    end
    for i = 0, w - 1 do
        for j = 0, h - 1 do
            local _x, _z
            if dir == 1 then
                _x = x + i
                _z = z
            elseif dir == 2 then
                _x = x
                _z = z + i
            end
            set(_x, y + j, _z, blockID, meta)
        end
    end
    return true
end

function floor(x, y, z, w, l, blockID, meta)
    for i = 0, w - 1 do
        for j = 0, l - 1 do
            set(x + i, y, z + j, blockID, meta)
        end
    end
    return true
end

function box(x, y, z, w, h, l, blockID, meta)
    wall(x, y, z, w, h, 1, blockID, meta)
    wall(x, y, z + l - 1, w, h, 1, blockID, meta)
    wall(x, y, z, w, h, 2, blockID, meta)
    wall(x + w - 1, y, z, w, h, 2, blockID, meta)
    floor(x, y, z, w, l, blockID, meta)
    floor(x, y + h - 1, z, w, l, blockID, meta)
    return true
end

function clearAll()
    clear(1, 1, 1, nWidth - 2, nHeight - 2, nLength - 2)
    box(0, 0, 0, nWidth, nHeight, nLength, defaultBlock, defaultMeta)
end

-- Creatures

function spawnCreature(x, y, z, name)
    if x < 0 or x >= nWidth or y < 0 or y >= nHeight or z < 0 or z >= nLength then
        return false
    end
    return controller.spawnCreatureAtPos(nX + x, nY + y, nZ + z, name)
end

-- Items

function spawnItem(x, y, z, itemID, damage, amount)
    if x < 0 or x >= nWidth or y < 0 or y >= nHeight or z < 0 or z >= nLength then
        return false
    end
    if damage and amount then
        return controller.spawnItemAtPos(nX + x, nY + y, nZ + z, itemID, damage, amount)
    elseif damage then
        return controller.spawnItemAtPos(nX + x, nY + y, nZ + z, itemID, damage)
    else
        return controller.spawnItemAtPos(nX + x, nY + y, nZ + z, itemID)
    end
end

-- Player

function isPlayerInside()
    local x, y, z = controller.getPlayerPos()
    x = x - nX
    y = y - nY
    z = z - nZ
    return x >= 0 and x < nWidth and y > 0 and y < nHeight and z > 0 and z < nLength
end

function getPlayerPos()
    local x, y, z = controller.getPlayerPos()
    return x - nX, y - nY, z - nZ
end

function teleportPlayer(x, y, z)
    if x < 0 or x >= nWidth or y < 0 or y >= nHeight or z < 0 or z >= nLength then
        return false
    end
    return controller.teleportPlayerToPos(nX + x, nY + y, nZ + z)
end

function sendMessage(msg)
    controller.sendMessageToPlayer(msg)
end

function savePlayerPos()
    pX, pY, pZ = controller.getPlayerPos()
end

function restorePlayerPos()
    return controller.teleportPlayerToPos(pX, pY, pZ)
end

-- Schematic

function buildSchematic(sPath, x, y, z)
    local schem, err = schematic.load(sPath)
    if not schem then
        return false, err
    end
    local _w, _h, _l = schematic.getSize(schem)
    if not x or not y or not z then
        -- Center
        x = math.floor(nWidth / 2) - math.floor(_w / 2)
        y = 1
        z = math.floor(nLength / 2) - math.floor(_l / 2)
    end
    if x + _w > nWidth then
        w = nWidth - x
    else
        w = _w
    end
    if y + _h > nHeight then
        h = nHeight - y
    else
        h = _h
    end
    if z + _l > nLength then
        l = nLength - z
    else
        l = _l
    end
    local blocks, data = schematic.getBlocks(schem)
    if not blocks then
        return false, "Not blocks to build"
    end
    for _y = 0, h - 1 do
        for _z = 0, l - 1 do
            for _x = 0, w - 1 do
                local n = _y * _w * _l + _z * _w + _x + 1
                set(x + _x, y + _y, z + _z, blocks[n], data and data[n])
            end
        end
        yield()
    end
    return true
end

The NBT api can read any .nbt file, and it supports almost every data type (float and double not supported yet).
The schematic api just uses the nbt api to read the file and then gets the values you want from it. (Note: the schematic files must be uncompressed).
Finally, the VirtualBox api defines some functions to create the "virtual" environment. You just call the init function, then set the location, size and default block (used for the walls) and start using the functions.

Example usage:

local nX, nY, nZ = 0, 0, 0 -- box location
local nWidth, nHeight, nLength = 30, 20, 30 -- box size
local defaultBlock, defaultMeta = 1, 0 -- default block id and metadata

if not nbt then
    os.loadAPI("nbt")
    if not nbt then
        error("Error loading nbt api")
    end
end
if not schematic then
    os.loadAPI("schematic")
    if not schematic then
        error("Error loading schematic api")
    end
end
if not vb then
    os.loadAPI("vb")
    if not vb then
        error("Error loading vb api")
    end
end

if not vb.init() then
    print("Operator Panel not found.")
    return
end

vb.setPos(nX, nY, nZ)
vb.setSize(nWidth, nHeight, nLength)
vb.setDefaultBlock(defaultBlock, defaultMeta)

-- Init
vb.savePlayerPos() -- save the current player position
vb.clearAll() -- clear the box (also adds the walls)

vb.teleportPlayer(nWidth / 2, 1, nLength / 2) -- teleport the player inside

local ok, err = vb.buildSchematic("someSchematicFile") -- build from an shematic file
if not ok then
    print("Error: ", err)
end
sleep(30) -- wait some time

-- End
vb.restorePlayerPos() -- return the player to his position
vb.clearAll() -- clear the box
I named the apis "nbt", "schematic" and "vb" (to make function calls shorter :)/>/>).

The function names are pretty descriptive, but if you have any question, just ask ;)/>/>
KingMachine #10
Posted 19 July 2012 - 05:59 PM
This is pretty much one of the most inventive and powerful things I've seen in quite sometime besides computercraft. Amazing work.
makerimages #11
Posted 20 July 2012 - 06:59 AM
what the heck is it? superfast turtles placing blocks or?????
MysticT #12
Posted 20 July 2012 - 04:38 PM
what the heck is it? superfast turtles placing blocks or?????
I used Computercraft an the operator panel.
It's on the peripheral library. Check it out.
allquan #13
Posted 24 July 2012 - 12:54 PM
@MysticT nice work! I like the way you did it.
ETHANATOR360 #14
Posted 07 August 2012 - 04:08 PM
nice work
Goof #15
Posted 12 October 2012 - 05:57 PM
Whhat the …. How can the computer program, api make that scematic? Is it turtles?
MysticT #16
Posted 12 October 2012 - 06:44 PM
Whhat the …. How can the computer program, api make that scematic? Is it turtles?
Read the op again. It uses the operator panel, a peripheral that lets you place blocks and more.
TheOddByte #17
Posted 12 October 2012 - 07:15 PM
This just look…… AWESOME!!!
Mr. Fang #18
Posted 23 October 2012 - 11:11 PM
Oh My God…how does this even work?
PixelToast #19
Posted 23 October 2012 - 11:48 PM
Oh My God…how does this even work?
a peripheral called operator panel
kaj #20
Posted 24 October 2012 - 10:34 AM
very cool ^_^/>/>