Uploading from working directory

master
mrunderhill89 2017-06-03 12:20:15 -07:00
parent a6b2b91cf3
commit 7f5cf229ec
16 changed files with 3300 additions and 1 deletions

View File

@ -1,6 +1,8 @@
MIT License
Copyright (c) 2017 mrunderhill89
MinetestRx: Copyright (c) 2017 Kevin Cameron
RxLua: Copyright (c) 2015 Bjorn Swenson
Moses: Copyright (c) 2012-2014 Roland Yonaba
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

0
lib_deps/depends.txt Normal file
View File

271
lib_deps/deps.lua Normal file
View File

@ -0,0 +1,271 @@
local _ = _ or require("moses_min")
local Rx = Rx or require("rx")
local warn = print
local load_module = Rx.Subject.create()
local load_dependency = Rx.Subject.create()
local Deps = {
--A read-only version of load_module for public use.
on_module_load = load_module:map(_.identity),
on_dependency_load = load_dependency:map(_.identity),
modules = {},
dependencies = {}
}
local function kvp(tab)
local i = 1
local array = {}
for k,v in pairs(tab) do
array[i] = {
key = k,
value = v
}
i = i + 1
end
return array
end
local function table_to_string(tab)
return _.reduce(kvp(tab), function(result, kvp)
local head = result.."\n"..tostring(kvp.key).."=>"
return head..tostring(kvp.value)
end, "{").."\n}"
end
-- Internal functions
local function to_property(source, ...)
local prop = Rx.BehaviorSubject.create(...)
source:subscribe(
_.bind(prop.onNext, prop),
_.bind(prop.onError, prop),
_.bind(prop.onCompleted, prop)
)
return prop
end
local function bind_last(fun, ...)
local bound_args = {...}
return function (...)
return fun(unpack(_.append({...},bound_args)))
end
end
-- Get Module
function Deps.get_module(name)
if _.isNil(Deps.modules[name]) then
--Create a branch off of on_module_load for this module.
Deps.modules[name] = to_property(
load_module:filter(function(loaded_module)
return loaded_module.name == name
end):map(function(loaded_module)
return loaded_module.value
end):distinctUntilChanged())
end
return Deps.modules[name]
end
-- Get Dependency
function Deps.get_dependency(deps)
if (_.isArray(deps) and _.size(deps) > 1) then
for ex_deps, obs in pairs(Deps.dependencies) do
if (_.same(ex_deps, deps)) then
--Reuse the previous observable if there is one
return obs
end
end
local new_dep = Rx.Observable.combineLatest(
unpack(
_.map(deps, function(key, module_name)
return Deps.get_module(module_name)
end)
)
)
new_dep:subscribe(function(...)
load_dependency:onNext({
deps = deps,
results = {...}
})
end)
Deps.dependencies[deps] = new_dep
return new_dep
elseif (_.isString(deps)) then
return Deps.get_module(deps)
elseif (_.isArray(deps)) then
if (_.size(deps) == 1) then
return Deps.get_module(deps[1])
else
error("Dependency array is empty.")
end
else
error("Dependency needs to be a string or array of strings.\n"
.."Got "..typeof(deps).." instead.")
end
end
--Depend
--- Core dependency registration function. Calls the provided function when
-- all dependencies are met. "Transform" parameter allows for Rx functions
-- to be called on the returned dependency.
-- @arg {string, array<string>} deps: dependencies to check before calling.
-- @arg {function(...)=>nil} definition: definition function to call when all deps are loaded.
-- @arg {function(observable)=>observable} transform: modifies the initial dependency observable.
function Deps.depend_custom(deps, definition, transform)
if _.isCallable(definition) then
if (_.isArray(deps) and _.size(deps) == 0) then
warn("Deps.depend: Got dependency array but it was empty. Do you really need to use dependencies for this?")
definition()
else
transform(Deps.get_dependency(deps)):subscribe(definition)
end
else
error("Deps.depend: Definition function needs to be callable.")
end
end
--- Standard dependency function. Automatically reloads when dependencies do.
function Deps.depend(deps, definition)
return Deps.depend_custom(deps, definition, _.identity)
end
--- Definition is ran only once after all deps are loaded. Reloading has no effect.
-- Use this if you have some sensitive data that you don't want clobbered on reload.
function Deps.depend_once(deps, definition)
return Deps.depend_custom(deps, definition, bind_last(Rx.Observable.take, 1))
end
--- Definition will stop listening to reloads when the given observable sends a value.
function Deps.depend_until(deps, definition, til)
return Deps.depend_custom(deps, definition, bind_last(Rx.Observable.takeUntil, til))
end
--- Definition will stop listening to reloads when the predicate returns falsy.
function Deps.depend_while(deps, definition, predicate)
return Deps.depend_custom(deps, definition, bind_last(Rx.Observable.takeWhile, predicate))
end
--Define
--- Super-simple module definition. Use this for modules already loaded using
-- require or dofile that don't need dependencies.
-- @arg {string} module_name: name of the module to define
-- @arg {any} value: value to store in the module
function Deps.define_value(module_name, value)
local output = Deps.get_module(module_name)
local module_event = {
name = module_name,
value = value
}
load_module:onNext(module_event)
--Debug logic. Make sure the module got loaded correctly
local result = output:getValue()
assert(result == module_event.value,
"DefineValue: Module '"..module_event.name.."' got something other than the value passed into it."
.."\nGot: "..tostring(result or "Nothing")
.."\nShould Be: "..tostring(module_event.value or "Nothing")
)
end
--- Core module definition function. Very similar to define_custom, but passes
-- the results of the definition function in as a new module.
-- Example Usage:
-- define("MyModule",
-- {"dep1", "dep2"},
-- function(dep1,dep2)
-- return my_module
-- end
-- )
-- @arg {string} module_name: name of the module to define
-- @arg {string, array<string>} deps: dependencies to check before calling.
-- @arg {function(...)=>nil} definition: definition function to call when all deps are loaded.
-- @arg {function(observable)=>observable} transform: modifies the initial dependency observable.
function Deps.define_custom(module_name, deps, definition, transform)
if _.isCallable(definition) then
Deps.depend_custom(deps,
function(...)
Deps.define_value(module_name, definition(...))
end
,transform)
else
warn("Deps.define: Received non-callable data for definition. You might want to use define_value instead.")
Deps.define_value(module_name, definition)
end
end
function Deps.define(module_name, deps, definition)
return Deps.define_custom(module_name, deps, definition, _.identity)
end
function Deps.define_once(module_name, deps, definition)
return Deps.define_custom(module_name, deps, definition, bind_last(Rx.Observable.take, 1))
end
function Deps.define_until(module_name, deps, definition, til)
return Deps.define_custom(module_name, deps, definition, bind_last(Rx.Observable.takeUntil, til))
end
function Deps.define_while(module_name, deps, definition, predicate)
return Deps.define_custom(module_name, deps, definition, bind_last(Rx.Observable.takeWhile, predicate))
end
-- Globalize
function Deps.globalize()
depend = Deps.depend
depend_once = Deps.depend_once
depend_until = Deps.depend_until
depend_while = Deps.depend_while
depend_custom = Deps.depend_custom
define = Deps.define
define_value = Deps.define_value
define_once = Deps.define_once
define_until = Deps.define_until
define_while = Deps.define_while
define_custom = Deps.define_custom
end
-- Finalize
function Deps.finalize()
Deps.on_module_load:onCompleted()
end
--Debugging Tools
function print_module(name, value)
local value_text = (_.isNil(value)) and "Empty"
or tostring(value)
print("module: "..name.." = "..value_text)
end
function Deps.log_modules()
_.each(Deps.modules, function(name, obs)
print_module(name, obs:getValue())
end)
end
function Deps.rx_log_modules()
--Log the modules that we already have (if any).
Deps.log_modules()
Deps.on_module_load:subscribe(function(params)
print_module(params.name, params.value)
end)
Deps.on_dependency_load:subscribe(function(dep)
print("dependency:"..table_to_string(dep.deps))
end)
end
--Default Modules
Deps.define_value("Moses", _)
Deps.define_value("Rx", Rx)
--Return module interface
return Deps

4
lib_deps/init.lua Normal file
View File

@ -0,0 +1,4 @@
_ = minetest.lib._
Rx = minetest.lib.Rx
minetest.lib.Deps = dofile(minetest.get_modpath("lib_deps").."/deps.lua")

5
lib_moses/init.lua Normal file
View File

@ -0,0 +1,5 @@
--All this does is load Moses and make it available to Minetest.
minetest.lib = minetest.lib or {}
minetest.lib._ = dofile(minetest.get_modpath("lib_moses").."/moses_min.lua")
return minetest.lib._

291
lib_moses/moses_min.lua Normal file
View File

@ -0,0 +1,291 @@
local daa='1.4.0'local _ba,aba,bba,cba,dba=next,type,unpack,select,pcall
local _ca,aca=setmetatable,getmetatable;local bca,cca=table.insert,table.sort;local dca,_da=table.remove,table.concat
local ada,bda,cda=math.randomseed,math.random,math.huge;local dda,__b,a_b=math.floor,math.max,math.min;local b_b=rawget;local c_b=bba
local d_b,_ab=pairs,ipairs;local aab={}local function bab(bcb,ccb)return bcb>ccb end
local function cab(bcb,ccb)return bcb<ccb end;local function dab(bcb,ccb,dcb)
return(bcb<ccb)and ccb or(bcb>dcb and dcb or bcb)end
local function _bb(bcb,ccb)return ccb and true end;local function abb(bcb)return not bcb end;local function bbb(bcb)local ccb=0
for dcb,_db in d_b(bcb)do ccb=ccb+1 end;return ccb end
local function cbb(bcb,ccb,dcb,...)local _db
local adb=dcb or aab.identity;for bdb,cdb in d_b(bcb)do
if not _db then _db=adb(cdb,...)else local ddb=adb(cdb,...)_db=
ccb(_db,ddb)and _db or ddb end end;return _db end
local function dbb(bcb,ccb,dcb)for i=0,#bcb,ccb do local _db=aab.slice(bcb,i+1,i+ccb)
if#_db>0 then dcb(_db)end end end
local function _cb(bcb,ccb,dcb)if ccb==0 then dcb(bcb)end
for i=1,ccb do bcb[ccb],bcb[i]=bcb[i],bcb[ccb]_cb(bcb,ccb-
1,dcb)bcb[ccb],bcb[i]=bcb[i],bcb[ccb]end end;local acb=-1
function aab.each(bcb,ccb,...)for dcb,_db in d_b(bcb)do ccb(dcb,_db,...)end end
function aab.eachi(bcb,ccb,...)
local dcb=aab.sort(aab.select(aab.keys(bcb),function(_db,adb)return aab.isInteger(adb)end))for _db,adb in _ab(dcb)do ccb(adb,bcb[adb],...)end end
function aab.at(bcb,...)local ccb={}for dcb,_db in _ab({...})do
if aab.has(bcb,_db)then ccb[#ccb+1]=bcb[_db]end end;return ccb end
function aab.count(bcb,ccb)if aab.isNil(ccb)then return aab.size(bcb)end;local dcb=0
aab.each(bcb,function(_db,adb)if
aab.isEqual(adb,ccb)then dcb=dcb+1 end end)return dcb end
function aab.countf(bcb,ccb,...)return aab.count(aab.map(bcb,ccb,...),true)end
function aab.cycle(bcb,ccb)ccb=ccb or 1;if ccb<=0 then return function()end end;local dcb,_db;local adb=0
while true do
return
function()dcb=
dcb and _ba(bcb,dcb)or _ba(bcb)_db=
not _db and dcb or _db;if ccb then
adb=(dcb==_db)and adb+1 or adb;if adb>ccb then return end end
return dcb,bcb[dcb]end end end;function aab.map(bcb,ccb,...)local dcb={}
for _db,adb in d_b(bcb)do dcb[_db]=ccb(_db,adb,...)end;return dcb end;function aab.reduce(bcb,ccb,dcb)
for _db,adb in
d_b(bcb)do if dcb==nil then dcb=adb else dcb=ccb(dcb,adb)end end;return dcb end;function aab.reduceRight(bcb,ccb,dcb)return
aab.reduce(aab.reverse(bcb),ccb,dcb)end
function aab.mapReduce(bcb,ccb,dcb)
local _db={}for adb,bdb in d_b(bcb)do _db[adb]=not dcb and bdb or ccb(dcb,bdb)
dcb=_db[adb]end;return _db end;function aab.mapReduceRight(bcb,ccb,dcb)
return aab.mapReduce(aab.reverse(bcb),ccb,dcb)end
function aab.include(bcb,ccb)local dcb=
aab.isFunction(ccb)and ccb or aab.isEqual;for _db,adb in d_b(bcb)do if dcb(adb,ccb)then
return true end end;return false end
function aab.detect(bcb,ccb)
local dcb=aab.isFunction(ccb)and ccb or aab.isEqual;for _db,adb in d_b(bcb)do if dcb(adb,ccb)then return _db end end end
function aab.contains(bcb,ccb)return aab.toBoolean(aab.detect(bcb,ccb))end
function aab.findWhere(bcb,ccb)
local dcb=aab.detect(bcb,function(_db)for adb in d_b(ccb)do
if ccb[adb]~=_db[adb]then return false end end;return true end)return dcb and bcb[dcb]end
function aab.select(bcb,ccb,...)local dcb=aab.map(bcb,ccb,...)local _db={}for adb,bdb in d_b(dcb)do if bdb then
_db[#_db+1]=bcb[adb]end end;return _db end
function aab.reject(bcb,ccb,...)local dcb=aab.map(bcb,ccb,...)local _db={}for adb,bdb in d_b(dcb)do if not bdb then
_db[#_db+1]=bcb[adb]end end;return _db end;function aab.all(bcb,ccb,...)return
( (#aab.select(aab.map(bcb,ccb,...),_bb))== (#bcb))end
function aab.invoke(bcb,ccb,...)
local dcb={...}
return
aab.map(bcb,function(_db,adb)
if aab.isTable(adb)then
if aab.has(adb,ccb)then if aab.isCallable(adb[ccb])then return
adb[ccb](adb,c_b(dcb))else return adb[ccb]end else if
aab.isCallable(ccb)then return ccb(adb,c_b(dcb))end end elseif aab.isCallable(ccb)then return ccb(adb,c_b(dcb))end end)end
function aab.pluck(bcb,ccb)return
aab.reject(aab.map(bcb,function(dcb,_db)return _db[ccb]end),abb)end;function aab.max(bcb,ccb,...)return cbb(bcb,bab,ccb,...)end;function aab.min(bcb,ccb,...)return
cbb(bcb,cab,ccb,...)end
function aab.shuffle(bcb,ccb)if ccb then ada(ccb)end
local dcb={}
aab.each(bcb,function(_db,adb)local bdb=dda(bda()*_db)+1;dcb[_db]=dcb[bdb]
dcb[bdb]=adb end)return dcb end
function aab.same(bcb,ccb)
return
aab.all(bcb,function(dcb,_db)return aab.include(ccb,_db)end)and
aab.all(ccb,function(dcb,_db)return aab.include(bcb,_db)end)end;function aab.sort(bcb,ccb)cca(bcb,ccb)return bcb end
function aab.groupBy(bcb,ccb,...)local dcb={...}
local _db={}
local adb=aab.isFunction(ccb)and ccb or(aab.isString(ccb)and function(bdb,cdb)return
cdb[ccb](cdb,c_b(dcb))end)if not adb then return end
aab.each(bcb,function(bdb,cdb)local ddb=adb(bdb,cdb)
if _db[ddb]then _db[ddb][#_db[ddb]+
1]=cdb else _db[ddb]={cdb}end end)return _db end
function aab.countBy(bcb,ccb,...)local dcb={...}local _db={}
aab.each(bcb,function(adb,bdb)local cdb=ccb(adb,bdb,c_b(dcb))_db[cdb]=(
_db[cdb]or 0)+1 end)return _db end
function aab.size(...)local bcb={...}local ccb=bcb[1]if aab.isNil(ccb)then return 0 elseif aab.isTable(ccb)then return
bbb(bcb[1])else return bbb(bcb)end end;function aab.containsKeys(bcb,ccb)
for dcb in d_b(ccb)do if not bcb[dcb]then return false end end;return true end
function aab.sameKeys(bcb,ccb)
aab.each(bcb,function(dcb)if
not ccb[dcb]then return false end end)
aab.each(ccb,function(dcb)if not bcb[dcb]then return false end end)return true end;function aab.toArray(...)return{...}end
function aab.find(bcb,ccb,dcb)for i=dcb or 1,#bcb do if
aab.isEqual(bcb[i],ccb)then return i end end end
function aab.reverse(bcb)local ccb={}for i=#bcb,1,-1 do ccb[#ccb+1]=bcb[i]end;return ccb end
function aab.selectWhile(bcb,ccb,...)local dcb={}for _db,adb in _ab(bcb)do
if ccb(_db,adb,...)then dcb[_db]=adb else break end end;return dcb end
function aab.dropWhile(bcb,ccb,...)local dcb
for _db,adb in _ab(bcb)do if not ccb(_db,adb,...)then dcb=_db;break end end;if aab.isNil(dcb)then return{}end;return aab.rest(bcb,dcb)end
function aab.sortedIndex(bcb,ccb,dcb,_db)local adb=dcb or cab;if _db then aab.sort(bcb,adb)end;for i=1,#bcb do if not
adb(bcb[i],ccb)then return i end end
return#bcb+1 end
function aab.indexOf(bcb,ccb)for k=1,#bcb do if bcb[k]==ccb then return k end end end
function aab.lastIndexOf(bcb,ccb)local dcb=aab.indexOf(aab.reverse(bcb),ccb)if dcb then return
#bcb-dcb+1 end end;function aab.addTop(bcb,...)
aab.each({...},function(ccb,dcb)bca(bcb,1,dcb)end)return bcb end;function aab.push(bcb,...)aab.each({...},function(ccb,dcb)
bcb[#bcb+1]=dcb end)
return bcb end
function aab.pop(bcb,ccb)
ccb=a_b(ccb or 1,#bcb)local dcb={}
for i=1,ccb do local _db=bcb[1]dcb[#dcb+1]=_db;dca(bcb,1)end;return c_b(dcb)end
function aab.unshift(bcb,ccb)ccb=a_b(ccb or 1,#bcb)local dcb={}for i=1,ccb do local _db=bcb[#bcb]
dcb[#dcb+1]=_db;dca(bcb)end;return c_b(dcb)end
function aab.pull(bcb,...)
for ccb,dcb in _ab({...})do for i=#bcb,1,-1 do
if aab.isEqual(bcb[i],dcb)then dca(bcb,i)end end end;return bcb end
function aab.removeRange(bcb,ccb,dcb)local _db=aab.clone(bcb)local adb,bdb=(_ba(_db)),#_db
if bdb<1 then return _db end;ccb=dab(ccb or adb,adb,bdb)
dcb=dab(dcb or bdb,adb,bdb)if dcb<ccb then return _db end;local cdb=dcb-ccb+1;local ddb=ccb;while cdb>0 do
dca(_db,ddb)cdb=cdb-1 end;return _db end
function aab.chunk(bcb,ccb,...)if not aab.isArray(bcb)then return bcb end;local dcb,_db,adb={},0
local bdb=aab.map(bcb,ccb,...)
aab.each(bdb,function(cdb,ddb)adb=(adb==nil)and ddb or adb;_db=(
(ddb~=adb)and(_db+1)or _db)
if not dcb[_db]then dcb[_db]={bcb[cdb]}else dcb[_db][
#dcb[_db]+1]=bcb[cdb]end;adb=ddb end)return dcb end
function aab.slice(bcb,ccb,dcb)return
aab.select(bcb,function(_db)return
(_db>= (ccb or _ba(bcb))and _db<= (dcb or#bcb))end)end;function aab.first(bcb,ccb)local dcb=ccb or 1
return aab.slice(bcb,1,a_b(dcb,#bcb))end
function aab.initial(bcb,ccb)
if ccb and ccb<0 then return end;return
aab.slice(bcb,1,ccb and#bcb- (a_b(ccb,#bcb))or#bcb-1)end;function aab.last(bcb,ccb)if ccb and ccb<=0 then return end
return aab.slice(bcb,ccb and
#bcb-a_b(ccb-1,#bcb-1)or 2,#bcb)end;function aab.rest(bcb,ccb)if ccb and
ccb>#bcb then return{}end
return aab.slice(bcb,
ccb and __b(1,a_b(ccb,#bcb))or 1,#bcb)end;function aab.compact(bcb)
return aab.reject(bcb,function(ccb,dcb)return
not dcb end)end
function aab.flatten(bcb,ccb)local dcb=ccb or false
local _db;local adb={}
for bdb,cdb in d_b(bcb)do
if aab.isTable(cdb)then
_db=dcb and cdb or aab.flatten(cdb)
aab.each(_db,function(ddb,__c)adb[#adb+1]=__c end)else adb[#adb+1]=cdb end end;return adb end
function aab.difference(bcb,ccb)if not ccb then return aab.clone(bcb)end;return
aab.select(bcb,function(dcb,_db)return not
aab.include(ccb,_db)end)end
function aab.union(...)return aab.uniq(aab.flatten({...}))end
function aab.intersection(bcb,...)local ccb={...}local dcb={}
for _db,adb in _ab(bcb)do if
aab.all(ccb,function(bdb,cdb)return aab.include(cdb,adb)end)then bca(dcb,adb)end end;return dcb end
function aab.symmetricDifference(bcb,ccb)return
aab.difference(aab.union(bcb,ccb),aab.intersection(bcb,ccb))end
function aab.unique(bcb)local ccb={}for i=1,#bcb do if not aab.find(ccb,bcb[i])then
ccb[#ccb+1]=bcb[i]end end;return ccb end
function aab.isunique(bcb)return aab.isEqual(bcb,aab.unique(bcb))end
function aab.zip(...)local bcb={...}
local ccb=aab.max(aab.map(bcb,function(_db,adb)return#adb end))local dcb={}for i=1,ccb do dcb[i]=aab.pluck(bcb,i)end;return dcb end
function aab.append(bcb,ccb)local dcb={}for _db,adb in _ab(bcb)do dcb[_db]=adb end;for _db,adb in _ab(ccb)do
dcb[#dcb+1]=adb end;return dcb end
function aab.interleave(...)return aab.flatten(aab.zip(...))end;function aab.interpose(bcb,ccb)return
aab.flatten(aab.zip(ccb,aab.rep(bcb,#ccb-1)))end
function aab.range(...)
local bcb={...}local ccb,dcb,_db
if#bcb==0 then return{}elseif#bcb==1 then dcb,ccb,_db=bcb[1],0,1 elseif#bcb==2 then
ccb,dcb,_db=bcb[1],bcb[2],1 elseif#bcb==3 then ccb,dcb,_db=bcb[1],bcb[2],bcb[3]end;if(_db and _db==0)then return{}end;local adb={}
local bdb=__b(dda((dcb-ccb)/_db),0)for i=1,bdb do adb[#adb+1]=ccb+_db*i end;if#adb>0 then
bca(adb,1,ccb)end;return adb end
function aab.rep(bcb,ccb)local dcb={}for i=1,ccb do dcb[#dcb+1]=bcb end;return dcb end
function aab.partition(bcb,ccb)return
coroutine.wrap(function()dbb(bcb,ccb or 1,coroutine.yield)end)end
function aab.permutation(bcb)return
coroutine.wrap(function()_cb(bcb,#bcb,coroutine.yield)end)end;function aab.invert(bcb)local ccb={}
aab.each(bcb,function(dcb,_db)ccb[_db]=dcb end)return ccb end
function aab.concat(bcb,ccb,dcb,_db)
local adb=aab.map(bcb,function(bdb,cdb)return
tostring(cdb)end)return _da(adb,ccb,dcb or 1,_db or#bcb)end;function aab.identity(bcb)return bcb end
function aab.once(bcb)local ccb=0;local dcb={}return
function(...)ccb=ccb+1;if ccb<=1 then
dcb={...}end;return bcb(c_b(dcb))end end
function aab.memoize(bcb,ccb)local dcb=_ca({},{__mode='kv'})
local _db=ccb or aab.identity
return function(...)local adb=_db(...)local bdb=dcb[adb]
if not bdb then dcb[adb]=bcb(...)end;return dcb[adb]end end
function aab.after(bcb,ccb)local dcb,_db=ccb,0;return
function(...)_db=_db+1;if _db>=dcb then return bcb(...)end end end
function aab.compose(...)local bcb=aab.reverse{...}return
function(...)local ccb;for dcb,_db in _ab(bcb)do ccb=ccb and _db(ccb)or
_db(...)end;return ccb end end
function aab.pipe(bcb,...)return aab.compose(...)(bcb)end
function aab.complement(bcb)return function(...)return not bcb(...)end end;function aab.juxtapose(bcb,...)local ccb={}
aab.each({...},function(dcb,_db)ccb[#ccb+1]=_db(bcb)end)return c_b(ccb)end
function aab.wrap(bcb,ccb)return function(...)return
ccb(bcb,...)end end
function aab.times(bcb,ccb,...)local dcb={}for i=1,bcb do dcb[i]=ccb(i,...)end;return dcb end
function aab.bind(bcb,ccb)return function(...)return bcb(ccb,...)end end
function aab.bindn(bcb,...)local ccb={...}return function(...)
return bcb(c_b(aab.append(ccb,{...})))end end
function aab.uniqueId(bcb,...)acb=acb+1
if bcb then if aab.isString(bcb)then return bcb:format(acb)elseif
aab.isFunction(bcb)then return bcb(acb,...)end end;return acb end;function aab.keys(bcb)local ccb={}
aab.each(bcb,function(dcb)ccb[#ccb+1]=dcb end)return ccb end;function aab.values(bcb)local ccb={}
aab.each(bcb,function(dcb,_db)ccb[
#ccb+1]=_db end)return ccb end;function aab.toBoolean(bcb)return
not not bcb end
function aab.extend(bcb,...)local ccb={...}
aab.each(ccb,function(dcb,_db)
if aab.isTable(_db)then aab.each(_db,function(adb,bdb)
bcb[adb]=bdb end)end end)return bcb end
function aab.functions(bcb,ccb)bcb=bcb or aab;local dcb={}
aab.each(bcb,function(adb,bdb)if aab.isFunction(bdb)then
dcb[#dcb+1]=adb end end)if not ccb then return aab.sort(dcb)end;local _db=aca(bcb)
if
_db and _db.__index then local adb=aab.functions(_db.__index)aab.each(adb,function(bdb,cdb)
dcb[#dcb+1]=cdb end)end;return aab.sort(dcb)end
function aab.clone(bcb,ccb)if not aab.isTable(bcb)then return bcb end;local dcb={}
aab.each(bcb,function(_db,adb)if
aab.isTable(adb)then
if not ccb then dcb[_db]=aab.clone(adb,ccb)else dcb[_db]=adb end else dcb[_db]=adb end end)return dcb end;function aab.tap(bcb,ccb,...)ccb(bcb,...)return bcb end;function aab.has(bcb,ccb)return
bcb[ccb]~=nil end
function aab.pick(bcb,...)local ccb=aab.flatten{...}
local dcb={}
aab.each(ccb,function(_db,adb)
if not aab.isNil(bcb[adb])then dcb[adb]=bcb[adb]end end)return dcb end
function aab.omit(bcb,...)local ccb=aab.flatten{...}local dcb={}
aab.each(bcb,function(_db,adb)if
not aab.include(ccb,_db)then dcb[_db]=adb end end)return dcb end;function aab.template(bcb,ccb)
aab.each(ccb or{},function(dcb,_db)if not bcb[dcb]then bcb[dcb]=_db end end)return bcb end
function aab.isEqual(bcb,ccb,dcb)
local _db=aba(bcb)local adb=aba(ccb)if _db~=adb then return false end
if _db~='table'then return(bcb==ccb)end;local bdb=aca(bcb)local cdb=aca(ccb)
if dcb then if
bdb or cdb and bdb.__eq or cdb.__eq then return(bcb==ccb)end end
if aab.size(bcb)~=aab.size(ccb)then return false end
for ddb,__c in d_b(bcb)do local a_c=ccb[ddb]if
aab.isNil(a_c)or not aab.isEqual(__c,a_c,dcb)then return false end end
for ddb,__c in d_b(ccb)do local a_c=bcb[ddb]if aab.isNil(a_c)then return false end end;return true end
function aab.result(bcb,ccb,...)
if bcb[ccb]then if aab.isCallable(bcb[ccb])then return bcb[ccb](bcb,...)else return
bcb[ccb]end end;if aab.isCallable(ccb)then return ccb(bcb,...)end end;function aab.isTable(bcb)return aba(bcb)=='table'end
function aab.isCallable(bcb)return
(
aab.isFunction(bcb)or
(aab.isTable(bcb)and aca(bcb)and aca(bcb).__call~=nil)or false)end
function aab.isArray(bcb)if not aab.isTable(bcb)then return false end;local ccb=0
for dcb in
d_b(bcb)do ccb=ccb+1;if aab.isNil(bcb[ccb])then return false end end;return true end
function aab.isIterable(bcb)return aab.toBoolean((dba(d_b,bcb)))end
function aab.isEmpty(bcb)if aab.isNil(bcb)then return true end;if aab.isString(bcb)then
return#bcb==0 end
if aab.isTable(bcb)then return _ba(bcb)==nil end;return true end;function aab.isString(bcb)return aba(bcb)=='string'end;function aab.isFunction(bcb)return
aba(bcb)=='function'end;function aab.isNil(bcb)
return bcb==nil end
function aab.isNumber(bcb)return aba(bcb)=='number'end
function aab.isNaN(bcb)return aab.isNumber(bcb)and bcb~=bcb end
function aab.isFinite(bcb)if not aab.isNumber(bcb)then return false end;return
bcb>-cda and bcb<cda end;function aab.isBoolean(bcb)return aba(bcb)=='boolean'end
function aab.isInteger(bcb)return
aab.isNumber(bcb)and dda(bcb)==bcb end
do aab.forEach=aab.each;aab.forEachi=aab.eachi;aab.loop=aab.cycle
aab.collect=aab.map;aab.inject=aab.reduce;aab.foldl=aab.reduce
aab.injectr=aab.reduceRight;aab.foldr=aab.reduceRight;aab.mapr=aab.mapReduce
aab.maprr=aab.mapReduceRight;aab.any=aab.include;aab.some=aab.include;aab.filter=aab.select
aab.discard=aab.reject;aab.every=aab.all;aab.takeWhile=aab.selectWhile
aab.rejectWhile=aab.dropWhile;aab.shift=aab.pop;aab.remove=aab.pull;aab.rmRange=aab.removeRange
aab.chop=aab.removeRange;aab.sub=aab.slice;aab.head=aab.first;aab.take=aab.first
aab.tail=aab.rest;aab.skip=aab.last;aab.without=aab.difference;aab.diff=aab.difference
aab.symdiff=aab.symmetricDifference;aab.xor=aab.symmetricDifference;aab.uniq=aab.unique
aab.isuniq=aab.isunique;aab.part=aab.partition;aab.perm=aab.permutation;aab.mirror=aab.invert
aab.join=aab.concat;aab.cache=aab.memoize;aab.juxt=aab.juxtapose;aab.uid=aab.uniqueId
aab.methods=aab.functions;aab.choose=aab.pick;aab.drop=aab.omit;aab.defaults=aab.template
aab.compare=aab.isEqual end
do local bcb={}local ccb={}ccb.__index=bcb;local function dcb(_db)local adb={_value=_db,_wrapped=true}
return _ca(adb,ccb)end
_ca(ccb,{__call=function(_db,adb)return dcb(adb)end,__index=function(_db,adb,...)return
bcb[adb]end})function ccb.chain(_db)return dcb(_db)end
function ccb:value()return self._value end;bcb.chain,bcb.value=ccb.chain,ccb.value
for _db,adb in d_b(aab)do
bcb[_db]=function(bdb,...)local cdb=aab.isTable(bdb)and
bdb._wrapped or false
if cdb then
local ddb=bdb._value;local __c=adb(ddb,...)return dcb(__c)else return adb(bdb,...)end end end
bcb.import=function(_db,adb)_db=_db or _G;local bdb=aab.functions()
aab.each(bdb,function(cdb,ddb)
if b_b(_db,ddb)then if not adb then
_db[ddb]=aab[ddb]end else _db[ddb]=aab[ddb]end end)return _db end;ccb._VERSION='Moses v'..daa
ccb._URL='http://github.com/Yonaba/Moses'
ccb._LICENSE='MIT <http://raw.githubusercontent.com/Yonaba/Moses/master/LICENSE>'ccb._DESCRIPTION='utility-belt library for functional programming in Lua'return
ccb end

5
lib_rx/init.lua Normal file
View File

@ -0,0 +1,5 @@
--All this does is load RxLua and make it available to Minetest.
minetest.lib = minetest.lib or {}
minetest.lib.Rx = dofile(minetest.get_modpath("lib_rx").."/rx.lua")
return minetest.lib.Rx

2203
lib_rx/rx.lua Normal file

File diff suppressed because it is too large Load Diff

95
minetest_rx/controls.lua Normal file
View File

@ -0,0 +1,95 @@
local minetest = minetest or require("mock_minetest")
local Rx = minetest.lib.Rx or require("rx")
local _ = minetest.lib._ or require("moses_min")
-- Player -> Key -> Function
-- Null string "" is used to indicate "all players."
local all = ""
local function build_key()
local key = {
value = Rx.Subject.create()
}
key.change = key.value:scan(function(mem, event)
local value = event.status and 1 or 0
if mem.event then
mem.delta = (event.status and 1 or 0) - (mem.event.status and 1 or 0)
end
mem.event = event
return mem
end, {delta = 0})
key.press = key.change:filter(function(v_data)
return v_data.delta == 1
end):map("event")
key.release = key.change:filter(function(v_data)
return v_data.delta == -1
end):map("event")
key.hold = key.change:filter(function(v_data)
return v_data.delta == 0 and (vdata.event and v_data.event.status)
end):map("event")
key.idle = key.change:filter(function(v_data)
return v_data.delta == 0 and not (vdata.event and v_data.event.status)
end):map("event")
key.release_time = key.press:flatMap(function(press_event)
return control_data[press_event.player][press_event.key].release:take(1):map(function(release_event)
return {
press = press_event,
release = release_event,
hold_time = release_event.t.time - press_event.t.time
}
end)
end)
return key
end
local player_meta = {
__index = function(self,key)
--print('New Key:"'..key..'"')
self[key] = build_key()
return self[key]
end
}
local function build_player()
local player = setmetatable({}, player_meta)
player[all].value:subscribe(function(event)
player[event.key].value:onNext(event)
end)
return player
end
local control_data = setmetatable({}, {
__index = function(self,key)
--print('New Player:"'..key..'"')
self[key] = build_player()
return self[key]
end
})
control_data[all][all].value:subscribe(function(event)
control_data[event.player][all].value:onNext(event)
end)
function on_frame(t)
for i, player in ipairs(minetest.get_connected_players()) do
local player_name = player:get_player_name()
if player_name ~= all then
local input = player:get_player_control()
for key, status in pairs(input) do
control_data[all][all].value:onNext({
player = player,
key = key,
status = status,
t = t
})
end
end
end
end
minetest.Rx.events.globaltime:subscribe(on_frame)
return control_data

2
minetest_rx/depends.txt Normal file
View File

@ -0,0 +1,2 @@
lib_moses
lib_rx

222
minetest_rx/game_events.lua Normal file
View File

@ -0,0 +1,222 @@
minetest = minetest or require("mock_minetest")
local Rx = minetest.lib.Rx or require("rx")
local _ = minetest.lib._ or require("moses_min")
local function dispose_on_shutdown(observer)
minetest.register_on_shutdown(function()
observer:onCompleted()
end)
end
local events = {
globalstep = Rx.Observable.create(function(observer)
minetest.register_globalstep(function(dtime)
local params = {dtime = dtime}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_shutdown = Rx.Observable.create(function(observer)
minetest.register_on_shutdown(function()
observer:onNext()
end)
dispose_on_shutdown(observer)
end),
on_dignode = Rx.Observable.create(function(observer)
minetest.register_on_dignode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
local params = {
pos = pos,
newnode = newnode,
placer = placer,
oldnode = oldnode,
itemstack = itemstack,
pointed_thing = pointed_thing
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_punchnode = Rx.Observable.create(function(observer)
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
local params = {
pos = pos,
node = node,
puncher = puncher,
pointed_thing = pointed_thing
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_placenode = Rx.Observable.create(function(observer)
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
local params = {
pos = pos,
newnode = newnode,
placer = placer,
oldnode = oldnode,
itemstack = itemstack,
pointed_thing = pointed_thing
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_punchplayer = Rx.Observable.create(function(observer)
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
local params = {
player = player,
hitter = hitter,
time_from_last_punch = time_from_last_punch,
tool_capabilities = tool_capabilities,
dir = dir,
damage = damage
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_craft = Rx.Observable.create(function(observer)
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
local params = {
itemstack = itemstack,
player = player,
old_craft_grid = old_craft_grid,
craft_inv = craft_ind
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
craft_predict = Rx.Observable.create(function(observer)
minetest.register_craft_predict(function(itemstack, player, old_craft_grid, craft_inv)
local params = {
itemstack = itemstack,
player = player,
old_craft_grid = old_craft_grid,
craft_inv = craft_ind
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_item_eat = Rx.Observable.create(function(observer)
minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)
local params = {
hp_change = hp_change,
replace_with_item = replace_with_item,
itemstack = itemstack,
user = user,
pointed_thing = pointed_thing
}
end)
dispose_on_shutdown(observer)
end),
on_generated = Rx.Observable.create(function(observer)
minetest.register_on_generated(function(minp, maxp, blockseed)
local params = {
minp = minp,
maxp = maxp,
blockseed = blockseed
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_newplayer = Rx.Observable.create(function(observer)
minetest.register_on_newplayer(function(obj_ref)
local params = {
obj_ref = obj_ref
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_prejoinplayer = Rx.Observable.create(function(observer)
minetest.register_on_prejoinplayer(function(obj_ref)
local params = {
name = name,
ip = ip
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_joinplayer = Rx.Observable.create(function(observer)
minetest.register_on_joinplayer(function(obj_ref)
local params = {
obj_ref = obj_ref
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_dieplayer = Rx.Observable.create(function(observer)
minetest.register_on_dieplayer(function(obj_ref)
local params = {
obj_ref = obj_ref
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_respawnplayer = Rx.Observable.create(function(observer)
minetest.register_on_respawnplayer(function(obj_ref)
local params = {
obj_ref = obj_ref
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_leaveplayer = Rx.Observable.create(function(observer)
minetest.register_on_respawnplayer(function(obj_ref)
local params = {
obj_ref = obj_ref
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_cheat = Rx.Observable.create(function(observer)
minetest.register_on_respawnplayer(function(obj_ref, cheat)
local params = {
obj_ref = obj_ref,
cheat = cheat
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_chat_message = Rx.Observable.create(function(observer)
minetest.register_on_chat_message(function(name, message)
local params = {
name = name,
message = message
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end),
on_protection_violation = Rx.Observable.create(function(observer)
minetest.register_on_protection_violation(function(pos, name)
local params = {
pos = pos,
name = name
}
observer:onNext(params)
end)
dispose_on_shutdown(observer)
end)
}
-- This stream is generally the same as globalstep, but returns
-- the accumulated time since the server was started. It's used
-- for anything that requires polling.
events.globaltime = events.globalstep:scan(function(memo, step)
memo.time = memo.time + step.dtime
memo.dtime = step.dtime
return memo
end, {time = 0, dtime = 0}):map(_.clone)
minetest.Rx.events = events
return events

6
minetest_rx/init.lua Normal file
View File

@ -0,0 +1,6 @@
minetest = minetest or require("mock_minetest")
local modpath = minetest.get_modpath("minetest_rx")
minetest.Rx = {}
dofile(modpath.."/registration.lua")
dofile(modpath.."/game_events.lua")
dofile(modpath.."/controls.lua")

View File

@ -0,0 +1,4 @@
local any = ""
return function()
end

View File

@ -0,0 +1,25 @@
package.path = package.path
.. ";../lib_moses/?.lua"
.. ";../lib_rx/?.lua"
.. ";../lib_deps/?.lua"
local mock = {
get_modpath = function(path)
return "."
end,
Rx = {
events = {
globaltime = {
subscribe = function()
print("events.globaltime subscribed")
end
}
}
},
lib = {
_ = require("moses_min"),
Rx = require("rx"),
Deps = require("deps"),
}
}
return mock

View File

@ -0,0 +1,163 @@
minetest = minetest or require("mock_minetest")
local Rx = minetest.lib.Rx or require("rx")
local _ = minetest.lib._ or require("moses_min")
local function wrap_existing(name, existing)
return
type(existing) == "function" and existing()
or type(existing) == "string" and minetest[existing]
or minetest["registered_"..name.."s"]
end
local mt_native = {}
-- Keyless Events
local function keyless_event_setup(name, native, existing)
local existing = wrap_existing(name, existing)
local future = Rx.Subject.create()
local observable = Rx.Observable.create(function(observer)
for i, value in ipairs(existing) do
observer:onNext(value)
end
end):merge(future)
local wrapper = function(...)
local result = {native(...)}
future:onNext(...)
return unpack(result)
end
return native, wrapper, observable
end
for i, key in pairs({
"craft",
"decoration",
"ore"
}) do
mt_native["register_"..key], minetest["register_"..key], minetest["on_register_"..key] =
keyless_event_setup(key, minetest["register_"..key])
end
-- Keyed Events
local any = ""
local function key_event_setup(name, native, existing)
local existing = wrap_existing(name, existing)
local store = {
[any] = Rx.Subject.create()
}
local observables = function(key)
if (type(key) ~= "string") then
return store[any]
end
if (store[key] == nil) then
if string.match(key, "^group:") then
local g_name = string.gsub(key, "^group:", "")
-- This is a group.
store[key] = Rx.Observable.create(function(obs)
for k,params in pairs(existing) do
local g_val = type(params.groups) == "table" and params.groups[g_name] or 0
obs:onNext({
key = key,
value = g_val,
params = params
})
end
end):merge(store[any]:map(function(kvp)
local params = kvp.value[1]
local g_val = type(params.groups) == "table" and params.groups[g_name] or 0
return {
key = kvp.key,
value = g_val,
params = params
}
end))
else
-- This is just a node name.
store[key] = Rx.ReplaySubject.create(1)
if (existing[key]) then
store[key]:onNext(existing[key])
end
end
end
return store[key]
end
local wrapper = function(key, ...)
assert(type(key) == "string", "Key for registration function must be a string. Got "..type(key).." instead.")
local san_key = string.gsub(key, "^:+", "")
assert(san_key ~= any, "Attempted to use special 'any' value for registration.")
local result = {native(":"..san_key, ...)}
observables(any):onNext({
key = san_key,
value = {...}
})
observables(key):onNext(...)
return unpack(result)
end
return native, wrapper, observables
end
for i, key in pairs({
"craftitem",
"node",
"tool",
"privilege"
}) do
mt_native["register_"..key], minetest["register_"..key], minetest["on_register_"..key] =
key_event_setup(key, minetest["register_"..key])
end
-- Special case for weird plurals.
mt_native.register_entity, minetest.register_entity, minetest.on_register_entity =
key_event_setup("entity", minetest.register_entity, "registered_entities")
local function lazy_extend(base, length)
if (length == 0) then
return base
end
return function(n)
local step = _.extend(n, base)
return lazy_extend(step, length-1)
end
end
-- Extend/Copy functions
for i, key in pairs({
"craftitem",
"node",
"tool",
"entity"
}) do
minetest["extend_"..key] = function(old_name, new_name, params)
assert(type(old_name) == "string", "Extension target key must be a string. Got "..type(old_name).." instead.")
assert(old_name ~= any, "Attempted to use special 'any' value for extension.")
assert(not string.match(old_name, "^group:"), old_name.." is a group and shouldn't be used as an extension target.")
if type(new_name) ~= "string" and params == nil then
params = new_name
new_name = old_name
end
local san_name = string.gsub(new_name, "^:+", "")
local extend = type(params) == "function" and params
or function(old,new)
local result = {}
for k,v in pairs(old) do
result[k] = v
end
for k,v in pairs(new) do
result[k] = v
end
return result
end
minetest["on_register_"..key](old_name):subscribe(function(old_params)
if (old_params) then
local new_params = extend(old_params, params or {})
print("Extending "..old_name.." to "..new_name..".")
-- At least try to prevent infinite loops
if (old_name == new_name) then
mt_native["register_"..key](":"..san_name, new_params)
else
minetest["register_"..key](":"..san_name, new_params)
end
end
end)
end
end

1
modpack.txt Normal file
View File

@ -0,0 +1 @@
The presence of this file indicates that the current folder is a modpack.