camera/init.lua

244 lines
6.3 KiB
Lua
Raw Normal View History

2016-01-30 08:56:04 +01:00
--[[
2017-02-07 22:45:57 +01:00
Copyright 2016-2017 - Auke Kok <sofar@foo-projects.org>
2017-01-20 02:55:19 +01:00
Copyright 2017 - Elijah Duffy <theoctacian@gmail.com>
2016-01-30 08:56:04 +01:00
License:
2017-01-20 02:55:19 +01:00
- Code: MIT
2016-01-30 08:56:04 +01:00
- Models and textures: CC-BY-SA-3.0
2017-01-20 02:55:19 +01:00
Usage: /camera
2016-01-30 08:56:04 +01:00
2017-01-20 02:55:19 +01:00
Execute command to start recording. While recording:
2016-01-30 08:56:04 +01:00
- use up/down to accelerate/decelerate
- use jump to brake
- use crouch to stop recording
Use /camera play to play back the last recording. While playing back:
2016-01-30 08:56:04 +01:00
- use crouch to stop playing back
Use /camera play <name> to play a specific recording
Use /camera save <name> to save the last recording
- saved recordings exist through game restarts
Use /camera list to show all saved recording
2016-01-30 08:56:04 +01:00
--]]
local recordings = {}
2017-02-07 23:07:18 +01:00
-- [function] Load recordings
local path = minetest.get_worldpath()
local function load()
local res = io.open(path.."/recordings.txt", "r")
if res then
res = minetest.deserialize(res:read("*all"))
if type(res) == "table" then
recordings = res
end
end
end
2017-02-07 23:07:18 +01:00
-- Call load
load()
2017-02-07 23:07:18 +01:00
-- [function] Save recordings
function save()
io.open(path.."/recordings.txt", "w"):write(minetest.serialize(recordings))
end
2017-02-07 23:07:18 +01:00
-- [function] Get recording list per-player for chat
function get_recordings(name)
local recs = recordings[name]
local list = ""
if recs then
for name, path in pairs(recs) do
list = list..name..", "
end
return list
else
return "You do not saved any recordings."
end
end
2017-02-07 23:07:18 +01:00
-- [event] On shutdown save recordings
minetest.register_on_shutdown(save)
-- Table for storing unsaved temporary recordings
local temp = {}
2017-02-07 23:07:18 +01:00
-- Camera definition
2016-01-30 08:56:04 +01:00
local camera = {
description = "Camera",
2017-01-20 02:55:19 +01:00
visual = "wielditem",
textures = {},
2016-01-30 08:56:04 +01:00
physical = false,
2017-01-20 02:55:19 +01:00
is_visible = false,
collide_with_objects = false,
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
physical = false,
visual = "cube",
2016-01-30 08:56:04 +01:00
driver = nil,
mode = 0,
velocity = {x=0, y=0, z=0},
old_pos = nil,
old_velocity = nil,
pre_stop_dir = nil,
MAX_V = 20,
init = function(self, player, mode)
self.driver = player
self.mode = mode
self.path = {}
end,
}
2017-01-20 02:55:19 +01:00
2017-02-07 23:07:18 +01:00
-- [event] On step
2016-01-30 08:56:04 +01:00
function camera:on_step(dtime)
2017-02-07 23:07:18 +01:00
-- if not driver, remove object
2016-01-30 08:56:04 +01:00
if not self.driver then
self.object:remove()
return
end
2017-02-07 23:07:18 +01:00
2016-01-30 08:56:04 +01:00
local pos = self.object:getpos()
local vel = self.object:getvelocity()
local dir = self.driver:get_look_dir()
2017-02-07 23:07:18 +01:00
-- if record mode
2016-01-30 08:56:04 +01:00
if self.mode == 0 then
2017-02-07 23:07:18 +01:00
-- Update path
2016-01-30 08:56:04 +01:00
self.path[#self.path + 1] = {
pos = pos,
velocity = vel,
pitch = self.driver:get_look_pitch(),
yaw = self.driver:get_look_yaw()
}
2017-02-07 23:07:18 +01:00
-- Modify yaw and pitch to match driver (player)
2016-01-30 08:56:04 +01:00
self.object:set_look_pitch(self.driver:get_look_pitch())
self.object:set_look_yaw(self.driver:get_look_yaw())
2017-01-20 02:55:19 +01:00
2017-02-07 23:07:18 +01:00
-- Get controls
2016-01-30 08:56:04 +01:00
local ctrl = self.driver:get_player_control()
2017-02-07 23:07:18 +01:00
-- Initialize speed
2016-01-30 08:56:04 +01:00
local speed = vector.distance(vector.new(), vel)
2017-02-07 23:07:18 +01:00
-- if up, accelerate forward
2016-01-30 08:56:04 +01:00
if ctrl.up then
speed = math.min(speed + 0.1, 20)
end
2017-02-07 23:07:18 +01:00
-- if down, accelerate backward
2016-01-30 08:56:04 +01:00
if ctrl.down then
speed = math.max(speed - 0.1, -20)
end
2017-02-07 23:07:18 +01:00
-- if jump, brake
2016-01-30 08:56:04 +01:00
if ctrl.jump then
speed = math.max(speed * 0.9, 0.0)
end
2017-02-07 23:07:18 +01:00
-- if sneak, stop recording
2016-01-30 08:56:04 +01:00
if ctrl.sneak then
self.driver:set_detach()
minetest.chat_send_player(self.driver:get_player_name(), "Recorded stopped after " .. #self.path .. " points")
temp[self.driver:get_player_name()] = table.copy(self.path)
2016-01-30 08:56:04 +01:00
self.object:remove()
return
end
2017-02-07 23:07:18 +01:00
-- Set updated velocity
2016-01-30 08:56:04 +01:00
self.object:setvelocity(vector.multiply(self.driver:get_look_dir(), speed))
2017-02-07 23:07:18 +01:00
elseif self.mode == 1 then -- elseif playback mode
-- Get controls
2016-01-30 08:56:04 +01:00
local ctrl = self.driver:get_player_control()
2017-02-07 23:07:18 +01:00
-- if sneak or no path, stop playback
2016-01-30 08:56:04 +01:00
if ctrl.sneak or #self.path < 1 then
self.driver:set_detach()
minetest.chat_send_player(self.driver:get_player_name(), "Playback stopped")
self.object:remove()
return
end
2017-02-07 23:07:18 +01:00
-- Update position
2016-01-30 08:56:04 +01:00
self.object:moveto(self.path[1].pos, true)
2017-02-07 23:07:18 +01:00
-- Update yaw/pitch
2016-01-30 08:56:04 +01:00
self.driver:set_look_yaw(self.path[1].yaw - (math.pi/2))
self.driver:set_look_pitch(0 - self.path[1].pitch)
2017-02-07 23:07:18 +01:00
-- Update velocity
2016-01-30 08:56:04 +01:00
self.object:setvelocity(self.path[1].velocity)
2017-02-07 23:07:18 +01:00
-- Remove path table
2016-01-30 08:56:04 +01:00
table.remove(self.path, 1)
end
end
2017-02-07 23:07:18 +01:00
-- Register entity
2016-01-30 08:56:04 +01:00
minetest.register_entity("camera:camera", camera)
2017-02-07 23:07:18 +01:00
-- Register chatcommand
2017-01-20 02:55:19 +01:00
minetest.register_chatcommand("camera", {
description = "Manipulate recording",
2017-02-07 23:07:18 +01:00
params = "<option> <value>",
2017-01-20 02:55:19 +01:00
func = function(name, param)
2017-02-07 23:07:18 +01:00
local player = minetest.get_player_by_name(name)
local param1, param2 = param:split(" ")[1], param:split(" ")[2]
2017-02-07 23:07:18 +01:00
-- if play, begin playback preperation
if param1 == "play" then
local function play(path)
local object = minetest.add_entity(player:getpos(), "camera:camera")
object:get_luaentity():init(player, 1)
object:setyaw(player:get_look_yaw())
player:set_attach(object, "", {x=5,y=10,z=0}, {x=0,y=0,z=0})
object:get_luaentity().path = path
end
2017-01-20 02:55:19 +01:00
-- Check for param2 (recording name)
if param2 and param2 ~= "" then
2017-02-07 23:07:18 +01:00
-- if recording exists, start
if recordings[name][param2] then
play(table.copy(recordings[name][param2]))
2017-02-07 23:07:18 +01:00
else -- else, return error
return false, "Invalid recording "..param2..". Use /camera list to list recordings."
end
2017-02-07 23:07:18 +01:00
else -- else, check temp for a recording path
if temp[name] then
play(table.copy(temp[name]))
else
return false, "No recordings could be found"
end
2017-01-20 02:55:19 +01:00
end
2017-01-20 02:55:19 +01:00
return true, "Playback started"
2017-02-07 23:07:18 +01:00
elseif param1 == "save" then -- elseif save, prepare to save path
-- if no table for player in recordings, initialize
if not recordings[name] then
recordings[name] = {}
end
2017-02-07 23:07:18 +01:00
-- if param2 is not blank, save
if param2 and param2 ~= "" then
recordings[name][param2] = temp[name]
return true, "Saved recording as "..param2
2017-02-07 23:07:18 +01:00
else -- else, return error
return false, "Missing name to save recording under (/camera save <name>)"
end
2017-02-07 23:07:18 +01:00
elseif param1 == "list" then -- elseif list, list recordings
return true, "Recordings: "..get_recordings(name)
2017-02-07 23:07:18 +01:00
else -- else, begin recording
2017-01-20 02:55:19 +01:00
local object = minetest.add_entity(player:getpos(), "camera:camera")
object:get_luaentity():init(player, 0)
object:setyaw(player:get_look_yaw())
player:set_attach(object, "", {x=0,y=10,z=0}, {x=0,y=0,z=0})
return true, "Recording started"
2016-01-30 08:56:04 +01:00
end
end,
})