Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- sender.lua
- -- Camera data transmitter with recording
- local camera = peripheral.find("camera")
- local modem = peripheral.find("modem")
- if not camera then print("No camera!") return end
- if not modem then print("No modem!") return end
- -- Config
- local CHANNEL = 1
- local NETWORK = "security"
- -- State
- local isRecording = false
- local isPlaying = false
- local frames = {}
- local recStart = 0
- local playStart = 0
- local playIndex = 1
- local playSpeed = 1.0
- local doLoop = false
- local tick = 0
- -- Safe method caller
- local function call(method, ...)
- if camera[method] then
- return camera[method](...)
- end
- return nil
- end
- -- Setup
- call("setNetwork", NETWORK)
- call("start")
- modem.open(100)
- print("=== Camera Sender ===")
- print("Commands: rec, stop, play, loop, save, load, test, quit")
- write("> ")
- -- Capture frame
- local function capture(ents, center)
- if not isRecording then return end
- if #frames >= 6000 then
- isRecording = false
- print("\n[REC] Max!")
- write("> ")
- return
- end
- local f = {
- t = tick - recStart,
- e = {},
- c = {
- x = center and center.x or 0,
- y = center and center.y or 0,
- z = center and center.z or 0
- }
- }
- if ents then
- for i = 1, #ents do
- local e = ents[i]
- if e then
- f.e[#f.e + 1] = {
- id = e.id or "",
- name = e.name or "",
- entityType = e.entityType or "",
- isPlayer = e.isPlayer or false,
- x = e.x or 0,
- y = e.y or 0,
- z = e.z or 0,
- yaw = e.yaw or 0,
- pitch = e.pitch or 0,
- bodyYaw = e.bodyYaw or 0
- }
- end
- end
- end
- frames[#frames + 1] = f
- end
- -- Get playback frame
- local function getFrame()
- if not isPlaying or #frames == 0 then
- return nil, nil
- end
- local elapsed = (tick - playStart) * playSpeed
- while playIndex < #frames do
- local nxt = frames[playIndex + 1]
- if nxt and nxt.t and elapsed >= nxt.t then
- playIndex = playIndex + 1
- else
- break
- end
- end
- local last = frames[#frames]
- if last and last.t and elapsed >= last.t then
- if doLoop then
- playStart = tick
- playIndex = 1
- else
- isPlaying = false
- playIndex = 1
- print("\n[PLAY] Done")
- write("> ")
- return nil, nil
- end
- end
- local f = frames[playIndex]
- if f then
- return f.e or {}, f.c or {x=0,y=0,z=0}
- end
- return {}, {x=0,y=0,z=0}
- end
- -- Get live camera data
- local function getLiveData()
- local ents = call("get3DEntityData") or {}
- local center = call("getNetworkCenter") or {x=0,y=0,z=0}
- -- Filter to tables only
- local filtered = {}
- if type(ents) == "table" then
- for i = 1, #ents do
- if type(ents[i]) == "table" then
- filtered[#filtered + 1] = ents[i]
- end
- end
- end
- return filtered, center
- end
- -- Test camera
- local function testCamera()
- print("Testing...")
- local ents = call("get3DEntityData")
- local center = call("getNetworkCenter")
- print("Entities: " .. (ents and #ents or "nil"))
- print("Center: " .. (center and "yes" or "nil"))
- if center then
- print(" x=" .. (center.x or "?"))
- print(" y=" .. (center.y or "?"))
- print(" z=" .. (center.z or "?"))
- end
- end
- -- Commands
- local function cmd(input)
- local c = ((input or ""):match("%S+") or ""):lower()
- local a = (input or ""):match("%S+%s+(%S+)")
- if c == "rec" then
- if isPlaying then print("Stop play first!")
- elseif isRecording then print("Already rec!")
- else
- frames = {}
- recStart = tick
- isRecording = true
- print("[REC] Go...")
- end
- elseif c == "stop" then
- if isRecording then
- isRecording = false
- print("[REC] " .. #frames .. " frames")
- elseif isPlaying then
- isPlaying = false
- playIndex = 1
- print("[PLAY] Stopped")
- else
- print("Nothing")
- end
- elseif c == "play" then
- if isRecording then print("Stop rec first!")
- elseif #frames == 0 then print("No recording!")
- else
- isPlaying = true
- playIndex = 1
- playStart = tick
- print("[PLAY] " .. #frames .. " frames")
- end
- elseif c == "loop" then
- doLoop = not doLoop
- print("Loop: " .. (doLoop and "ON" or "OFF"))
- elseif c == "speed" and a then
- local s = tonumber(a)
- if s then playSpeed = s print("Speed: " .. s) end
- elseif c == "save" then
- local name = a or "rec.dat"
- if #frames == 0 then print("Empty!") return false end
- local file = fs.open(name, "w")
- if file then
- file.write(textutils.serialize(frames))
- file.close()
- print("Saved " .. #frames)
- end
- elseif c == "load" then
- local name = a or "rec.dat"
- if not fs.exists(name) then print("Not found!") return false end
- local file = fs.open(name, "r")
- if file then
- local d = textutils.unserialize(file.readAll())
- file.close()
- if d then frames = d print("Loaded " .. #frames) end
- end
- elseif c == "status" then
- print("Rec:" .. (isRecording and "Y" or "N") .. " Play:" .. (isPlaying and "Y" or "N") .. " Frames:" .. #frames)
- elseif c == "test" then
- testCamera()
- elseif c == "quit" or c == "exit" then
- return true
- end
- return false
- end
- -- Main loop
- local buf = ""
- local timer = os.startTimer(0.05)
- local statCnt = 0
- while true do
- local ev, p1 = os.pullEvent()
- if ev == "timer" and p1 == timer then
- tick = tick + 1
- local ents, center
- if isPlaying then
- ents, center = getFrame()
- else
- ents, center = getLiveData()
- if isRecording then
- capture(ents, center)
- end
- end
- -- Ensure we have valid data
- ents = ents or {}
- center = center or {x=0,y=0,z=0}
- if #ents > 0 then
- modem.transmit(CHANNEL, 100, {
- type = "entities",
- entities = ents,
- center = center,
- isPlayback = isPlaying
- })
- end
- statCnt = statCnt + 1
- if statCnt >= 40 and isRecording then
- statCnt = 0
- print("\n[REC] " .. #frames)
- write("> " .. buf)
- end
- timer = os.startTimer(0.05)
- elseif ev == "char" then
- buf = buf .. p1
- write(p1)
- elseif ev == "key" then
- if p1 == keys.enter then
- print()
- if cmd(buf) then break end
- buf = ""
- write("> ")
- elseif p1 == keys.backspace and #buf > 0 then
- buf = buf:sub(1, -2)
- local x, y = term.getCursorPos()
- term.setCursorPos(x-1, y)
- write(" ")
- term.setCursorPos(x-1, y)
- end
- elseif ev == "terminate" then
- break
- end
- end
- call("stop")
- print("Done.")
Advertisement
Add Comment
Please, Sign In to add comment