Ir para conteúdo
Entre para seguir isso  
Capaverde

Função saveMap, salva em um novo .otbm

Recommended Posts

Capaverde    1
Capaverde

Nome: Função saveMap
Autor: Capaverde
Versão Testada: The Forgotten Server - Version 0.2rc9 (Mystic Spirit)

Função que salva o estado do seu mapa num novo .otbm, útil para servidores com sistemas de construção.
Instruções para como instalar abaixo.

bit32 = bit
print = debugPrint

--SPECIAL CHARACTERS
NODE_START = 0xfe
NODE_END = 0xff
ESCAPE_CHAR = 0xfd

--OTBM NODE TYPES
OTBM_ROOTV1 = 1
OTBM_MAP_DATA = 2
OTBM_ITEM_DEF = 3
OTBM_TILE_AREA = 4
OTBM_TILE = 5
OTBM_ITEM = 6
OTBM_TILE_SQUARE = 7
OTBM_TILE_REF = 8
OTBM_SPAWNS = 9
OTBM_SPAWN_AREA = 10
OTBM_MONSTER = 11
OTBM_TOWNS = 12
OTBM_TOWN = 13
OTBM_HOUSETILE = 14

--OTBM ATTR TYPES
OTBM_ATTR_DESCRIPTION = 1
OTBM_ATTR_EXT_FILE = 2
OTBM_ATTR_TILE_FLAGS = 3
OTBM_ATTR_ACTION_ID = 4
OTBM_ATTR_UNIQUE_ID = 5
OTBM_ATTR_TEXT = 6
OTBM_ATTR_DESC = 7
OTBM_ATTR_TELE_DEST = 8
OTBM_ATTR_ITEM = 9
OTBM_ATTR_DEPOT_ID = 10
OTBM_ATTR_EXT_SPAWN_FILE = 11
OTBM_ATTR_RUNE_CHARGES = 12
OTBM_ATTR_EXT_HOUSE_FILE = 13
OTBM_ATTR_HOUSEDOORID = 14
OTBM_ATTR_COUNT = 15
OTBM_ATTR_DURATION = 16
OTBM_ATTR_DECAYING_STATE = 17
OTBM_ATTR_WRITTENDATE = 18
OTBM_ATTR_WRITTENBY = 19
OTBM_ATTR_SLEEPERGUID = 20
OTBM_ATTR_SLEEPSTART = 21
OTBM_ATTR_CHARGES = 22

function lchar(i) s="" while i>0 do s=s..string.char(i%256) i=math.floor(i/256) end return s end

function format(s,size)
    local len = #s
    for x=1,size/8-len do
        s=s.."\0"
    end
    return s
end

function writeData(f,data,size,unescape)
    local thestr
    if type(data) == "string" then
        thestr = format(data,size)
    elseif type(data) == "number" then
        thestr = format(lchar(data),size)
    elseif type(data) == "table" then
        for k,v in pairs(data) do
            print(k,v)
        end
        return
    else
        print(data)
        return
    end
    for x=1,size/8 do
        local c = thestr:sub(x,x)
        --print(#thestr,size,string.byte(c))
        --if c == string.char(0x0D) then error("daonde") end
        if unescape and (c==string.char(NODE_START) or c==string.char(NODE_END) or c==string.char(ESCAPE_CHAR)) then
            f:write(string.char(ESCAPE_CHAR))
        end
        f:write(c)
    end
end

function addU8(f,data)
    writeData(f,data,8,true)
end

function addByte(f,data)
    writeData(f,data,8,false)
end

function addU16(f,data)
    writeData(f,data,16,true)
end

function addU32(f,data)
    writeData(f,data,32,false)
end

function addString(f,data)
    if #data > 0xffff then
        return false
    end
    addU16(f,#data)
    writeData(f,data,#data*8,false)
end

function startNode(f,c) --c is a char
    writeData(f,NODE_START,8,false)
    writeData(f,c,8,true)
end

function endNode(f)
writeData(f,NODE_END,8,false)
end

WIDTH = 128 --put here the dimensions of your map
HEIGHT = 128 --
ITEMDWMAJORVERSION = 2
ITEMDWMINORVERSION = 8

function saveMap(name) --e.g. "map.otbm"
    local minv = math.huge
    local maxv = 0
    print("saveMap start")
    f = io.open(name,"wb")
    addU32(f,0); --version
    startNode(f,0)
    addU32(f,0); --version again 
    addU16(f,WIDTH)
    addU16(f,HEIGHT)
    addU32(f,ITEMDWMAJORVERSION)
    addU32(f,ITEMDWMINORVERSION)

    startNode(f,OTBM_MAP_DATA)
    --addByte(f,OTBM_ATTR_DESCRIPTION)
    --addString(f,"Created with saveMap script, a translation of Remere's")
    local first = true
    local l_x=-1
    local l_y=-1
    local l_Z=-1
    for z=0,7 do
        for xi=0,WIDTH-1,256 do
            for yi=0,HEIGHT-1,256 do
                for x=xi,math.min(xi+256-1,WIDTH-1) do
                    for y=yi,math.min(yi+256-1,HEIGHT-1) do
                        if x<l_x or x>=l_x+256 or y<l_y or y>=l_y+256 or z~=l_z then
                            if not first then
                                endNode(f)
                            end
                            first = false
                            --start new node
                            startNode(f,OTBM_TILE_AREA)
                            l_x=bit32.band(x,0xff00)
                            l_y=bit32.band(y,0xff00)
                            l_z=z
                            addU16(f,l_x)
                            addU16(f,l_y)
                            addU8(f,l_z)
                        end
                        startNode(f,OTBM_TILE)
                        addU8(f,bit32.band(x,0xff))
                        addU8(f,bit32.band(y,0xff))

                        for stackpos=0,10 do
                            local pos = {x=x,y=y,z=z,stackpos=stackpos}
                            local thing = getTileThingByPos(pos)
                                if (thing.itemid==0 and stackpos==0) then --no tile, so we can skip it
                                    break
                                end
                                if thing.itemid > 0 and stackpos ~= 253 then --TODO: save item counts, save containers
                                    addByte(f,OTBM_ATTR_ITEM)
                                    addU16(f,thing.itemid)
                                end
                        end
                        endNode(f)
                    end
                end
            end
        end
    end

    if not first then
        endNode(f)
    end

    endNode(f)
    endNode(f)
    f:close()
    print(minv,maxv)
end

Pra instalar é só colocar o código acima no global.lua, e daí chamar saveMap("map.otbm") onde você quiser, numa talkaction ou npc.
Aviso: Pode lagar um pouco, dependendo do tamanho do seu mapa. Editado por Elwyn
cabeçalho

Compartilhar este post


Link para o post
Gpwjhlkdcf    21
Gpwjhlkdcf

Aprovado!

Editado por Skyen Hasus

Compartilhar este post


Link para o post
Eventide    7
Eventide

Muito interessante, mas eu fiquei mais curioso pra saber qual servidor tem sistema de construção... Será possível fazer um survival tipo minecraft/terraria no Tibia? Seria interessante...

Compartilhar este post


Link para o post
Anderkrox    23
Anderkrox

Gostaria de usar este código, porém está com problemas do fórum!

Compartilhar este post


Link para o post
Elwyn    106
Elwyn

 

 

 

bit32 = bit
print = debugPrint

--SPECIAL CHARACTERS
NODE_START = 0xfe
NODE_END = 0xff
ESCAPE_CHAR = 0xfd

--OTBM NODE TYPES
OTBM_ROOTV1 = 1
OTBM_MAP_DATA = 2
OTBM_ITEM_DEF = 3
OTBM_TILE_AREA = 4
OTBM_TILE = 5
OTBM_ITEM = 6
OTBM_TILE_SQUARE = 7
OTBM_TILE_REF = 8
OTBM_SPAWNS = 9
OTBM_SPAWN_AREA = 10
OTBM_MONSTER = 11
OTBM_TOWNS = 12
OTBM_TOWN = 13
OTBM_HOUSETILE = 14

--OTBM ATTR TYPES
OTBM_ATTR_DESCRIPTION = 1
OTBM_ATTR_EXT_FILE = 2
OTBM_ATTR_TILE_FLAGS = 3
OTBM_ATTR_ACTION_ID = 4
OTBM_ATTR_UNIQUE_ID = 5
OTBM_ATTR_TEXT = 6
OTBM_ATTR_DESC = 7
OTBM_ATTR_TELE_DEST = 8
OTBM_ATTR_ITEM = 9
OTBM_ATTR_DEPOT_ID = 10
OTBM_ATTR_EXT_SPAWN_FILE = 11
OTBM_ATTR_RUNE_CHARGES = 12
OTBM_ATTR_EXT_HOUSE_FILE = 13
OTBM_ATTR_HOUSEDOORID = 14
OTBM_ATTR_COUNT = 15
OTBM_ATTR_DURATION = 16
OTBM_ATTR_DECAYING_STATE = 17
OTBM_ATTR_WRITTENDATE = 18
OTBM_ATTR_WRITTENBY = 19
OTBM_ATTR_SLEEPERGUID = 20
OTBM_ATTR_SLEEPSTART = 21
OTBM_ATTR_CHARGES = 22

function lchar(i) s="" while i>0 do s=s..string.char(i%256) i=math.floor(i/256) end return s end

function format(s,size)
    local len = #s
    for x=1,size/8-len do
        s=s.."\0"
    end
    return s
end

function writeData(f,data,size,unescape)
    local thestr
    if type(data) == "string" then
        thestr = format(data,size)
    elseif type(data) == "number" then
        thestr = format(lchar(data),size)
    elseif type(data) == "table" then
        for k,v in pairs(data) do
            print(k,v)
        end
        return
    else
        print(data)
        return
    end
    for x=1,size/8 do
        local c = thestr:sub(x,x)
        --print(#thestr,size,string.byte(c))
        --if c == string.char(0x0D) then error("daonde") end
        if unescape and (c==string.char(NODE_START) or c==string.char(NODE_END) or c==string.char(ESCAPE_CHAR)) then
            f:write(string.char(ESCAPE_CHAR))
        end
        f:write(c)
    end
end

function addU8(f,data)
    writeData(f,data,8,true)
end

function addByte(f,data)
    writeData(f,data,8,false)
end

function addU16(f,data)
    writeData(f,data,16,true)
end

function addU32(f,data)
    writeData(f,data,32,false)
end

function addString(f,data)
    if #data > 0xffff then
        return false
    end
    addU16(f,#data)
    writeData(f,data,#data*8,false)
end

function startNode(f,c) --c is a char
    writeData(f,NODE_START,8,false)
    writeData(f,c,8,true)
end

function endNode(f)
writeData(f,NODE_END,8,false)
end

WIDTH = 128 --put here the dimensions of your map
HEIGHT = 128 --
ITEMDWMAJORVERSION = 2
ITEMDWMINORVERSION = 8

function saveMap(name) --e.g. "map.otbm"
    local minv = math.huge
    local maxv = 0
    print("saveMap start")
    f = io.open(name,"wb")
    addU32(f,0); --version
    startNode(f,0)
    addU32(f,0); --version again 
    addU16(f,WIDTH)
    addU16(f,HEIGHT)
    addU32(f,ITEMDWMAJORVERSION)
    addU32(f,ITEMDWMINORVERSION)

    startNode(f,OTBM_MAP_DATA)
    --addByte(f,OTBM_ATTR_DESCRIPTION)
    --addString(f,"Created with saveMap script, a translation of Remere's")
    local first = true
    local l_x=-1
    local l_y=-1
    local l_Z=-1
    for z=0,7 do
        for xi=0,WIDTH-1,256 do
            for yi=0,HEIGHT-1,256 do
                for x=xi,math.min(xi+256-1,WIDTH-1) do
                    for y=yi,math.min(yi+256-1,HEIGHT-1) do
                        if x<l_x or x>=l_x+256 or y<l_y or y>=l_y+256 or z~=l_z then
                            if not first then
                                endNode(f)
                            end
                            first = false
                            --start new node
                            startNode(f,OTBM_TILE_AREA)
                            l_x=bit32.band(x,0xff00)
                            l_y=bit32.band(y,0xff00)
                            l_z=z
                            addU16(f,l_x)
                            addU16(f,l_y)
                            addU8(f,l_z)
                        end
                        startNode(f,OTBM_TILE)
                        addU8(f,bit32.band(x,0xff))
                        addU8(f,bit32.band(y,0xff))

                        for stackpos=0,10 do
                            local pos = {x=x,y=y,z=z,stackpos=stackpos}
                            local thing = getTileThingByPos(pos)
                                if (thing.itemid==0 and stackpos==0) then --no tile, so we can skip it
                                    break
                                end
                                if thing.itemid > 0 and stackpos ~= 253 then --TODO: save item counts, save containers
                                    addByte(f,OTBM_ATTR_ITEM)
                                    addU16(f,thing.itemid)
                                end
                        end
                        endNode(f)
                    end
                end
            end
        end
    end

    if not first then
        endNode(f)
    end

    endNode(f)
    endNode(f)
    f:close()
    print(minv,maxv)
end

 

 

Compartilhar este post


Link para o post
Visitante
Este tópico está impedido de receber novos posts.
Entre para seguir isso  
  • Quem Está Navegando   0 membros estão online

    Nenhum usuário registrado visualizando esta página.

×