mirror of
https://github.com/Oarcinae/FactorioScenarioMultiplayerSpawn.git
synced 2025-01-30 03:38:00 +02:00
Removing locale in preparation for including a git submodule.
This commit is contained in:
parent
dc1c503244
commit
8c221f67bf
@ -1,38 +0,0 @@
|
||||
-- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss <alexthkloss@web.de>
|
||||
-- licensed under the terms of the LGPL2
|
||||
|
||||
-- character table string
|
||||
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||
local M = {}
|
||||
|
||||
-- encoding
|
||||
M.enc = function(data)
|
||||
return ((data:gsub('.', function(x)
|
||||
local r,b='',x:byte()
|
||||
for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
|
||||
return r;
|
||||
end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
|
||||
if (#x < 6) then return '' end
|
||||
local c=0
|
||||
for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
|
||||
return b:sub(c+1,c+1)
|
||||
end)..({ '', '==', '=' })[#data%3+1])
|
||||
end
|
||||
|
||||
-- decoding
|
||||
M.dec = function(data)
|
||||
data = string.gsub(data, '[^'..b..'=]', '')
|
||||
return (data:gsub('.', function(x)
|
||||
if (x == '=') then return '' end
|
||||
local r,f='',(b:find(x)-1)
|
||||
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
|
||||
return r;
|
||||
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
|
||||
if (#x ~= 8) then return '' end
|
||||
local c=0
|
||||
for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
|
||||
return string.char(c)
|
||||
end))
|
||||
end
|
||||
|
||||
return M
|
@ -1,241 +0,0 @@
|
||||
--[[
|
||||
Blueprint String
|
||||
Copyright (c) 2016 David McWilliams, MIT License
|
||||
|
||||
This library helps you convert blueprints to text strings, and text strings to blueprints.
|
||||
|
||||
|
||||
Saving Blueprints
|
||||
-----------------
|
||||
local BlueprintString = require "blueprintstring.blueprintstring"
|
||||
local blueprint_table = {
|
||||
entities = blueprint.get_blueprint_entities(),
|
||||
tiles = blueprint.get_blueprint_tiles(),
|
||||
icons = blueprint.blueprint_icons,
|
||||
name = blueprint.label,
|
||||
myfield = "Add some extra fields if you want",
|
||||
}
|
||||
local str = BlueprintString.toString(blueprint_table)
|
||||
|
||||
|
||||
Loading Blueprints
|
||||
------------------
|
||||
local BlueprintString = require "blueprintstring.blueprintstring"
|
||||
local blueprint_table = BlueprintString.fromString(str)
|
||||
blueprint.set_blueprint_entities(blueprint_table.entities)
|
||||
blueprint.set_blueprint_tiles(blueprint_table.tiles)
|
||||
blueprint.blueprint_icons = blueprint_table.icons
|
||||
blueprint.label = blueprint_table.name or ""
|
||||
|
||||
|
||||
Blueprint Books
|
||||
------------------
|
||||
A blueprint book is stored in the book field.
|
||||
The active blueprint is index 1, other blueprints start from index 2.
|
||||
|
||||
local blueprint_table = {
|
||||
name = "Label for blueprint book",
|
||||
book = {
|
||||
[1] = {
|
||||
entities = active_inventory[1].get_blueprint_entities(),
|
||||
icons = active_inventory[1].blueprint_icons,
|
||||
},
|
||||
[2] = {
|
||||
entities = main_inventory[1].get_blueprint_entities(),
|
||||
icons = main_inventory[1].blueprint_icons,
|
||||
},
|
||||
[3] = {
|
||||
entities = main_inventory[2].get_blueprint_entities(),
|
||||
icons = main_inventory[2].blueprint_icons,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
]]--
|
||||
|
||||
local serpent = require "serpent0272"
|
||||
local inflate = require "deflatelua"
|
||||
local deflate = require "zlib-deflate"
|
||||
local base64 = require "base64"
|
||||
|
||||
function trim(s)
|
||||
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
|
||||
function item_count(t)
|
||||
local count = 0
|
||||
if (#t >= 2) then return 2 end
|
||||
for k,v in pairs(t) do count = count + 1 end
|
||||
return count
|
||||
end
|
||||
|
||||
function fix_entities(array)
|
||||
if (not array or type(array) ~= "table") then return {} end
|
||||
local entities = {}
|
||||
local count = 1
|
||||
for _, entity in ipairs(array) do
|
||||
if (type(entity) == 'table') then
|
||||
-- Factorio 0.12 format
|
||||
if (entity.conditions and type(entity.conditions) == 'table') then
|
||||
if (entity.conditions.circuit) then
|
||||
entity.control_behavior = {circuit_condition = entity.conditions.circuit}
|
||||
end
|
||||
if (entity.conditions.arithmetic) then
|
||||
entity.control_behavior = {arithmetic_conditions = entity.conditions.arithmetic}
|
||||
end
|
||||
if (entity.conditions.decider) then
|
||||
entity.control_behavior = {decider_conditions = entity.conditions.decider}
|
||||
end
|
||||
end
|
||||
if (entity.name == "constant-combinator" and entity.filters) then
|
||||
entity.control_behavior = {filters = entity.filters}
|
||||
end
|
||||
|
||||
-- Factorio 0.13 format
|
||||
if (entity.name == "constant-combinator" and entity.control_behavior and type(entity.control_behavior) == 'table' and entity.control_behavior.filters and type(entity.control_behavior.filters) == 'table') then
|
||||
for _, filter in pairs(entity.control_behavior.filters) do
|
||||
local uint32 = tonumber(filter.count)
|
||||
if (uint32 and uint32 >= 2147483648 and uint32 < 4294967296) then
|
||||
filter.count = uint32 - 4294967296
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Add entity number
|
||||
entity.entity_number = count
|
||||
entities[count] = entity
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return entities
|
||||
end
|
||||
|
||||
function fix_icons(array)
|
||||
if (not array or type(array) ~= "table") then return {} end
|
||||
if (#array > 1000) then return {} end
|
||||
local icons = {}
|
||||
local count = 1
|
||||
for _, icon in pairs(array) do
|
||||
if (count > 4) then break end
|
||||
if (type(icon) == "table" and icon.signal) then
|
||||
-- Factorio 0.13 format
|
||||
table.insert(icons, {index = count, signal = icon.signal})
|
||||
count = count + 1
|
||||
elseif (type(icon) == "table" and icon.name) then
|
||||
-- Factorio 0.12 format
|
||||
if (icon.name == "straight-rail" or icon.name == "curved-rail") then
|
||||
icon.name = "rail"
|
||||
end
|
||||
table.insert(icons, {index = count, signal = {type = "item", name = icon.name}})
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return icons
|
||||
end
|
||||
|
||||
function fix_name(name)
|
||||
if (not name or type(name) ~= "string") then return nil end
|
||||
return name:sub(1,100)
|
||||
end
|
||||
|
||||
function remove_useless_fields(entities)
|
||||
if (not entities or type(entities) ~= "table") then return end
|
||||
for _, entity in ipairs(entities) do
|
||||
if (type(entity) ~= "table") then entity = {} end
|
||||
|
||||
-- Entity_number is calculated in fix_entities()
|
||||
entity.entity_number = nil
|
||||
|
||||
if (item_count(entity) == 0) then entity = nil end
|
||||
end
|
||||
end
|
||||
|
||||
-- ====================================================
|
||||
-- Public API
|
||||
|
||||
local M = {}
|
||||
|
||||
M.COMPRESS_STRINGS = true -- Compress saved strings. Format is gzip + base64.
|
||||
M.LINE_LENGTH = 120 -- Length of lines in compressed string. 0 means unlimited length.
|
||||
|
||||
M.toString = function(blueprint_table)
|
||||
remove_useless_fields(blueprint_table.entities)
|
||||
blueprint_table.name = fix_name(blueprint_table.name)
|
||||
if (blueprint_table.book) then
|
||||
for _, page in pairs(blueprint_table.book) do
|
||||
remove_useless_fields(page.entities)
|
||||
page.name = fix_name(page.name)
|
||||
end
|
||||
end
|
||||
|
||||
local data = serpent.dump(blueprint_table)
|
||||
if (M.COMPRESS_STRINGS) then
|
||||
data = deflate.gzip(data)
|
||||
data = base64.enc(data)
|
||||
if (M.LINE_LENGTH > 0) then
|
||||
-- Add line breaks
|
||||
data = data:gsub( ("%S"):rep(M.LINE_LENGTH), "%1\n" )
|
||||
end
|
||||
end
|
||||
data = data .. "\n"
|
||||
return data
|
||||
end
|
||||
|
||||
M.fromString = function(data)
|
||||
data = trim(data)
|
||||
if (string.sub(data, 1, 8) ~= "do local") then
|
||||
-- Decompress string
|
||||
local output = {}
|
||||
local input = base64.dec(data)
|
||||
local status, result = pcall(inflate.gunzip, { input = input, output = function(byte) output[#output+1] = string.char(byte) end })
|
||||
if (status) then
|
||||
data = table.concat(output)
|
||||
else
|
||||
--game.player.print(result)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Factorio 0.12 to 0.13 entity rename
|
||||
data = data:gsub("[%w-]+", {
|
||||
["basic-accumulator"] = "accumulator",
|
||||
["basic-armor"] = "light-armor",
|
||||
["basic-beacon"] = "beacon",
|
||||
["basic-bullet-magazine"] = "firearm-magazine",
|
||||
["basic-exoskeleton-equipment"] = "exoskeleton-equipment",
|
||||
["basic-grenade"] = "grenade",
|
||||
["basic-inserter"] = "inserter",
|
||||
["basic-laser-defense-equipment"] = "personal-laser-defense-equipment",
|
||||
["basic-mining-drill"] = "electric-mining-drill",
|
||||
["basic-modular-armor"] = "modular-armor",
|
||||
["basic-splitter"] = "splitter",
|
||||
["basic-transport-belt"] = "transport-belt",
|
||||
["basic-transport-belt-to-ground"] = "underground-belt",
|
||||
["express-transport-belt-to-ground"] = "express-underground-belt",
|
||||
["fast-transport-belt-to-ground"] = "fast-underground-belt",
|
||||
["piercing-bullet-magazine"] = "piercing-rounds-magazine",
|
||||
["smart-chest"] = "steel-chest",
|
||||
["smart-inserter"] = "filter-inserter",
|
||||
})
|
||||
|
||||
local status, result = serpent.load(data)
|
||||
if (not status) then
|
||||
--game.player.print(result)
|
||||
return nil
|
||||
end
|
||||
|
||||
result.entities = fix_entities(result.entities)
|
||||
result.icons = fix_icons(result.icons)
|
||||
result.name = fix_name(result.name)
|
||||
if (result.book) then
|
||||
for _, page in pairs(result.book) do
|
||||
page.entities = fix_entities(page.entities)
|
||||
page.icons = fix_icons(page.icons)
|
||||
page.name = fix_name(page.name)
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
return M
|
@ -1,207 +0,0 @@
|
||||
--[[
|
||||
|
||||
LUA MODULE
|
||||
|
||||
digest.crc32 - CRC-32 checksum implemented entirely in Lua.
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
local CRC = require 'digest.crc32lua'
|
||||
print(CRC.crc32 'test') --> 0xD87F7E0C or -662733300
|
||||
|
||||
assert(CRC.crc32('st', CRC.crc32('te')) == CRC.crc32 'test')
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
This can be used to compute CRC-32 checksums on strings.
|
||||
This is similar to [1-2].
|
||||
|
||||
API
|
||||
|
||||
Note: in the functions below, checksums are 32-bit integers stored in
|
||||
numbers. The number format currently depends on the bit
|
||||
implementation--see DESIGN NOTES below.
|
||||
|
||||
CRC.crc32_byte(byte [, crc]) --> rcrc
|
||||
|
||||
Returns CRC-32 checksum `rcrc` of byte `byte` (number 0..255) appended to
|
||||
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
|
||||
if omitted.
|
||||
|
||||
CRC.crc32_string(s, crc) --> bcrc
|
||||
|
||||
Returns CRC-32 checksum `rcrc` of string `s` appended to
|
||||
a string with CRC-32 checksum `crc`. `crc` defaults to 0 (empty string)
|
||||
if omitted.
|
||||
|
||||
CRC.crc32(o, crc) --> bcrc
|
||||
|
||||
This invokes `crc32_byte` if `o` is a byte or `crc32_string` if `o`
|
||||
is a string.
|
||||
|
||||
CRC.bit
|
||||
|
||||
This contains the underlying bit library used by the module. It
|
||||
should be considered a read-only copy.
|
||||
|
||||
DESIGN NOTES
|
||||
|
||||
Currently, this module exposes the underlying bit array implementation in CRC
|
||||
checksums returned. In BitOp, bit arrays are 32-bit signed integer numbers
|
||||
(may be negative). In Lua 5.2 'bit32' and 'bit.numberlua', bit arrays are
|
||||
32-bit unsigned integer numbers (non-negative). This is subject to change
|
||||
in the future but is currently done due to (unconfirmed) performance
|
||||
implications.
|
||||
|
||||
On platforms with 64-bit numbers, one way to normalize CRC
|
||||
checksums to be unsigned is to do `crcvalue % 2^32`,
|
||||
|
||||
The name of this module is inspired by Perl `Digest::CRC*`.
|
||||
|
||||
DEPENDENCIES
|
||||
|
||||
Requires one of the following bit libraries:
|
||||
|
||||
BitOp "bit" -- bitop.luajit.org -- This is included in LuaJIT and also available
|
||||
for Lua 5.1/5.2. This provides the fastest performance in LuaJIT.
|
||||
Lua 5.2 "bit32" -- www.lua.org/manual/5.2 -- This is provided in Lua 5.2
|
||||
and is preferred in 5.2 (unless "bit" also happens to be installed).
|
||||
"bit.numberlua" (>=000.003) -- https://github.com/davidm/lua-bit-numberlua
|
||||
This is slowest and used as a last resort.
|
||||
It is only a few times slower than "bit32" though.
|
||||
|
||||
DOWNLOAD/INSTALLATION
|
||||
|
||||
If using LuaRocks:
|
||||
luarocks install lua-digest-crc32lua
|
||||
|
||||
Otherwise, download <https://github.com/davidm/lua-digest-crc32lua/zipball/master>.
|
||||
Alternately, if using git:
|
||||
git clone git://github.com/davidm/lua-digest-crc32lua.git
|
||||
cd lua-digest-crc32lua
|
||||
Optionally unpack:
|
||||
./util.mk
|
||||
or unpack and install in LuaRocks:
|
||||
./util.mk install
|
||||
|
||||
REFERENCES
|
||||
|
||||
[1] http://www.axlradius.com/freestuff/CRC32.java
|
||||
[2] http://www.gamedev.net/reference/articles/article1941.asp
|
||||
[3] http://java.sun.com/j2se/1.5.0/docs/api/java/util/zip/CRC32.html
|
||||
[4] http://www.dsource.org/projects/tango/docs/current/tango.io.digest.Crc32.html
|
||||
[5] http://pydoc.org/1.5.2/zlib.html#-crc32
|
||||
[6] http://www.python.org/doc/2.5.2/lib/module-binascii.html
|
||||
|
||||
LICENSE
|
||||
|
||||
(c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
(end license)
|
||||
|
||||
--]]
|
||||
|
||||
|
||||
local M = {_TYPE='module', _NAME='digest.crc32', _VERSION='0.3.20111128'}
|
||||
|
||||
local type = type
|
||||
local require = require
|
||||
local setmetatable = setmetatable
|
||||
|
||||
--[[
|
||||
Requires the first module listed that exists, else raises like `require`.
|
||||
If a non-string is encountered, it is returned.
|
||||
Second return value is module name loaded (or '').
|
||||
--]]
|
||||
local function requireany(...)
|
||||
local errs = {}
|
||||
for _,name in ipairs{...} do
|
||||
if type(name) ~= 'string' then return name, '' end
|
||||
local ok, mod = pcall(require, name)
|
||||
if ok then return mod, name end
|
||||
errs[#errs+1] = mod
|
||||
end
|
||||
error(table.concat(errs, '\n'), 2)
|
||||
end
|
||||
|
||||
local bit, name_ = requireany('bit', 'bit32', 'bit.numberlua')
|
||||
local bxor = bit.bxor
|
||||
local bnot = bit.bnot
|
||||
local band = bit.band
|
||||
local rshift = bit.rshift
|
||||
|
||||
-- CRC-32-IEEE 802.3 (V.42)
|
||||
local POLY = 0xEDB88320
|
||||
|
||||
-- Memoize function pattern (like http://lua-users.org/wiki/FuncTables ).
|
||||
local function memoize(f)
|
||||
local mt = {}
|
||||
local t = setmetatable({}, mt)
|
||||
function mt:__index(k)
|
||||
local v = f(k); t[k] = v
|
||||
return v
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
-- CRC table.
|
||||
local crc_table = memoize(function(i)
|
||||
local crc = i
|
||||
for _=1,8 do
|
||||
local b = band(crc, 1)
|
||||
crc = rshift(crc, 1)
|
||||
if b == 1 then crc = bxor(crc, POLY) end
|
||||
end
|
||||
return crc
|
||||
end)
|
||||
|
||||
|
||||
function M.crc32_byte(byte, crc)
|
||||
crc = bnot(crc or 0)
|
||||
local v1 = rshift(crc, 8)
|
||||
local v2 = crc_table[bxor(crc % 256, byte)]
|
||||
return bnot(bxor(v1, v2))
|
||||
end
|
||||
local M_crc32_byte = M.crc32_byte
|
||||
|
||||
|
||||
function M.crc32_string(s, crc)
|
||||
crc = crc or 0
|
||||
for i=1,#s do
|
||||
crc = M_crc32_byte(s:byte(i), crc)
|
||||
end
|
||||
return crc
|
||||
end
|
||||
local M_crc32_string = M.crc32_string
|
||||
|
||||
|
||||
function M.crc32(s, crc)
|
||||
if type(s) == 'string' then
|
||||
return M_crc32_string(s, crc)
|
||||
else
|
||||
return M_crc32_byte(s, crc)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
M.bit = bit -- bit library used
|
||||
|
||||
|
||||
return M
|
@ -1,866 +0,0 @@
|
||||
--[[
|
||||
|
||||
LUA MODULE
|
||||
|
||||
compress.deflatelua - deflate (and gunzip/zlib) implemented in Lua.
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
local DEFLATE = require 'compress.deflatelua'
|
||||
-- uncompress gzip file
|
||||
local fh = assert(io.open'foo.txt.gz', 'rb')
|
||||
local ofh = assert(io.open'foo.txt', 'wb')
|
||||
DEFLATE.gunzip {input=fh, output=ofh}
|
||||
fh:close(); ofh:close()
|
||||
-- can also uncompress from string including zlib and raw DEFLATE formats.
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
This is a pure Lua implementation of decompressing the DEFLATE format,
|
||||
including the related zlib and gzip formats.
|
||||
|
||||
Note: This library only supports decompression.
|
||||
Compression is not currently implemented.
|
||||
|
||||
API
|
||||
|
||||
Note: in the following functions, input stream `fh` may be
|
||||
a file handle, string, or an iterator function that returns strings.
|
||||
Output stream `ofh` may be a file handle or a function that
|
||||
consumes one byte (number 0..255) per call.
|
||||
|
||||
DEFLATE.inflate {input=fh, output=ofh}
|
||||
|
||||
Decompresses input stream `fh` in the DEFLATE format
|
||||
while writing to output stream `ofh`.
|
||||
DEFLATE is detailed in http://tools.ietf.org/html/rfc1951 .
|
||||
|
||||
DEFLATE.gunzip {input=fh, output=ofh, disable_crc=disable_crc}
|
||||
|
||||
Decompresses input stream `fh` with the gzip format
|
||||
while writing to output stream `ofh`.
|
||||
`disable_crc` (defaults to `false`) will disable CRC-32 checking
|
||||
to increase speed.
|
||||
gzip is detailed in http://tools.ietf.org/html/rfc1952 .
|
||||
|
||||
DEFLATE.inflate_zlib {input=fh, output=ofh, disable_crc=disable_crc}
|
||||
|
||||
Decompresses input stream `fh` with the zlib format
|
||||
while writing to output stream `ofh`.
|
||||
`disable_crc` (defaults to `false`) will disable CRC-32 checking
|
||||
to increase speed.
|
||||
zlib is detailed in http://tools.ietf.org/html/rfc1950 .
|
||||
|
||||
DEFLATE.adler32(byte, crc) --> rcrc
|
||||
|
||||
Returns adler32 checksum of byte `byte` (number 0..255) appended
|
||||
to string with adler32 checksum `crc`. This is internally used by
|
||||
`inflate_zlib`.
|
||||
ADLER32 in detailed in http://tools.ietf.org/html/rfc1950 .
|
||||
|
||||
COMMAND LINE UTILITY
|
||||
|
||||
A `gunziplua` command line utility (in folder `bin`) is also provided.
|
||||
This mimicks the *nix `gunzip` utility but is a pure Lua implementation
|
||||
that invokes this library. For help do
|
||||
|
||||
gunziplua -h
|
||||
|
||||
DEPENDENCIES
|
||||
|
||||
Requires 'digest.crc32lua' (used for optional CRC-32 checksum checks).
|
||||
https://github.com/davidm/lua-digest-crc32lua
|
||||
|
||||
Will use a bit library ('bit', 'bit32', 'bit.numberlua') if available. This
|
||||
is not that critical for this library but is required by digest.crc32lua.
|
||||
|
||||
'pythonic.optparse' is only required by the optional `gunziplua`
|
||||
command-line utilty for command line parsing.
|
||||
https://github.com/davidm/lua-pythonic-optparse
|
||||
|
||||
INSTALLATION
|
||||
|
||||
Copy the `compress` directory into your LUA_PATH.
|
||||
|
||||
REFERENCES
|
||||
|
||||
[1] DEFLATE Compressed Data Format Specification version 1.3
|
||||
http://tools.ietf.org/html/rfc1951
|
||||
[2] GZIP file format specification version 4.3
|
||||
http://tools.ietf.org/html/rfc1952
|
||||
[3] http://en.wikipedia.org/wiki/DEFLATE
|
||||
[4] pyflate, by Paul Sladen
|
||||
http://www.paul.sladen.org/projects/pyflate/
|
||||
[5] Compress::Zlib::Perl - partial pure Perl implementation of
|
||||
Compress::Zlib
|
||||
http://search.cpan.org/~nwclark/Compress-Zlib-Perl/Perl.pm
|
||||
|
||||
LICENSE
|
||||
|
||||
(c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
(end license)
|
||||
--]]
|
||||
|
||||
local M = {_TYPE='module', _NAME='compress.deflatelua', _VERSION='0.3.20111128'}
|
||||
|
||||
local assert = assert
|
||||
local error = error
|
||||
local ipairs = ipairs
|
||||
local pairs = pairs
|
||||
local print = print
|
||||
local require = require
|
||||
local tostring = tostring
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local io = io
|
||||
local math = math
|
||||
local table_sort = table.sort
|
||||
local math_max = math.max
|
||||
local string_char = string.char
|
||||
|
||||
--[[
|
||||
Requires the first module listed that exists, else raises like `require`.
|
||||
If a non-string is encountered, it is returned.
|
||||
Second return value is module name loaded (or '').
|
||||
--]]
|
||||
local function requireany(...)
|
||||
local errs = {}
|
||||
for i = 1, select('#', ...) do local name = select(i, ...)
|
||||
if type(name) ~= 'string' then return name, '' end
|
||||
local ok, mod = pcall(require, name)
|
||||
if ok then return mod, name end
|
||||
errs[#errs+1] = mod
|
||||
end
|
||||
error(table.concat(errs, '\n'), 2)
|
||||
end
|
||||
|
||||
|
||||
local crc32 = require "crc32lua" . crc32_byte
|
||||
local bit, name_ = requireany('bit', 'bit32', 'bit.numberlua', nil)
|
||||
|
||||
local DEBUG = false
|
||||
|
||||
-- Whether to use `bit` library functions in current module.
|
||||
-- Unlike the crc32 library, it doesn't make much difference in this module.
|
||||
local NATIVE_BITOPS = (bit ~= nil)
|
||||
|
||||
local band, lshift, rshift
|
||||
if NATIVE_BITOPS then
|
||||
band = bit.band
|
||||
lshift = bit.lshift
|
||||
rshift = bit.rshift
|
||||
end
|
||||
|
||||
|
||||
local function warn(s)
|
||||
-- io.stderr:write(s, '\n')
|
||||
end
|
||||
|
||||
|
||||
local function debug(...)
|
||||
print('DEBUG', ...)
|
||||
end
|
||||
|
||||
|
||||
local function runtime_error(s, level)
|
||||
error(s)
|
||||
end
|
||||
|
||||
|
||||
local function make_outstate(outbs)
|
||||
local outstate = {}
|
||||
outstate.outbs = outbs
|
||||
outstate.window = {}
|
||||
outstate.window_pos = 1
|
||||
return outstate
|
||||
end
|
||||
|
||||
|
||||
local function output(outstate, byte)
|
||||
-- debug('OUTPUT:', s)
|
||||
local window_pos = outstate.window_pos
|
||||
outstate.outbs(byte)
|
||||
outstate.window[window_pos] = byte
|
||||
outstate.window_pos = window_pos % 32768 + 1 -- 32K
|
||||
end
|
||||
|
||||
|
||||
local function noeof(val)
|
||||
return assert(val, 'unexpected end of file')
|
||||
end
|
||||
|
||||
|
||||
local function hasbit(bits, bit)
|
||||
return bits % (bit + bit) >= bit
|
||||
end
|
||||
|
||||
|
||||
local function memoize(f)
|
||||
local mt = {}
|
||||
local t = setmetatable({}, mt)
|
||||
function mt:__index(k)
|
||||
local v = f(k)
|
||||
t[k] = v
|
||||
return v
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
-- small optimization (lookup table for powers of 2)
|
||||
local pow2 = memoize(function(n) return 2^n end)
|
||||
|
||||
--local tbits = memoize(
|
||||
-- function(bits)
|
||||
-- return memoize( function(bit) return getbit(bits, bit) end )
|
||||
-- end )
|
||||
|
||||
|
||||
-- weak metatable marking objects as bitstream type
|
||||
local is_bitstream = setmetatable({}, {__mode='k'})
|
||||
|
||||
|
||||
-- DEBUG
|
||||
-- prints LSB first
|
||||
--[[
|
||||
local function bits_tostring(bits, nbits)
|
||||
local s = ''
|
||||
local tmp = bits
|
||||
local function f()
|
||||
local b = tmp % 2 == 1 and 1 or 0
|
||||
s = s .. b
|
||||
tmp = (tmp - b) / 2
|
||||
end
|
||||
if nbits then
|
||||
for i=1,nbits do f() end
|
||||
else
|
||||
while tmp ~= 0 do f() end
|
||||
end
|
||||
|
||||
return s
|
||||
end
|
||||
--]]
|
||||
|
||||
local function bytestream_from_file(fh)
|
||||
local o = {}
|
||||
function o:read()
|
||||
local sb = fh:read(1)
|
||||
if sb then return sb:byte() end
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
|
||||
local function bytestream_from_string(s)
|
||||
local i = 1
|
||||
local o = {}
|
||||
function o:read()
|
||||
local by
|
||||
if i <= #s then
|
||||
by = s:byte(i)
|
||||
i = i + 1
|
||||
end
|
||||
return by
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
|
||||
local function bytestream_from_function(f)
|
||||
local i = 0
|
||||
local buffer = ''
|
||||
local o = {}
|
||||
function o:read()
|
||||
i = i + 1
|
||||
if i > #buffer then
|
||||
buffer = f()
|
||||
if not buffer then return end
|
||||
i = 1
|
||||
end
|
||||
return buffer:byte(i,i)
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
|
||||
local function bitstream_from_bytestream(bys)
|
||||
local buf_byte = 0
|
||||
local buf_nbit = 0
|
||||
local o = {}
|
||||
|
||||
function o:nbits_left_in_byte()
|
||||
return buf_nbit
|
||||
end
|
||||
|
||||
if NATIVE_BITOPS then
|
||||
function o:read(nbits)
|
||||
nbits = nbits or 1
|
||||
while buf_nbit < nbits do
|
||||
local byte = bys:read()
|
||||
if not byte then return end -- note: more calls also return nil
|
||||
buf_byte = buf_byte + lshift(byte, buf_nbit)
|
||||
buf_nbit = buf_nbit + 8
|
||||
end
|
||||
local bits
|
||||
if nbits == 0 then
|
||||
bits = 0
|
||||
elseif nbits == 32 then
|
||||
bits = buf_byte
|
||||
buf_byte = 0
|
||||
else
|
||||
bits = band(buf_byte, rshift(0xffffffff, 32 - nbits))
|
||||
buf_byte = rshift(buf_byte, nbits)
|
||||
end
|
||||
buf_nbit = buf_nbit - nbits
|
||||
return bits
|
||||
end
|
||||
else
|
||||
function o:read(nbits)
|
||||
nbits = nbits or 1
|
||||
while buf_nbit < nbits do
|
||||
local byte = bys:read()
|
||||
if not byte then return end -- note: more calls also return nil
|
||||
buf_byte = buf_byte + pow2[buf_nbit] * byte
|
||||
buf_nbit = buf_nbit + 8
|
||||
end
|
||||
local m = pow2[nbits]
|
||||
local bits = buf_byte % m
|
||||
buf_byte = (buf_byte - bits) / m
|
||||
buf_nbit = buf_nbit - nbits
|
||||
return bits
|
||||
end
|
||||
end
|
||||
|
||||
is_bitstream[o] = true
|
||||
|
||||
return o
|
||||
end
|
||||
|
||||
|
||||
local function get_bitstream(o)
|
||||
local bs
|
||||
if is_bitstream[o] then
|
||||
return o
|
||||
-- elseif io.type(o) == 'file' then
|
||||
-- bs = bitstream_from_bytestream(bytestream_from_file(o))
|
||||
elseif type(o) == 'string' then
|
||||
bs = bitstream_from_bytestream(bytestream_from_string(o))
|
||||
elseif type(o) == 'function' then
|
||||
bs = bitstream_from_bytestream(bytestream_from_function(o))
|
||||
else
|
||||
runtime_error 'unrecognized type'
|
||||
end
|
||||
return bs
|
||||
end
|
||||
|
||||
|
||||
local function get_obytestream(o)
|
||||
local bs
|
||||
if type(o) == 'function' then
|
||||
bs = o
|
||||
-- elseif io.type(o) == 'file' then
|
||||
-- bs = function(sbyte) o:write(string_char(sbyte)) end
|
||||
else
|
||||
runtime_error('unrecognized type: ' .. tostring(o))
|
||||
end
|
||||
return bs
|
||||
end
|
||||
|
||||
|
||||
local function HuffmanTable(init, is_full)
|
||||
local t = {}
|
||||
if is_full then
|
||||
for val,nbits in pairs(init) do
|
||||
if nbits ~= 0 then
|
||||
t[#t+1] = {val=val, nbits=nbits}
|
||||
--debug('*',val,nbits)
|
||||
end
|
||||
end
|
||||
else
|
||||
for i=1,#init-2,2 do
|
||||
local firstval, nbits, nextval = init[i], init[i+1], init[i+2]
|
||||
--debug(val, nextval, nbits)
|
||||
if nbits ~= 0 then
|
||||
for val=firstval,nextval-1 do
|
||||
t[#t+1] = {val=val, nbits=nbits}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table_sort(t, function(a,b)
|
||||
return a.nbits == b.nbits and a.val < b.val or a.nbits < b.nbits
|
||||
end)
|
||||
|
||||
-- assign codes
|
||||
local code = 1 -- leading 1 marker
|
||||
local nbits = 0
|
||||
for i,s in ipairs(t) do
|
||||
if s.nbits ~= nbits then
|
||||
code = code * pow2[s.nbits - nbits]
|
||||
nbits = s.nbits
|
||||
end
|
||||
s.code = code
|
||||
--debug('huffman code:', i, s.nbits, s.val, code, bits_tostring(code))
|
||||
code = code + 1
|
||||
end
|
||||
|
||||
local minbits = math.huge
|
||||
local look = {}
|
||||
for i,s in ipairs(t) do
|
||||
minbits = math.min(minbits, s.nbits)
|
||||
look[s.code] = s.val
|
||||
end
|
||||
|
||||
--for _,o in ipairs(t) do
|
||||
-- debug(':', o.nbits, o.val)
|
||||
--end
|
||||
|
||||
-- function t:lookup(bits) return look[bits] end
|
||||
|
||||
local msb = NATIVE_BITOPS and function(bits, nbits)
|
||||
local res = 0
|
||||
for i=1,nbits do
|
||||
res = lshift(res, 1) + band(bits, 1)
|
||||
bits = rshift(bits, 1)
|
||||
end
|
||||
return res
|
||||
end or function(bits, nbits)
|
||||
local res = 0
|
||||
for i=1,nbits do
|
||||
local b = bits % 2
|
||||
bits = (bits - b) / 2
|
||||
res = res * 2 + b
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
local tfirstcode = memoize(
|
||||
function(bits) return pow2[minbits] + msb(bits, minbits) end)
|
||||
|
||||
function t:read(bs)
|
||||
local code = 1 -- leading 1 marker
|
||||
local nbits = 0
|
||||
while 1 do
|
||||
if nbits == 0 then -- small optimization (optional)
|
||||
code = tfirstcode[noeof(bs:read(minbits))]
|
||||
nbits = nbits + minbits
|
||||
else
|
||||
local b = noeof(bs:read())
|
||||
nbits = nbits + 1
|
||||
code = code * 2 + b -- MSB first
|
||||
--[[NATIVE_BITOPS
|
||||
code = lshift(code, 1) + b -- MSB first
|
||||
--]]
|
||||
end
|
||||
--debug('code?', code, bits_tostring(code))
|
||||
local val = look[code]
|
||||
if val then
|
||||
--debug('FOUND', val)
|
||||
return val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
local function parse_gzip_header(bs)
|
||||
-- local FLG_FTEXT = 2^0
|
||||
local FLG_FHCRC = 2^1
|
||||
local FLG_FEXTRA = 2^2
|
||||
local FLG_FNAME = 2^3
|
||||
local FLG_FCOMMENT = 2^4
|
||||
|
||||
local id1 = bs:read(8)
|
||||
local id2 = bs:read(8)
|
||||
if id1 ~= 31 or id2 ~= 139 then
|
||||
runtime_error 'not in gzip format'
|
||||
end
|
||||
local cm = bs:read(8) -- compression method
|
||||
local flg = bs:read(8) -- FLaGs
|
||||
local mtime = bs:read(32) -- Modification TIME
|
||||
local xfl = bs:read(8) -- eXtra FLags
|
||||
local os = bs:read(8) -- Operating System
|
||||
|
||||
if DEBUG then
|
||||
debug("CM=", cm)
|
||||
debug("FLG=", flg)
|
||||
debug("MTIME=", mtime)
|
||||
-- debug("MTIME_str=",os.date("%Y-%m-%d %H:%M:%S",mtime)) -- non-portable
|
||||
debug("XFL=", xfl)
|
||||
debug("OS=", os)
|
||||
end
|
||||
|
||||
if not os then runtime_error 'invalid header' end
|
||||
|
||||
if hasbit(flg, FLG_FEXTRA) then
|
||||
local xlen = bs:read(16)
|
||||
local extra = 0
|
||||
for i=1,xlen do
|
||||
extra = bs:read(8)
|
||||
end
|
||||
if not extra then runtime_error 'invalid header' end
|
||||
end
|
||||
|
||||
local function parse_zstring(bs)
|
||||
repeat
|
||||
local by = bs:read(8)
|
||||
if not by then runtime_error 'invalid header' end
|
||||
until by == 0
|
||||
end
|
||||
|
||||
if hasbit(flg, FLG_FNAME) then
|
||||
parse_zstring(bs)
|
||||
end
|
||||
|
||||
if hasbit(flg, FLG_FCOMMENT) then
|
||||
parse_zstring(bs)
|
||||
end
|
||||
|
||||
if hasbit(flg, FLG_FHCRC) then
|
||||
local crc16 = bs:read(16)
|
||||
if not crc16 then runtime_error 'invalid header' end
|
||||
-- IMPROVE: check CRC. where is an example .gz file that
|
||||
-- has this set?
|
||||
if DEBUG then
|
||||
debug("CRC16=", crc16)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function parse_zlib_header(bs)
|
||||
local cm = bs:read(4) -- Compression Method
|
||||
local cinfo = bs:read(4) -- Compression info
|
||||
local fcheck = bs:read(5) -- FLaGs: FCHECK (check bits for CMF and FLG)
|
||||
local fdict = bs:read(1) -- FLaGs: FDICT (present dictionary)
|
||||
local flevel = bs:read(2) -- FLaGs: FLEVEL (compression level)
|
||||
local cmf = cinfo * 16 + cm -- CMF (Compresion Method and flags)
|
||||
local flg = fcheck + fdict * 32 + flevel * 64 -- FLaGs
|
||||
|
||||
if cm ~= 8 then -- not "deflate"
|
||||
runtime_error("unrecognized zlib compression method: " + cm)
|
||||
end
|
||||
if cinfo > 7 then
|
||||
runtime_error("invalid zlib window size: cinfo=" + cinfo)
|
||||
end
|
||||
local window_size = 2^(cinfo + 8)
|
||||
|
||||
if (cmf*256 + flg) % 31 ~= 0 then
|
||||
runtime_error("invalid zlib header (bad fcheck sum)")
|
||||
end
|
||||
|
||||
if fdict == 1 then
|
||||
runtime_error("FIX:TODO - FDICT not currently implemented")
|
||||
local dictid_ = bs:read(32)
|
||||
end
|
||||
|
||||
return window_size
|
||||
end
|
||||
|
||||
local function parse_huffmantables(bs)
|
||||
local hlit = bs:read(5) -- # of literal/length codes - 257
|
||||
local hdist = bs:read(5) -- # of distance codes - 1
|
||||
local hclen = noeof(bs:read(4)) -- # of code length codes - 4
|
||||
|
||||
local ncodelen_codes = hclen + 4
|
||||
local codelen_init = {}
|
||||
local codelen_vals = {
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
|
||||
for i=1,ncodelen_codes do
|
||||
local nbits = bs:read(3)
|
||||
local val = codelen_vals[i]
|
||||
codelen_init[val] = nbits
|
||||
end
|
||||
local codelentable = HuffmanTable(codelen_init, true)
|
||||
|
||||
local function decode(ncodes)
|
||||
local init = {}
|
||||
local nbits
|
||||
local val = 0
|
||||
while val < ncodes do
|
||||
local codelen = codelentable:read(bs)
|
||||
--FIX:check nil?
|
||||
local nrepeat
|
||||
if codelen <= 15 then
|
||||
nrepeat = 1
|
||||
nbits = codelen
|
||||
--debug('w', nbits)
|
||||
elseif codelen == 16 then
|
||||
nrepeat = 3 + noeof(bs:read(2))
|
||||
-- nbits unchanged
|
||||
elseif codelen == 17 then
|
||||
nrepeat = 3 + noeof(bs:read(3))
|
||||
nbits = 0
|
||||
elseif codelen == 18 then
|
||||
nrepeat = 11 + noeof(bs:read(7))
|
||||
nbits = 0
|
||||
else
|
||||
error 'ASSERT'
|
||||
end
|
||||
for i=1,nrepeat do
|
||||
init[val] = nbits
|
||||
val = val + 1
|
||||
end
|
||||
end
|
||||
local huffmantable = HuffmanTable(init, true)
|
||||
return huffmantable
|
||||
end
|
||||
|
||||
local nlit_codes = hlit + 257
|
||||
local ndist_codes = hdist + 1
|
||||
|
||||
local littable = decode(nlit_codes)
|
||||
local disttable = decode(ndist_codes)
|
||||
|
||||
return littable, disttable
|
||||
end
|
||||
|
||||
|
||||
local tdecode_len_base
|
||||
local tdecode_len_nextrabits
|
||||
local tdecode_dist_base
|
||||
local tdecode_dist_nextrabits
|
||||
local function parse_compressed_item(bs, outstate, littable, disttable)
|
||||
local val = littable:read(bs)
|
||||
--debug(val, val < 256 and string_char(val))
|
||||
if val < 256 then -- literal
|
||||
output(outstate, val)
|
||||
elseif val == 256 then -- end of block
|
||||
return true
|
||||
else
|
||||
if not tdecode_len_base then
|
||||
local t = {[257]=3}
|
||||
local skip = 1
|
||||
for i=258,285,4 do
|
||||
for j=i,i+3 do t[j] = t[j-1] + skip end
|
||||
if i ~= 258 then skip = skip * 2 end
|
||||
end
|
||||
t[285] = 258
|
||||
tdecode_len_base = t
|
||||
--for i=257,285 do debug('T1',i,t[i]) end
|
||||
end
|
||||
if not tdecode_len_nextrabits then
|
||||
local t = {}
|
||||
if NATIVE_BITOPS then
|
||||
for i=257,285 do
|
||||
local j = math_max(i - 261, 0)
|
||||
t[i] = rshift(j, 2)
|
||||
end
|
||||
else
|
||||
for i=257,285 do
|
||||
local j = math_max(i - 261, 0)
|
||||
t[i] = (j - (j % 4)) / 4
|
||||
end
|
||||
end
|
||||
t[285] = 0
|
||||
tdecode_len_nextrabits = t
|
||||
--for i=257,285 do debug('T2',i,t[i]) end
|
||||
end
|
||||
local len_base = tdecode_len_base[val]
|
||||
local nextrabits = tdecode_len_nextrabits[val]
|
||||
local extrabits = bs:read(nextrabits)
|
||||
local len = len_base + extrabits
|
||||
|
||||
if not tdecode_dist_base then
|
||||
local t = {[0]=1}
|
||||
local skip = 1
|
||||
for i=1,29,2 do
|
||||
for j=i,i+1 do t[j] = t[j-1] + skip end
|
||||
if i ~= 1 then skip = skip * 2 end
|
||||
end
|
||||
tdecode_dist_base = t
|
||||
--for i=0,29 do debug('T3',i,t[i]) end
|
||||
end
|
||||
if not tdecode_dist_nextrabits then
|
||||
local t = {}
|
||||
if NATIVE_BITOPS then
|
||||
for i=0,29 do
|
||||
local j = math_max(i - 2, 0)
|
||||
t[i] = rshift(j, 1)
|
||||
end
|
||||
else
|
||||
for i=0,29 do
|
||||
local j = math_max(i - 2, 0)
|
||||
t[i] = (j - (j % 2)) / 2
|
||||
end
|
||||
end
|
||||
tdecode_dist_nextrabits = t
|
||||
--for i=0,29 do debug('T4',i,t[i]) end
|
||||
end
|
||||
local dist_val = disttable:read(bs)
|
||||
local dist_base = tdecode_dist_base[dist_val]
|
||||
local dist_nextrabits = tdecode_dist_nextrabits[dist_val]
|
||||
local dist_extrabits = bs:read(dist_nextrabits)
|
||||
local dist = dist_base + dist_extrabits
|
||||
|
||||
--debug('BACK', len, dist)
|
||||
for i=1,len do
|
||||
local pos = (outstate.window_pos - 1 - dist) % 32768 + 1 -- 32K
|
||||
output(outstate, assert(outstate.window[pos], 'invalid distance'))
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
local function parse_block(bs, outstate)
|
||||
local bfinal = bs:read(1)
|
||||
local btype = bs:read(2)
|
||||
|
||||
local BTYPE_NO_COMPRESSION = 0
|
||||
local BTYPE_FIXED_HUFFMAN = 1
|
||||
local BTYPE_DYNAMIC_HUFFMAN = 2
|
||||
local BTYPE_RESERVED_ = 3
|
||||
|
||||
if DEBUG then
|
||||
debug('bfinal=', bfinal)
|
||||
debug('btype=', btype)
|
||||
end
|
||||
|
||||
if btype == BTYPE_NO_COMPRESSION then
|
||||
bs:read(bs:nbits_left_in_byte())
|
||||
local len = bs:read(16)
|
||||
local nlen_ = noeof(bs:read(16))
|
||||
|
||||
for i=1,len do
|
||||
local by = noeof(bs:read(8))
|
||||
output(outstate, by)
|
||||
end
|
||||
elseif btype == BTYPE_FIXED_HUFFMAN or btype == BTYPE_DYNAMIC_HUFFMAN then
|
||||
local littable, disttable
|
||||
if btype == BTYPE_DYNAMIC_HUFFMAN then
|
||||
littable, disttable = parse_huffmantables(bs)
|
||||
else
|
||||
littable = HuffmanTable {0,8, 144,9, 256,7, 280,8, 288,nil}
|
||||
disttable = HuffmanTable {0,5, 32,nil}
|
||||
end
|
||||
|
||||
repeat
|
||||
local is_done = parse_compressed_item(
|
||||
bs, outstate, littable, disttable)
|
||||
until is_done
|
||||
else
|
||||
runtime_error 'unrecognized compression type'
|
||||
end
|
||||
|
||||
return bfinal ~= 0
|
||||
end
|
||||
|
||||
|
||||
function M.inflate(t)
|
||||
local bs = get_bitstream(t.input)
|
||||
local outbs = get_obytestream(t.output)
|
||||
local outstate = make_outstate(outbs)
|
||||
|
||||
repeat
|
||||
local is_final = parse_block(bs, outstate)
|
||||
until is_final
|
||||
end
|
||||
local inflate = M.inflate
|
||||
|
||||
|
||||
function M.gunzip(t)
|
||||
local bs = get_bitstream(t.input)
|
||||
local outbs = get_obytestream(t.output)
|
||||
local disable_crc = t.disable_crc
|
||||
if disable_crc == nil then disable_crc = false end
|
||||
|
||||
parse_gzip_header(bs)
|
||||
|
||||
local data_crc32 = 0
|
||||
|
||||
inflate{input=bs, output=
|
||||
disable_crc and outbs or
|
||||
function(byte)
|
||||
data_crc32 = crc32(byte, data_crc32)
|
||||
outbs(byte)
|
||||
end
|
||||
}
|
||||
|
||||
bs:read(bs:nbits_left_in_byte())
|
||||
|
||||
local expected_crc32 = bs:read(32)
|
||||
local isize = bs:read(32) -- ignored
|
||||
if DEBUG then
|
||||
debug('crc32=', expected_crc32)
|
||||
debug('isize=', isize)
|
||||
end
|
||||
if not disable_crc and data_crc32 then
|
||||
if data_crc32 ~= expected_crc32 then
|
||||
runtime_error('invalid compressed data--crc error')
|
||||
end
|
||||
end
|
||||
if bs:read() then
|
||||
warn 'trailing garbage ignored'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M.adler32(byte, crc)
|
||||
local s1 = crc % 65536
|
||||
local s2 = (crc - s1) / 65536
|
||||
s1 = (s1 + byte) % 65521
|
||||
s2 = (s2 + s1) % 65521
|
||||
return s2*65536 + s1
|
||||
end -- 65521 is the largest prime smaller than 2^16
|
||||
|
||||
|
||||
function M.inflate_zlib(t)
|
||||
local bs = get_bitstream(t.input)
|
||||
local outbs = get_obytestream(t.output)
|
||||
local disable_crc = t.disable_crc
|
||||
if disable_crc == nil then disable_crc = false end
|
||||
|
||||
local window_size_ = parse_zlib_header(bs)
|
||||
|
||||
local data_adler32 = 1
|
||||
|
||||
inflate{input=bs, output=
|
||||
disable_crc and outbs or
|
||||
function(byte)
|
||||
data_adler32 = M.adler32(byte, data_adler32)
|
||||
outbs(byte)
|
||||
end
|
||||
}
|
||||
|
||||
bs:read(bs:nbits_left_in_byte())
|
||||
|
||||
local b3 = bs:read(8)
|
||||
local b2 = bs:read(8)
|
||||
local b1 = bs:read(8)
|
||||
local b0 = bs:read(8)
|
||||
local expected_adler32 = ((b3*256 + b2)*256 + b1)*256 + b0
|
||||
if DEBUG then
|
||||
debug('alder32=', expected_adler32)
|
||||
end
|
||||
if not disable_crc then
|
||||
if data_adler32 ~= expected_adler32 then
|
||||
runtime_error('invalid compressed data--crc error')
|
||||
end
|
||||
end
|
||||
if bs:read() then
|
||||
warn 'trailing garbage ignored'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return M
|
@ -1,144 +0,0 @@
|
||||
local n, v = "serpent", 0.272 -- (C) 2012-13 Paul Kulchenko; MIT License
|
||||
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
|
||||
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
|
||||
local badtype = {thread = true, userdata = true, cdata = true}
|
||||
local keyword, globals, G = {}, {}, (_G or _ENV)
|
||||
for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false',
|
||||
'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
|
||||
'return', 'then', 'true', 'until', 'while'}) do keyword[k] = true end
|
||||
for k,v in pairs(G) do globals[v] = k end -- build func to name mapping
|
||||
for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'}) do
|
||||
for k,v in pairs(G[g] or {}) do globals[v] = g..'.'..k end end
|
||||
|
||||
local function s(t, opts)
|
||||
local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
|
||||
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
|
||||
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
|
||||
local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge)
|
||||
local seen, sref, syms, symn = {}, {'local '..iname..'={}'}, {}, 0
|
||||
local function gensym(val) return '_'..(tostring(tostring(val)):gsub("[^%w]",""):gsub("(%d%w+)",
|
||||
-- tostring(val) is needed because __tostring may return a non-string value
|
||||
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return syms[s] end)) end
|
||||
local function safestr(s) return type(s) == "number" and (huge and snum[tostring(s)] or s)
|
||||
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
|
||||
or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
|
||||
local function comment(s,l) return comm and (l or 0) < comm and ' --[['..tostring(s)..']]' or '' end
|
||||
local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
|
||||
and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end
|
||||
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
|
||||
local n = name == nil and '' or name
|
||||
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
|
||||
local safe = plain and n or '['..safestr(n)..']'
|
||||
return (path or '')..(plain and path and '.' or '')..safe, safe end
|
||||
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(k, o, n) -- k=keys, o=originaltable, n=padding
|
||||
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
|
||||
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
|
||||
table.sort(k, function(a,b)
|
||||
-- sort numeric keys first: k[key] is not nil for numerical keys
|
||||
return (k[a] ~= nil and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
|
||||
< (k[b] ~= nil and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
|
||||
local function val2str(t, name, indent, insref, path, plainindex, level)
|
||||
local ttype, level, mt = type(t), (level or 0), getmetatable(t)
|
||||
local spath, sname = safename(path, name)
|
||||
local tag = plainindex and
|
||||
((type(name) == "number") and '' or name..space..'='..space) or
|
||||
(name ~= nil and sname..space..'='..space or '')
|
||||
if seen[t] then -- already seen this element
|
||||
sref[#sref+1] = spath..space..'='..space..seen[t]
|
||||
return tag..'nil'..comment('ref', level) end
|
||||
if type(mt) == 'table' and (mt.__serialize or mt.__tostring) then -- knows how to serialize itself
|
||||
seen[t] = insref or spath
|
||||
if mt.__serialize then t = mt.__serialize(t) else t = tostring(t) end
|
||||
ttype = type(t) end -- new value falls through to be serialized
|
||||
if ttype == "table" then
|
||||
if level >= maxl then return tag..'{}'..comment('max', level) end
|
||||
seen[t] = insref or spath
|
||||
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
|
||||
local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
|
||||
for key = 1, maxn do o[key] = key end
|
||||
if not maxnum or #o < maxnum then
|
||||
local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
|
||||
for key in pairs(t) do if o[key] ~= key then n = n + 1; o[n] = key end end end
|
||||
if maxnum and #o > maxnum then o[maxnum+1] = nil end
|
||||
if opts.sortkeys and #o > maxn then alphanumsort(o, t, opts.sortkeys) end
|
||||
local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
|
||||
for n, key in ipairs(o) do
|
||||
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
|
||||
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
|
||||
or opts.keyallow and not opts.keyallow[key]
|
||||
or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
|
||||
or sparse and value == nil then -- skipping nils; do nothing
|
||||
elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
|
||||
if not seen[key] and not globals[key] then
|
||||
sref[#sref+1] = 'placeholder'
|
||||
local sname = safename(iname, gensym(key)) -- iname is table for local variables
|
||||
sref[#sref] = val2str(key,sname,indent,sname,iname,true) end
|
||||
sref[#sref+1] = 'placeholder'
|
||||
local path = seen[t]..'['..(seen[key] or globals[key] or gensym(key))..']'
|
||||
sref[#sref] = path..space..'='..space..(seen[value] or val2str(value,nil,indent,path))
|
||||
else
|
||||
out[#out+1] = val2str(value,key,indent,insref,seen[t],plainindex,level+1)
|
||||
end
|
||||
end
|
||||
local prefix = string.rep(indent or '', level)
|
||||
local head = indent and '{\n'..prefix..indent or '{'
|
||||
local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space))
|
||||
local tail = indent and "\n"..prefix..'}' or '}'
|
||||
return (custom and custom(tag,head,body,tail) or tag..head..body..tail)..comment(t, level)
|
||||
elseif badtype[ttype] then
|
||||
seen[t] = insref or spath
|
||||
return tag..globerr(t, level)
|
||||
elseif ttype == 'function' then
|
||||
seen[t] = insref or spath
|
||||
local ok, res = pcall(string.dump, t)
|
||||
local func = ok and ((opts.nocode and "function() --[[..skipped..]] end" or
|
||||
"((loadstring or load)("..safestr(res)..",'@serialized'))")..comment(t, level))
|
||||
return tag..(func or globerr(t, level))
|
||||
else return tag..safestr(t) end -- handle all other types
|
||||
end
|
||||
local sepr = indent and "\n" or ";"..space
|
||||
local body = val2str(t, name, indent) -- this call also populates sref
|
||||
local tail = #sref>1 and table.concat(sref, sepr)..sepr or ''
|
||||
local warn = opts.comment and #sref>1 and space.."--[[incomplete output with shared/self-references skipped]]" or ''
|
||||
return not name and body..warn or "do local "..body..sepr..tail.."return "..name..sepr.."end"
|
||||
end
|
||||
|
||||
local function deserialize(data, opts)
|
||||
--local f, res = (loadstring or load)('return '..data)
|
||||
--if not f then f, res = (loadstring or load)(data) end
|
||||
-- Isolated env added by David McWilliams
|
||||
local f, res = load(data,nil,"t",{})
|
||||
if not f then return f, res end
|
||||
if opts and opts.safe == false then return pcall(f) end
|
||||
|
||||
local count, thread = 0, coroutine.running()
|
||||
local h, m, c = debug.gethook(thread)
|
||||
--debug.sethook(function (e, l) count = count + 1
|
||||
-- if count >= 3 then error("cannot call functions") end
|
||||
--end, "c")
|
||||
-- Timeout check added by David McWilliams
|
||||
local linecount = 0
|
||||
debug.sethook(function (e, l)
|
||||
if (e == "call") then
|
||||
count = count + 1
|
||||
if count >= 3 then error("cannot call functions") end
|
||||
elseif (e == "line") then
|
||||
linecount = linecount + 1
|
||||
if linecount > 999999 then
|
||||
linecount = 0 -- set again, to give us time to remove the hook
|
||||
error("timeout")
|
||||
end
|
||||
end
|
||||
end, "cl")
|
||||
local res = {pcall(f)}
|
||||
count = 0 -- set again, otherwise it's tripped on the next sethook
|
||||
debug.sethook(thread, h, m, c)
|
||||
return (table.unpack or unpack)(res)
|
||||
end
|
||||
|
||||
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
|
||||
return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s,
|
||||
load = deserialize,
|
||||
dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end,
|
||||
line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end,
|
||||
block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end }
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +0,0 @@
|
||||
main-button=Blueprint
|
||||
save=Save
|
||||
save-as=Save as:
|
||||
cancel=Cancel
|
||||
textbox-caption=Blueprint String:
|
||||
blueprints-saved=__1__ blueprints saved to 'script-output/blueprint-string'
|
||||
blueprint-saved-as=__1__.txt saved to 'script-output/blueprint-string'
|
||||
blueprints-not-saved=Could not find any blueprints to save.
|
||||
no-empty-blueprint=You do not have any empty blueprints.
|
||||
unknown-format=That is not a blueprint string.
|
||||
no-string=Please paste a blueprint string in the text box.
|
||||
no-filename=Please enter a file name for this blueprint.
|
||||
no-blueprint-in-hand=Please click this button while holding a blueprint.
|
||||
blueprint-api-error=Blueprint error: __1__
|
||||
blueprint-icon-error=Blueprint icon error: __1__
|
||||
need-advanced-circuit=You need __1__ advanced circuit.
|
||||
need-blueprint=You need a blueprint to load that.
|
||||
need-blueprint-book=You need a blueprint book to load that.
|
@ -1,269 +0,0 @@
|
||||
--[[------------------------------------
|
||||
RandomLua v0.3.1
|
||||
Pure Lua Pseudo-Random Numbers Generator
|
||||
Under the MIT license.
|
||||
copyright(c) 2011 linux-man
|
||||
--]]------------------------------------
|
||||
|
||||
local _M = {}
|
||||
local mod = math.fmod
|
||||
local floor = math.floor
|
||||
local abs = math.abs
|
||||
|
||||
local function normalize(n) --keep numbers at (positive) 32 bits
|
||||
return n % 0x80000000
|
||||
end
|
||||
|
||||
local function bit_and(a, b)
|
||||
local r = 0
|
||||
local m = 0
|
||||
for m = 0, 31 do
|
||||
if (a % 2 == 1) and (b % 2 == 1) then r = r + 2^m end
|
||||
if a % 2 ~= 0 then a = a - 1 end
|
||||
if b % 2 ~= 0 then b = b - 1 end
|
||||
a = a / 2 b = b / 2
|
||||
end
|
||||
return normalize(r)
|
||||
end
|
||||
|
||||
local function bit_or(a, b)
|
||||
local r = 0
|
||||
local m = 0
|
||||
for m = 0, 31 do
|
||||
if (a % 2 == 1) or (b % 2 == 1) then r = r + 2^m end
|
||||
if a % 2 ~= 0 then a = a - 1 end
|
||||
if b % 2 ~= 0 then b = b - 1 end
|
||||
a = a / 2 b = b / 2
|
||||
end
|
||||
return normalize(r)
|
||||
end
|
||||
|
||||
local function bit_xor(a, b)
|
||||
local r = 0
|
||||
local m = 0
|
||||
for m = 0, 31 do
|
||||
if a % 2 ~= b % 2 then r = r + 2^m end
|
||||
if a % 2 ~= 0 then a = a - 1 end
|
||||
if b % 2 ~= 0 then b = b - 1 end
|
||||
a = a / 2 b = b / 2
|
||||
end
|
||||
return normalize(r)
|
||||
end
|
||||
|
||||
local function seed()
|
||||
--return normalize(tonumber(tostring(os.time()):reverse()))
|
||||
return normalize(os.time())
|
||||
end
|
||||
|
||||
--Mersenne twister
|
||||
mersenne_twister = {}
|
||||
mersenne_twister.__index = mersenne_twister
|
||||
|
||||
function mersenne_twister:randomseed(s)
|
||||
if not s then s = seed() end
|
||||
self.mt[0] = normalize(s)
|
||||
for i = 1, 623 do
|
||||
self.mt[i] = normalize(0x6c078965 * bit_xor(self.mt[i-1], floor(self.mt[i-1] / 0x40000000)) + i)
|
||||
end
|
||||
end
|
||||
|
||||
function mersenne_twister:random(a, b)
|
||||
local y
|
||||
if self.index == 0 then
|
||||
for i = 0, 623 do
|
||||
--y = bit_or(floor(self.mt[i] / 0x80000000) * 0x80000000, self.mt[(i + 1) % 624] % 0x80000000)
|
||||
y = self.mt[(i + 1) % 624] % 0x80000000
|
||||
self.mt[i] = bit_xor(self.mt[(i + 397) % 624], floor(y / 2))
|
||||
if y % 2 ~= 0 then self.mt[i] = bit_xor(self.mt[i], 0x9908b0df) end
|
||||
end
|
||||
end
|
||||
y = self.mt[self.index]
|
||||
y = bit_xor(y, floor(y / 0x800))
|
||||
y = bit_xor(y, bit_and(normalize(y * 0x80), 0x9d2c5680))
|
||||
y = bit_xor(y, bit_and(normalize(y * 0x8000), 0xefc60000))
|
||||
y = bit_xor(y, floor(y / 0x40000))
|
||||
self.index = (self.index + 1) % 624
|
||||
if not a then return y / 0x80000000
|
||||
elseif not b then
|
||||
if a == 0 then return y
|
||||
else return 1 + (y % a)
|
||||
end
|
||||
else
|
||||
return a + (y % (b - a + 1))
|
||||
end
|
||||
end
|
||||
|
||||
function _M.twister(s)
|
||||
local temp = {}
|
||||
setmetatable(temp, mersenne_twister)
|
||||
temp.mt = {}
|
||||
temp.index = 0
|
||||
temp:randomseed(s)
|
||||
return temp
|
||||
end
|
||||
|
||||
--Linear Congruential Generator
|
||||
linear_congruential_generator = {}
|
||||
linear_congruential_generator.__index = linear_congruential_generator
|
||||
|
||||
function linear_congruential_generator:random(a, b)
|
||||
local y = (self.a * self.x + self.c) % self.m
|
||||
self.x = y
|
||||
if not a then return y / 0x10000
|
||||
elseif not b then
|
||||
if a == 0 then return y
|
||||
else return 1 + (y % a) end
|
||||
else
|
||||
return a + (y % (b - a + 1))
|
||||
end
|
||||
end
|
||||
|
||||
function linear_congruential_generator:randomseed(s)
|
||||
if not s then s = seed() end
|
||||
self.x = normalize(s)
|
||||
end
|
||||
|
||||
function _M.lcg(s, r)
|
||||
local temp = {}
|
||||
setmetatable(temp, linear_congruential_generator)
|
||||
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
|
||||
if r then
|
||||
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
|
||||
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
|
||||
end
|
||||
temp:randomseed(s)
|
||||
return temp
|
||||
end
|
||||
|
||||
-- Multiply-with-carry
|
||||
multiply_with_carry = {}
|
||||
multiply_with_carry.__index = multiply_with_carry
|
||||
|
||||
function multiply_with_carry:random(a, b)
|
||||
local m = self.m
|
||||
local t = self.a * self.x + self.c
|
||||
local y = t % m
|
||||
self.x = y
|
||||
self.c = floor(t / m)
|
||||
if not a then return y / 0x10000
|
||||
elseif not b then
|
||||
if a == 0 then return y
|
||||
else return 1 + (y % a) end
|
||||
else
|
||||
local diff = 0
|
||||
if a == b then return a end
|
||||
if a < 0 then
|
||||
diff = abs(a)
|
||||
a = a + diff
|
||||
b = b + diff
|
||||
end
|
||||
return a + (y % (b - a + 1)) - diff
|
||||
end
|
||||
end
|
||||
|
||||
function multiply_with_carry:randomseed(s)
|
||||
if not s then s = seed() end
|
||||
self.c = self.ic
|
||||
self.x = normalize(s)
|
||||
end
|
||||
|
||||
function _M.mwc(s, r)
|
||||
local temp = {}
|
||||
setmetatable(temp, multiply_with_carry)
|
||||
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
|
||||
if r then
|
||||
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
|
||||
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
|
||||
end
|
||||
temp.ic = temp.c
|
||||
temp:randomseed(s)
|
||||
return temp
|
||||
end
|
||||
|
||||
function _M.mwvc(s)
|
||||
return _M.mwc(s, 'mvc')
|
||||
end
|
||||
|
||||
local B = 0x10000
|
||||
|
||||
-- rough adaptation of Knuth float generator
|
||||
function _M.krandom( seedobj, fVal1, fVal2 )
|
||||
local ma = seedobj.ma
|
||||
local seed = seedobj.seed
|
||||
local mj, mk
|
||||
if seed < 0 or not ma then
|
||||
ma = {}
|
||||
seedobj.ma = ma
|
||||
mj = normalize( seed )
|
||||
mj = mod( mj, B )
|
||||
ma[55] = mj
|
||||
mk = 1
|
||||
for i = 1, 54 do
|
||||
local ii = mod( 21 * i, 55 )
|
||||
ma[ii] = mk
|
||||
mk = mj - mk
|
||||
if mk < 0 then mk = mk + B end
|
||||
mj = ma[ii]
|
||||
end
|
||||
for k = 1, 4 do
|
||||
for i = 1, 55 do
|
||||
ma[i] = ma[i] - ma[ 1 + mod( i + 30, 55) ]
|
||||
if ma[i] < 0 then ma[i] = ma[i] + B end
|
||||
end
|
||||
end
|
||||
seedobj.inext = 0
|
||||
seedobj.inextp = 31
|
||||
seedobj.seed = 1
|
||||
end -- if
|
||||
local inext = seedobj.inext
|
||||
local inextp = seedobj.inextp
|
||||
inext = inext + 1
|
||||
if inext == 56 then inext = 1 end
|
||||
seedobj.inext = inext
|
||||
inextp = inextp + 1
|
||||
if inextp == 56 then inextp = 1 end
|
||||
seedobj.inextp = inextp
|
||||
mj = ma[ inext ] - ma[ inextp ]
|
||||
if mj < 0 then mj = mj + B end
|
||||
ma[ inext ] = mj
|
||||
local temp_rand = mj / B
|
||||
if fVal2 then
|
||||
return floor( fVal1 + 0.5 + temp_rand * ( fVal2 - fVal1 ) )
|
||||
elseif fVal1 then
|
||||
return floor( temp_rand * fVal1 ) + 1
|
||||
else
|
||||
return temp_rand
|
||||
end
|
||||
end
|
||||
|
||||
-- Sys rand
|
||||
sys_rand = {}
|
||||
sys_rand.__index = sys_rand
|
||||
function sys_rand:random(a, b)
|
||||
local diff = 0
|
||||
if a and b and a == b then math.random(); return a end
|
||||
if a and b then
|
||||
if a < 0 then
|
||||
diff = abs(a)
|
||||
a = a + diff
|
||||
b = b + diff
|
||||
end
|
||||
return math.random(a, b) - diff
|
||||
end
|
||||
if a and a == 0 then return floor(math.random() * 0x10000) end
|
||||
if a then return math.random(a) end
|
||||
return math.random()
|
||||
end
|
||||
|
||||
function sys_rand:randomseed(s)
|
||||
-- ignore
|
||||
return
|
||||
end
|
||||
|
||||
function _M.sys_rand(s)
|
||||
local temp = {}
|
||||
setmetatable(temp, sys_rand)
|
||||
return temp
|
||||
end
|
||||
|
||||
return _M
|
@ -1,104 +0,0 @@
|
||||
--[[--
|
||||
Metaball implementation for LUA by Dark
|
||||
For bruteforce usage, not efficient nor fast
|
||||
|
||||
Force scales to from inf to 1 at R
|
||||
--]]--
|
||||
local _M = {}
|
||||
local sqrt = math.sqrt
|
||||
local cos = math.cos
|
||||
local sin = math.sin
|
||||
local abs = math.abs
|
||||
local zero_value = 0x80000000
|
||||
|
||||
--Classic ball
|
||||
local MetaBall = {x=0, y=0, radius=0, goo=1, type="MetaBall"}
|
||||
MetaBall.__index = MetaBall
|
||||
_M.MetaBall=MetaBall
|
||||
|
||||
function MetaBall:new(x, y, radius, goo)
|
||||
goo = goo or 1
|
||||
return setmetatable({x=x, y=y, radius=radius, goo=goo}, MetaBall)
|
||||
end
|
||||
|
||||
function MetaBall:force(x, y)
|
||||
--Calculate force at point x y
|
||||
local force = sqrt( (x - self.x)^2 + (y - self.y)^2 )
|
||||
if force == 0 then return zero_value end
|
||||
return (self.radius / force)^self.goo
|
||||
end
|
||||
|
||||
--Ellipse
|
||||
local MetaEllipse = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaEllipse"}
|
||||
MetaEllipse.__index = MetaEllipse
|
||||
_M.MetaEllipse=MetaEllipse
|
||||
|
||||
function MetaEllipse:new(x, y, radius, angle, x_scale, y_scale, goo)
|
||||
angle = angle or 0
|
||||
x_scale = x_scale or 1
|
||||
y_scale = y_scale or 1
|
||||
goo = goo or 1
|
||||
cosa = cos(angle)
|
||||
sina = sin(angle)
|
||||
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaEllipse)
|
||||
end
|
||||
|
||||
function MetaEllipse:force(x, y)
|
||||
--Calculate force at point x y
|
||||
local force = sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
|
||||
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) )
|
||||
if force == 0 then return zero_value end
|
||||
return (self.radius / force)^self.goo
|
||||
end
|
||||
|
||||
--SquareBalls
|
||||
local MetaSquare = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaSquare"}
|
||||
MetaSquare.__index = MetaSquare
|
||||
_M.MetaSquare=MetaSquare
|
||||
|
||||
function MetaSquare:new(x, y, radius, angle, x_scale, y_scale, goo)
|
||||
angle = angle or 0
|
||||
x_scale = x_scale or 1
|
||||
y_scale = y_scale or 1
|
||||
goo = goo or 1
|
||||
cosa = cos(angle)
|
||||
sina = sin(angle)
|
||||
return setmetatable({x=x, y=y, radius=radius, angle=angle, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaSquare)
|
||||
end
|
||||
|
||||
function MetaSquare:force(x, y)
|
||||
--Calculate force at point x y
|
||||
local force = ( abs( (x - self.x)*self.cosa + (y - self.y)*self.sina )/self.x_scale +
|
||||
abs( (y - self.y)*self.cosa - (x - self.x)*self.sina )/self.y_scale )
|
||||
if force == 0 then return zero_value end
|
||||
return (self.radius / force)^self.goo
|
||||
end
|
||||
|
||||
--Donuts
|
||||
local MetaDonut = {x=0, y=0, radius=0, angle=0, x_scale=1, y_scale=1, type="MetaDonut"}
|
||||
MetaDonut.__index = MetaDonut
|
||||
_M.MetaDonut=MetaDonut
|
||||
|
||||
function MetaDonut:new(x, y, out_r, int_r, angle, x_scale, y_scale, goo)
|
||||
angle = angle or 0
|
||||
x_scale = x_scale or 1
|
||||
y_scale = y_scale or 1
|
||||
goo = goo or 1
|
||||
cosa = cos(angle)
|
||||
sina = sin(angle)
|
||||
if int_r >= out_r then error("int_r >= out_r ("..int_r.." > "..out_r); return; end
|
||||
local radius = out_r--(out_r - int_r)*0.5
|
||||
local radius2 = int_r--(radius2 + radius)*0.5
|
||||
return setmetatable({x=x, y=y, radius=radius, radius2=radius2, x_scale=x_scale, y_scale=y_scale, goo=goo, cosa=cosa, sina=sina}, MetaDonut)
|
||||
end
|
||||
|
||||
function MetaDonut:force(x, y)
|
||||
--Calculate force at point x y
|
||||
local force = abs(self.radius - sqrt( (( (x - self.x)*self.cosa + (y - self.y)*self.sina )^2)/(self.x_scale) +
|
||||
(( (y - self.y)*self.cosa - (x - self.x)*self.sina )^2)/(self.y_scale) ))
|
||||
if force == 0 then return zero_value end
|
||||
return (self.radius2 / force)^self.goo
|
||||
|
||||
end
|
||||
|
||||
return _M
|
Loading…
x
Reference in New Issue
Block a user