Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Deals with the model file, and some common operations on it
- --[[
- NOTE: models are described as a series of "fenced" shapes, eg a
- shape going from X=4 to X=6 takes up voxels 4 and 5.
- The range in all 3 dimensions is 0-16: 16 voxels in total (0-1,
- 1-2, 2-3, etc).
- ]]
- local table = require("table")
- local s11n = require("serialization")
- local Model = {}
- Model.__index = Model
- local Textures = {}
- Textures.__index = Textures
- -- Load a model from a file (returns Model or nil, string or nil, in case of error)
- function Model.load(filename)
- local file, reason = io.open(filename, "r")
- if not file then
- return nil, reason
- end
- local rawdata = file:read("*all")
- file:close()
- local data, reason = load("return " .. rawdata)
- if not data then
- return nil, reason
- end
- return setmetatable(data(), Model)
- end
- -- Create a new, empty model
- function Model.new()
- local self = setmetatable({}, Model)
- -- Initialize fields
- self.label = nil -- String
- self.tooltip = nil -- String
- self.lightlevel = nil -- int 0-8
- self.emitRedstone = nil -- bool or int 0-15
- self.buttonMode = nil -- bool
- self.collidable = {true, true}
- self.shapes = {}
- return self
- end
- -- Iterate over the shapes, transforming them into {x,y,z,...}
- -- The resulting voxels are indexed; coords are [1,16]
- function Model:voxels()
- if #self.shapes == 0 then
- -- Empty shapes, dump out
- return function() end
- end
- -- We have to unravel a triply-nested loop, also known as masochism
- local s = 1
- local x = self.shapes[s][1] - 1
- local y = self.shapes[s][2]
- local z = self.shapes[s][3]
- return function()
- x = x + 1
- if x >= self.shapes[s][4] then
- y = y + 1
- x = self.shapes[s][1]
- end
- if y >= self.shapes[s][5] then
- z = z + 1
- -- X rolled over
- y = self.shapes[s][2]
- end
- if z >= self.shapes[s][6] then
- s = s + 1
- if s > #self.shapes then
- return nil
- end
- -- X, Y rolled over on the wrong shape
- x = self.shapes[s][1]
- y = self.shapes[s][2]
- z = self.shapes[s][3]
- end
- return {x+1,y+1,z+1, state=self.shapes[s].state, texture=self.shapes[s].texture, tint=self.shapes[s].tint}
- end
- end
- -- Same as voxels, but loads a texture db and maps it to RGB
- -- Items are in the form {x,y,z,state=state,rgb=rgb}
- function Model:voxels_rgb(txtdb)
- if txtdb == nil then
- txtdb = Textures.load()
- end
- local voxels = self:voxels()
- return function()
- local v = voxels()
- if v == nil then
- return nil
- end
- return {v[1], v[2], v[3], state=v.state, rgb=txtdb:rgb(v)}
- end
- end
- -- Saves out the file. Makes an attempt at pretty-printing. Returns nil or reason
- function Model:save(filename)
- local f, r = io.open(filename, "w")
- if not f then
- return r
- end
- local raw = s11n.serialize(self, 1e99)
- f:write(raw)
- f:close()
- end
- -- Swallows errors, opting to return {} instead
- -- Dunno if this is right
- function Textures.load()
- local file, reasion = io.open("/usr/share/textures", "r")
- if not file then
- return setmetatable({}, Textures)
- end
- local rawdata = file:read("*all")
- file:close()
- local txtdb, reason = s11n.unserialize(rawdata)
- if not txtdb then
- txtdb = {}
- end
- return setmetatable(txtdb, Textures)
- end
- -- Takes a Model shape and guesses an RGB for it
- function Textures:rgb(shape)
- local base = self[shape.texture]
- if base == nil or base < 0 then
- return shape.tint or 0xFF0000
- elseif not shape.tint then
- return base
- else
- -- TODO: average base and tint
- return base
- end
- end
- return {
- Model=Model,
- Textures=Textures,
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement