Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --- Можн улучшить:
- -- [кря] Сейчас при установке проектора он поворачивается всегда на сервер, но можно этого не делать, заменив алагаритм нахождения пикселей при нажатии мечём заменив оси, учтённые при установке
- -- TODO
- -- Разобраться с зоной вокруг проектора
- local component, fs, serializ, event = require("component"), require("filesystem"), require("serialization"), require("event")
- local args = require("shell").parse(...)
- local user = ({event.pull()})[5] -- Ник того, кто запустил эту программу
- local nameSaveCFG, FileCfg , cfg = "/home/HoloSave.cfg", "/home/HoloEditor.cfg"
- cfg = fs.exists(nameSaveCFG) and serializ.unserialize(io.open(nameSaveCFG):read()) or {}
- local sensor = component.openperipheral_sensor
- function hologramAdd()
- print("Первичная колибровка, установите проектор")
- repeat until ({event.pull("component_added")})[3] == "hologram" -- TODO при файле конфига не запускает
- result = component.hologram
- result.setRotation(math.floor(sensor.getPlayerByName(user).all().living.yawHead/90+0.5)*90-180,0,1,0)
- --result.setTranslation(0,5,0)
- return result
- end
- local hologram = component.isAvailable("hologram") and component.hologram or hologramAdd()
- local set = hologram.set
- -- цвет, режим линии, шаг для кнопки "шаг назад", сам буфер, буфер кнопок, undo , относительные координаты Hologram к Sensor, переменная отвечающая за отображение всех кнопок
- local color, line, un, buf, buttons, undoBuf, w, fl = 2, 0, 0, {}, {}, {}, {}, {}
- local function add(mas,x,y,z,f)
- mas[x] = mas[x] or {}
- mas[x][y] = mas[x][y] or {}
- mas[x][y][z] = f
- end
- local function read(x,y,z) return buf[x] and buf[x][y] and buf[x][y][z] end -- Считывание буфера
- local xxx,yyy,zzz,ccol
- local function hologramSet(xx,yy,zz,col) -- Ставим пиксель
- if line ~= 0 and xxx == xx and yyy == yy and zzz == zz and ccol == ccol then return end
- add(buf,xx,yy,zz, col ~= 0 and col or nil )
- set(xx,yy,zz,col or 0)
- xxx,yyy,zzz,ccol = xx,yy,zz,col
- end
- local xS, yS, zS
- local Scale = hologram.getScale()
- local sizeRadiusHologram, stepFromHologram = Scale*1.5 , 2
- local zone = sizeRadiusHologram + stepFromHologram
- local function search(name) -- Возвращает данные о расположении игрока относительно координатной плоскости проектора, а так же направление взгляда
- local player
- pcall(function() player = sensor.getPlayerByName(name) end) -- Бывает выдаёт ошибки, поэтому засунул в pcall (name or "" не помогает)
- if player then
- player = player.all()
- local p = player.position
- p.x, p.y, p.z = p.x - w.x , p.y - w.y, p.z - w.z
- if (p.x > -zone) and (p.x < zone) and (p.z > -zone) and (p.z < zone) and (p.y > -Scale) and (p.y < zone*2) then
- local sneaking = player.living.isSneaking
- local growth = sneaking and 1.54 or 1.62 -- player growth
- p.x, p.y, p.z = (p.x + sizeRadiusHologram)/Scale, (p.y-Scale*2+growth-0.003)/Scale, (p.z + sizeRadiusHologram)/Scale -- Смещение к начальным координатам галограммы
- if player.player.isBlocking then
- local xH, yH, zH = p.x*16+1,(p.y)*16+1,p.z*16+1 -- Entry points on the hologram
- local yawHead, pitch = math.rad( player.living.yawHead ) , math.rad( player.living.pitch )
- local dx, dy, dz = -math.sin( yawHead )/48 , -math.tan( pitch )/48 , math.cos( yawHead )/48
- dy = dy > 1 and 1 or dy < -1 and -1 or dy -- Решение проблемы с появлением интвервала между пикселей при рисовании линий под 90 градусов относительно горизонта (голову резко вверх или виз)
- if dy == 1 or dy == -1 then dx, dz = 0,0 end
- return xH, yH, zH, dx, dy, dz, sneaking
- end
- end
- end
- end
- local function main(name)
- local xH, yH, zH, dx, dy, dz, sneaking = search(name)
- if not xH then return end
- local xS, yS, zS = xH, yH, zH
- local flag,undoMiniBuf,xL,yL,zL,x,y,z = true,{}
- repeat
- xH, yH, zH = xH + dx, yH + dy, zH + dz
- x,y,z = math.floor(xH) , math.floor(yH) , math.floor(zH)
- if (fl ~= 0 and buttons[x] and buttons[x][y] and buttons[x][y][z]) or (x == 1 and y == 32 and z == 1) then -- Buttons или столкновение
- buttons[x][y][z]()
- flag = false
- break
- end
- if read(x,y,z) and (x < 48 and y < 48 and z < 48 and x > 1 and y > 1 and z > 1 ) then -- Pixel
- if sneaking then -- Нажал Shift?
- if line == 0 then -- Выключена отрисовка линий?
- xxx = 0 -- <>
- x,y,z = math.floor(xH-dx),math.floor(yH-dy),math.floor(zH-dz)
- hologramSet(x,y,z,color) -- Set Pixel
- table.insert(undoMiniBuf,{color,x,y,z, true})
- break
- else
- xL,yL,zL = x,y,z
- break
- end
- else
- xxx = 0 -- <>
- table.insert(undoMiniBuf,{read(x,y,z),x,y,z, false})
- hologramSet(x,y,z,0) -- Delete Pixel
- flag = false
- break
- end
- end
- until x > 80 or y > 64 or z > 80 or x < -32 or y < -16 or z < -32
- if flag and line ~= 0 and sneaking then
- xH, yH, zH = xS, yS, zS
- x,y,z = 0,0,0
- repeat
- -- while not((x > 48 or y > 48 or z > 48 or x < 1 or y < 1 or z < 1) or (x == xL and y == yL and z == zL)) do
- --while (x < 48 or y < 48 or z < 48 or x > 1 or y > 1 or z > 1) and (x ~= xL and y ~= yL and z ~= zL) do
- xH, yH, zH = xH + dx, yH + dy, zH + dz
- x,y,z = math.floor(xH) , math.floor(yH) , math.floor(zH)
- hologramSet(x,y,z,line)
- table.insert(undoMiniBuf,{color,x,y,z, true})
- --end
- until (x > 48 or y > 48 or z > 48 or x < 1 or y < 1 or z < 1) or (x == xL and y == yL and z == zL)
- end
- if #undoMiniBuf > 0 then
- un = un + 1 > 40 and 1 or un + 1
- undoBuf[un] = undoMiniBuf
- local saveCFG = fs.exists(nameSaveCFG) and serializ.unserialize(io.open(nameSaveCFG):read()) or {}
- for _,v in pairs(undoMiniBuf) do -- Сохранение рисунка
- add(saveCFG,v[2],v[3],v[4],v[5] and v[1] or nil )
- end
- io.open(nameSaveCFG,"w"):write(serializ.serialize(saveCFG)):close()
- end
- end
- local function editScale(inc)
- if Scale+inc<1 and Scale+inc>4 then inc = 0 end
- Scale = Scale+inc/10
- hologram.setScale(Scale)
- sizeRadiusHologram, stepFromHologram = Scale*1.5 , 2
- zone = sizeRadiusHologram + stepFromHologram
- end
- local function start() -- Первичная калибровка координат сенсора и голограммы
- hologram.setScale(1)
- hologram.setTranslation(0,0.5,0)
- editScale(0)
- w.n = 0
- for _,_ in component.list("hologram") do w.n = w.n + 1 end
- if w.n == 1 then
- print("Встав на голографический проектор, нажмите Enter")
- else -- да я да я да
- if w.n == 4 or w.n == 8 then
- print("Встав между голографическими проекторами, нажмите Enter")
- else
- print("Найдено иное количество проекторов, отличающиеся от 1/4/8 шт ")
- end
- end
- local ev
- repeat ev = {event.pull("key_down")} until ev[3] == 13
- local playerPoz = sensor.getPlayerByName(ev[5]).all().position
- w.x, w.y, w.z = playerPoz.x, playerPoz.y, playerPoz.z
- if w.n == 1 or w.n == 8 then w.x, w.y, w.z = math.floor(w.x)+0.5, math.floor(w.y)-0.5, math.floor(w.z)+0.5 end
- if w.n == 4 then w.x, w.y, w.z = math.floor(w.x+0.5), math.floor(w.y+0.5), math.floor(w.z+0.5) end
- io.open(FileCfg,"w"):write(serializ.serialize(w)):close()
- print("При изменении положения сенсора или голограммы, либо запустите программу с параметром reset либо удалите файл HoloEditor.cfg , тогда колибровка запустится вновь")
- end
- local function setButtons(col) -- Выводим кнопки на экран
- for x,v1 in pairs(buttons) do
- for y,v2 in pairs(v1) do
- for z,_ in pairs(v2) do
- set(x,y,z,col)
- end
- end
- end
- for i=2,3 do set(i,5,1,line) end -- анимированная кнопка линии
- end
- local function clearHologram()
- hologram.clear()
- for z = 23,25 do
- for x = 23,25 do
- hologramSet(x,16,z,z-22)
- end
- end
- setButtons(color)
- if fs.exists(nameSaveCFG) then io.open(nameSaveCFG,"w"):write("{}"):close() end -- Стираем буфер сохранения
- end
- local function LineFun() -- Изменения состояния кисти "Линия" и анимация кнопки
- line = line==color and 0 or color
- for i=2,3 do set(i,5,1,line) end
- end --<>
- local function undo() -- Шаг назад
- if undoBuf[un] ~= nil then
- local saveCFG = fs.exists(nameSaveCFG) and serializ.unserialize(io.open(nameSaveCFG):read()) or {}
- for _,v in pairs( undoBuf[un] ) do
- hologramSet(v[2],v[3],v[4],v[5] and 0 or v[1])
- add(saveCFG,v[2],v[3],v[4],v[5] and 0 or v[1])
- end
- undoBuf[un] = nil
- un = un-1 < 1 and 40 or un-1
- io.open(nameSaveCFG,"w"):write(serializ.serialize(saveCFG)):close()
- end
- end
- buttons = {
- { { { 1,1,1 } } , function() color = color+1 > 3 and 1 or color+1 line = line == 0 and 0 or color set(1,1,1,color) setButtons(color) end}, -- Set color
- { { { 1,3,1 } } , function() set(1,3,1,color) hologramSet(math.floor(xS), math.floor(yS), math.floor(zS),color) end}, -- Set pixel to player
- { { { 1,5,1 } } , function() LineFun() set(1,5,1,color) end}, -- Line activation
- { { { 2,5,1 }, { 3,5,1 } } , function() LineFun() end},
- { { { 1,7,1 }, { 1,8,1 } } , function() undo() end},
- { { { 2,10,2 }, { 2,12,2 }, { 1,11,3 }, { 3,11,1 } } , function() editScale(1) end},
- { { { 2,14,2 }, { 1,14,3 }, { 3,14,1 } } , function() editScale(-1) end},
- { { { 1,30,1 } } , function() buf = {} clearHologram() end},
- { { { 1,32,1 } } , function() fl = fl==0 and color or 0 setButtons(fl) set(1,32,1,fl) end}
- }
- local bibi = {}
- for _,v in pairs(buttons) do -- Хитрожопная система, по превращению массива кнопок в удобный массив для использования
- for _,coords in pairs(v[1]) do
- add(bibi,coords[1],coords[2],coords[3],v[2])
- end
- end
- buttons = bibi
- bibi = nil
- if fs.exists(FileCfg) then -- Файл настроек относительных координат проектора
- w = serializ.unserialize(io.open(FileCfg):read())
- if w.n == nil then print("Файл HoloEditor.cfg повреждён. Перезапустите программу") fs.remove(FileCfg) os.exit() end
- else
- start()
- end
- if cfg ~= nil and type(cfg) == "table" then
- hologram.clear()
- for x,v1 in pairs(cfg) do -- Рисуем сохранённый рисунок из файла
- for y,v2 in pairs(v1) do
- for z,col in pairs(v2) do
- hologramSet(x,y,z,col)
- end
- end
- end
- setButtons(color)
- else
- clearHologram()
- end
- while true do
- if args[1] == "reset" then start() end
- if args[1] and tonumber(args[1]) == nil then -- Если при запуске проги был указан ник, тогда не будет поиска
- main(args[1])
- else
- for _,v in pairs( sensor.getPlayers() ) do
- main(v.name)
- end
- end
- os.sleep(0.0001)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement