diff --git a/Audio/Collapse.ogg b/Audio/Collapse.ogg new file mode 100644 index 0000000..2041364 Binary files /dev/null and b/Audio/Collapse.ogg differ diff --git a/Audio/Creaky.ogg b/Audio/Creaky.ogg new file mode 100644 index 0000000..5c96307 Binary files /dev/null and b/Audio/Creaky.ogg differ diff --git a/Audio/Deadly Sorrow.ogg b/Audio/Deadly Sorrow.ogg new file mode 100644 index 0000000..818f791 Binary files /dev/null and b/Audio/Deadly Sorrow.ogg differ diff --git a/Audio/Don't Die on Me.ogg b/Audio/Don't Die on Me.ogg new file mode 100644 index 0000000..b1b1a76 Binary files /dev/null and b/Audio/Don't Die on Me.ogg differ diff --git a/Audio/Laugh.ogg b/Audio/Laugh.ogg new file mode 100644 index 0000000..e3daee4 Binary files /dev/null and b/Audio/Laugh.ogg differ diff --git a/Audio/Lost World - myuu.ogg b/Audio/Lost World - myuu.ogg new file mode 100644 index 0000000..3e95504 Binary files /dev/null and b/Audio/Lost World - myuu.ogg differ diff --git a/Audio/The End Is Always Near.ogg b/Audio/The End Is Always Near.ogg new file mode 100644 index 0000000..8905381 Binary files /dev/null and b/Audio/The End Is Always Near.ogg differ diff --git a/Audio/What Could Have Been.ogg b/Audio/What Could Have Been.ogg new file mode 100644 index 0000000..072857d Binary files /dev/null and b/Audio/What Could Have Been.ogg differ diff --git a/Audio/Yawn.ogg b/Audio/Yawn.ogg new file mode 100644 index 0000000..f952bce Binary files /dev/null and b/Audio/Yawn.ogg differ diff --git a/Audio/alarm.ogg b/Audio/alarm.ogg new file mode 100644 index 0000000..d4bdaa3 Binary files /dev/null and b/Audio/alarm.ogg differ diff --git a/Audio/bed.ogg b/Audio/bed.ogg new file mode 100644 index 0000000..51ac852 Binary files /dev/null and b/Audio/bed.ogg differ diff --git a/Audio/boyknife.ogg b/Audio/boyknife.ogg new file mode 100644 index 0000000..5f8ee76 Binary files /dev/null and b/Audio/boyknife.ogg differ diff --git a/Audio/footsteps.ogg b/Audio/footsteps.ogg new file mode 100644 index 0000000..8e53815 Binary files /dev/null and b/Audio/footsteps.ogg differ diff --git a/Audio/hmm.ogg b/Audio/hmm.ogg new file mode 100644 index 0000000..02ded82 Binary files /dev/null and b/Audio/hmm.ogg differ diff --git a/Audio/knife.ogg b/Audio/knife.ogg new file mode 100644 index 0000000..b98fa18 Binary files /dev/null and b/Audio/knife.ogg differ diff --git a/Audio/over.ogg b/Audio/over.ogg new file mode 100644 index 0000000..d9635c0 Binary files /dev/null and b/Audio/over.ogg differ diff --git a/Audio/paper.ogg b/Audio/paper.ogg new file mode 100644 index 0000000..12d34c7 Binary files /dev/null and b/Audio/paper.ogg differ diff --git a/Audio/pots.ogg b/Audio/pots.ogg new file mode 100644 index 0000000..f8341f0 Binary files /dev/null and b/Audio/pots.ogg differ diff --git a/Audio/select.ogg b/Audio/select.ogg new file mode 100644 index 0000000..4e8fb46 Binary files /dev/null and b/Audio/select.ogg differ diff --git a/Audio/sigh.ogg b/Audio/sigh.ogg new file mode 100644 index 0000000..b5650ec Binary files /dev/null and b/Audio/sigh.ogg differ diff --git a/Audio/stairs.ogg b/Audio/stairs.ogg new file mode 100644 index 0000000..b512df1 Binary files /dev/null and b/Audio/stairs.ogg differ diff --git a/Audio/store.ogg b/Audio/store.ogg new file mode 100644 index 0000000..ad45b54 Binary files /dev/null and b/Audio/store.ogg differ diff --git a/Audio/twisted.ogg b/Audio/twisted.ogg new file mode 100644 index 0000000..b0b09dd Binary files /dev/null and b/Audio/twisted.ogg differ diff --git a/GuiManager/Core/Clickable.int b/GuiManager/Core/Clickable.int new file mode 100644 index 0000000..f192d8e --- /dev/null +++ b/GuiManager/Core/Clickable.int @@ -0,0 +1,15 @@ +function gui:Clickable() + local x,y,w,h=love.graphics.getScissor() + local mx=love.mouse.getX() + local my=love.mouse.getY() + if _GuiPro.HasStencel then + local obj=_GuiPro.StencelHolder + if self:isDescendant(obj) then + return math.sqrt((mx-obj.x)^2+(my-obj.y)^2)<=(obj.offset.size.x or 0) + end + end + if not(x) then + return true + end + return not(mx>x+w or mxy+h or myx+w or mxy+h or my self.x and x < self.x+self.width and y > self.y and y < self.y+self.height and self:TClickable(x,y) and self:eventable()) + end + end + self.id=-1 +end +multi:newTask(function() -- A bit of post-loading haha + gui.touchpressed=multi:newConnection() + gui.touchreleased=multi:newConnection() + gui.touchmoved=multi:newConnection() + love.touchpressed=Library.convert(love.touchpressed or function() end) + love.touchreleased=Library.convert(love.touchreleased or function() end) + love.touchmoved=Library.convert(love.touchmoved or function() end) + love.touchpressed:inject(function(id, x, y, dx, dy, pressure) gui.touchpressed:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) + love.touchreleased:inject(function(id, x, y, dx, dy, pressure) gui.touchreleased:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) + love.touchmoved:inject(function(id, x, y, dx, dy, pressure) gui.touchmoved:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) + _GuiPro.TouchReady=true + _GuiPro.TouchRegister={} + gui.touchpressed:connect(function(id, x, y, dx, dy, pressure) + for i,v in pairs(_GuiPro.TouchRegister) do + if #v.tid==0 then + if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then + v:addTID(id) + v.touchcount=1 + for i=1,#v.ToFuncP do + v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + elseif not(v:hasTID(id)) then + if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then + v:addTID(id) + v.touchcount=v.touchcount+1 + for i=1,#v.ToFuncP do + v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + end + end + end) + gui.touchreleased:connect(function(id, x, y, dx, dy, pressure) + for i,v in pairs(_GuiPro.TouchRegister) do + if v:hasTID(id) then + v:removeTID(id) + for i=1,#v.ToFuncR do + v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + end + end) + gui.touchmoved:connect(function(id, x, y, dx, dy, pressure) + for i,v in pairs(_GuiPro.TouchRegister) do + if v:hasTID(id) and (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then + for i=1,#v.ToFuncM do + v.ToFuncM[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + elseif v:hasTID(id) and not((x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable())) then + v:removeTID(id) + for i=1,#v.ToFuncR do + v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + end + end) +end) +-- now that that is done lets set up some more post loading checks +_GuiPro.int=multi:newProcess() +_GuiPro.int:Start() +_GuiPro.int:setJobSpeed(.001) +_GuiPro.EXACT=0 +_GuiPro.LAX=.01 +_GuiPro.LAZY=.05 +-- now lets define the reg function +function gui.Compare(a,b,v,tp) + if tp==">" then + if (a+v>b or a-v>b) then + return true + end + elseif tp=="<" then + if (a+v=" then + if (a+v>=b or a-v>=b) then + return true + end + elseif tp=="==" then -- this one is gonna be tricky + if (a>=b-v and a<=b+v) or (b>=a-v and b<=a+v) then + return true + end + end + return false +end +function gui:regesterTouch() + local obj=self + obj.ToFuncP={} + obj.ToFuncM={} + obj.ToFuncR={} + obj.To2Func={} + obj.ToDTFunc={} + obj.touchRendering =_GuiPro.EXACT -- exact(0), lax(), # + function obj:removeTID(id) + for i=1,#self.tid do + if self.tid[i]==id then + table.remove(self.tid,i) + self.touchcount=self.touchcount-1 + return + end + end + end + function obj:hasTID(id) + for i=1,#self.tid do + if self.tid[i]==id then + return true + end + end + return false + end + obj.txl1=0 + obj.tyl1=0 + obj.txl2=0 + obj.tyl2=0 + obj.LS=0 + obj:OnUpdate(function(self) + if self.touchcount==2 then + local x1,y1=love.touch.getPosition( self.tid[1] ) + local x2,y2=love.touch.getPosition( self.tid[2] ) + local CS=math.sqrt((x2-x1)^2+(y2-y1)^2) + if gui.Compare(CS,self.LS,self.touchRendering,">") then + for i=1,#self.To2Func do + self.To2Func[i](self,CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + end + elseif gui.Compare(CS,self.LS,self.touchRendering,"<") then + for i=1,#self.To2Func do + self.To2Func[i](self,-CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + end + elseif gui.Compare(CS,self.LS,self.touchRendering,"==") then + for i=1,#self.To2Func do + self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + end + end + -- if self.txl1~=x1 or self.txl2~=x2 or self.tyl1~=y1 or self.tyl2~=y2 then + -- for i=1,#self.To2Func do + -- self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + -- end + -- end + self.LS=CS + self.txl1=x1 + self.txl2=x2 + self.tyl1=y1 + self.tyl2=y2 + end + end) + function obj:OnDoubleTap(func) + table.insert(self.ToDTFunc,func) + end + function obj:On2TouchMoved(func) + table.insert(self.To2Func,func) + end + function obj:addTID(id) + table.insert(self.tid,id) + end + function obj:OnTouchPressed(func) + table.insert(self.ToFuncP,func) -- event for touches + end + function obj:OnTouchReleased(func) -- event for touches + table.insert(self.ToFuncR,func) + end + function obj:OnTouchMoved(func) -- event for touches + table.insert(self.ToFuncM,func) + end + if _GuiPro.TouchReady then -- my sneaky test + print("Registred: "..tostring(obj)) + table.insert(_GuiPro.TouchRegister,obj) + else + print("Attempting to register: "..tostring(obj)) + _GuiPro.int:newJob(function() table.insert(_GuiPro.TouchRegister,obj) end) -- a sneaky way to ensure that your object gets registered eventually, even if you call the method before the touch patch was activated. + end +end diff --git a/GuiManager/Drawing/AddDrawRuleB.int b/GuiManager/Drawing/AddDrawRuleB.int new file mode 100644 index 0000000..5510a3d --- /dev/null +++ b/GuiManager/Drawing/AddDrawRuleB.int @@ -0,0 +1,4 @@ +function gui:AddDrawRuleB(rule) + if not(self.DrawRulesB) then self.DrawRulesB={} end + table.insert(self.DrawRulesB,rule) +end \ No newline at end of file diff --git a/GuiManager/Drawing/AddDrawRuleE.int b/GuiManager/Drawing/AddDrawRuleE.int new file mode 100644 index 0000000..a025f89 --- /dev/null +++ b/GuiManager/Drawing/AddDrawRuleE.int @@ -0,0 +1,4 @@ +function gui:AddDrawRuleE(rule) + if not(self.DrawRulesE) then self.DrawRulesE={} end + table.insert(self.DrawRulesE,rule) +end \ No newline at end of file diff --git a/GuiManager/Drawing/draw.int b/GuiManager/Drawing/draw.int new file mode 100644 index 0000000..d0b2404 --- /dev/null +++ b/GuiManager/Drawing/draw.int @@ -0,0 +1,12 @@ +function gui:draw() + if _GuiPro.rotate~=0 then + love.graphics.rotate(math.rad(_GuiPro.rotate)) + end + if self.FormFactor:lower()=="rectangle" then + self:drawR() + elseif self.FormFactor:lower()=="circle" then + self:drawC() + else + error("Unsupported FormFactor: "..self.FormFactor.."!") + end +end \ No newline at end of file diff --git a/GuiManager/Drawing/drawC.int b/GuiManager/Drawing/drawC.int new file mode 100644 index 0000000..84592b5 --- /dev/null +++ b/GuiManager/Drawing/drawC.int @@ -0,0 +1,89 @@ +function gui:drawC() + if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then + _GuiPro.DragItem={} + _GuiPro.hasDrag=false + end + if self.Visible==true and self.VIS==true then + local b=true + for i,v in pairs(_GuiPro.Clips) do + if self:isDescendant(v)==true then + b=false + end + end + if b then + love.graphics.setStencilTest( ) + _GuiPro.HasStencel=false + _GuiPro.StencelHolder=nil + end + local x,y,r,s=(self.offset.pos.x or 0)+self.Parent.x,(self.offset.pos.y or 0)+self.Parent.y,self.offset.size.x or 0,self.offset.size.y or 360 + if self.CC then + x,y=x+r,y+r + end + self.x,self.y=x,y + _GuiPro.circleStencilFunction = function() + love.graphics.circle("fill",x,y,r,s) + end + if math.sqrt((love.mouse.getX()-x)^2+(love.mouse.getY()-y)^2)<=r and self:eventable() and self:Clickable() and self.Active==true then + self.hovering=true + if love.mouse.isDown("l") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.lclicked=true + elseif love.mouse.isDown("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=true + elseif love.mouse.isDown("m") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.mclicked=true + else + if string.find(self.Type, "Button") and _GuiPro.hasDrag==false then + love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + self.hovering=false + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + if self.ClipDescendants==true then + _GuiPro.Clips[tostring(self)]=self + _GuiPro.HasStencel=true + _GuiPro.StencelHolder=self + love.graphics.stencil(_GuiPro.circleStencilFunction) + love.graphics.setStencilTest("notequal",0) + end + love.graphics.circle("fill",x,y,r,s) + love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.Visibility*254) + for b=0,self.BorderSize-1 do + love.graphics.circle("line",x,y,r+b,s) + end + if string.find(self.Type, "Text") then + if self.text~=nil then + if self.AutoScaleText then + self.FontSize=math.floor(self.height/1.45833) + end + love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) + love.graphics.setFont(self.Font) + love.graphics.printf(self.text, x-(r/2)+(self.XTween), y-(r/2)+self.Tween, r, self.TextFormat) + end + end + end +end \ No newline at end of file diff --git a/GuiManager/Drawing/drawR.int b/GuiManager/Drawing/drawR.int new file mode 100644 index 0000000..33a1d0c --- /dev/null +++ b/GuiManager/Drawing/drawR.int @@ -0,0 +1,118 @@ +function gui:drawR() + if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then + _GuiPro.DragItem={} + _GuiPro.hasDrag=false + end + if self.Visible==true and self.VIS==true then + local b=true + for i,v in pairs(_GuiPro.Clips) do + if self:isDescendant(v)==true then + b=false + end + end + if b==true then + love.graphics.setStencilTest() + love.graphics.setScissor() + end + self.x=(self.Parent.width*self.scale.pos.x)+self.offset.pos.x+self.Parent.x + self.y=(self.Parent.height*self.scale.pos.y)+self.offset.pos.y+self.Parent.y + self.width=(self.Parent.width*self.scale.size.x)+self.offset.size.x + self.height=(self.Parent.height*self.scale.size.y)+self.offset.size.y + if self.DrawRulesB then + for dr=1,#self.DrawRulesB do + self.DrawRulesB[dr](self) + end + end + if (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height and self:Clickable() and self:eventable()) or self:touchable("r") and self.Active==true then + self.hovering=true + if love.mouse.isDown("l") or self:touchable("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.lclicked=true + elseif love.mouse.isDown("r") or self:touchable("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=true + elseif love.mouse.isDown("m") or self:touchable("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.mclicked=true + else + if string.find(self.Type, "Button") or self:touchable("r") and _GuiPro.hasDrag==false then + love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + self.hovering=false + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + if self.ClipDescendants==true then + _GuiPro.Clips[tostring(self)]=self + love.graphics.setScissor(self.x, self.y, self.width, self.height) + end + if self:hasRoundness() then + love.graphics.stencil(self.stfunc, "replace", 1) + love.graphics.setStencilTest("greater", 0) + end + love.graphics.rectangle("fill", self.x, self.y, self.width, self.height,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) + if string.find(self.Type, "Image") then + self:ImageRule() + end + if self.Type=="Video" then + self:VideoRule() + end + if self:hasRoundness() then + love.graphics.setStencilTest() + end + love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.Visibility*254) + for b=0,self.BorderSize-1 do + love.graphics.rectangle("line", self.x-(b/2), self.y-(b/2), self.width+b, self.height+b,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) + end + if string.find(self.Type, "Text") then + if self.text~=nil then + if self.AutoScaleText then + self.FontSize=math.floor(self.height/1.45833) + end + love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) + if self.Font==_defaultfont then + love.graphics.setFont(self.Font) + love.graphics.printf(self.text, self.x+2+(self.XTween*self.DPI)+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+(self.FontHeight/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) + else + if type(self.Font)=="string" then + self.Font=love.graphics.newFont(self.Font,self.FontSize) + self.FontHeight=self.Font:getHeight() + else + love.graphics.setFont(self.Font) + end + if type(self.FontSize)=="string" then + self.FontSize=tonumber(self.FontSize) + love.graphics.setNewFont(self.FontSize) + end + love.graphics.printf(self.text, self.x+2+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+math.floor((self.FontHeight-self.FontSize)/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) + end + end + end + if self.DrawRulesE then + for dr=1,#self.DrawRulesE do + self.DrawRulesE[dr](self) + end + end + end +end \ No newline at end of file diff --git a/GuiManager/Frame/newDropFrame.int b/GuiManager/Frame/newDropFrame.int new file mode 100644 index 0000000..97e4720 --- /dev/null +++ b/GuiManager/Frame/newDropFrame.int @@ -0,0 +1,37 @@ +function gui:newDropFrame(name,x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("DropFrame",name, x, y, w, h, sx ,sy ,sw ,sh) + c.WasBeingDragged=false + c.IsBeingDragged=false + c.Draggable=false + c.funcD={} + function c:GetDroppedItems() + local t=self:getChildren() + local tab={} + for i=1,#t do + if t[i].Type=="TextImageButtonFrameDrag" then + table.insert(tab,t[i]) + end + end + return tab + end + function c:OnDropped(func) + table.insert(self.funcD,func) + end + c:OnUpdate(function(self) + if _GuiPro.DragItem then + if _GuiPro.DragItem.Type=="TextImageButtonFrameDrag" and love.mouse.isDown(_GuiPro.DragItem.dragbut or "m")==false and self:IsHovering() then + local t=_GuiPro.DragItem + _GuiPro.DragItem={} + for i=1,#t.funcD do + t.funcD[i](self,t) + end + for i=1,#self.funcD do + self.funcD[i](self,t) + end + _GuiPro.hasDrag=false + end + end + end) + return c +end \ No newline at end of file diff --git a/GuiManager/Frame/newFrame.int b/GuiManager/Frame/newFrame.int new file mode 100644 index 0000000..5e6b084 --- /dev/null +++ b/GuiManager/Frame/newFrame.int @@ -0,0 +1,8 @@ +function gui:newFrame(name,x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("Frame",name, x, y, w, h, sx ,sy ,sw ,sh) + c.WasBeingDragged=false + c.IsBeingDragged=false + c.Draggable=false + return c +end \ No newline at end of file diff --git a/GuiManager/Frame/newFullFrame.int b/GuiManager/Frame/newFullFrame.int new file mode 100644 index 0000000..5cda200 --- /dev/null +++ b/GuiManager/Frame/newFullFrame.int @@ -0,0 +1,4 @@ +function gui:newFullFrame(name) + name=name or "" + return self:newFrame(name,0,0,0,0,0,0,1,1) +end \ No newline at end of file diff --git a/GuiManager/Frame/newTabFrame.int b/GuiManager/Frame/newTabFrame.int new file mode 100644 index 0000000..9f8f8fe --- /dev/null +++ b/GuiManager/Frame/newTabFrame.int @@ -0,0 +1,59 @@ +function gui:newTabFrame(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=gui:newFrame(name, x, y, w, h, sx ,sy ,sw ,sh) + c.tabheight=20 + c.Holder=c:newFrame("Holder",0,c.tabheight,0,0,0,0,1,1) + c.TabHolder=c:newFrame("TabHolder",0,0,0,c.tabheight,0,0,1) + function c:setTabHeight(n) + self.tabheight=n + self.Holder:SetDualDim(0,-self.tabheight,0,0,0,0,1,1) + end + function c:addTab(name,colorT,colorH) + if colorT and not(colorH) then + colorH=colorT + end + local tab=self.TabHolder:newTextButton(name,name,0,0,0,0,0,0,0,1) + tab.Tween=-3 + if colorT then + tab.Color=colorT + end + local holder=self.Holder:newFrame(name,0,0,0,0,0,0,1,1) + if colorH then + holder.Color=colorH + end + tab.frame=holder + tab:OnReleased(function(b,self) + if b=="l" then + local tt=self.Parent:getChildren() + local th=self.Parent.Parent.Holder:getChildren() + for i=1,#th do + th[i].Visible=false + end + for i=1,#tt do + tt[i].frame.Visible=false + tt[i].BorderSize=1 + end + self.BorderSize=0 + self.frame.Visible=true + end + end) + local tt=self.TabHolder:getChildren() + for i=1,#tt do + tt[i].frame.Visible=false + tt[i].BorderSize=1 + end + tab.frame.Visible=true + tab.BorderSize=0 + return tab,holder + end + c:OnUpdate(function(self) + local th=self.TabHolder:getChildren() + local l=self.width/#th + for i=1,#th do + th[i]:SetDualDim(l*(i-1),0,l) + end + if #th==0 then + self:Destroy() + end + end) + return c +end \ No newline at end of file diff --git a/GuiManager/Frame/newratioFrame.int b/GuiManager/Frame/newratioFrame.int new file mode 100644 index 0000000..e69de29 diff --git a/GuiManager/Image-Animation/SetImage.int b/GuiManager/Image-Animation/SetImage.int new file mode 100644 index 0000000..d0d5f78 --- /dev/null +++ b/GuiManager/Image-Animation/SetImage.int @@ -0,0 +1,13 @@ +function gui:SetImage(i) + if type(i)=="string" then + self.Image=love.graphics.newImage(i) + else + self.Image=i + end + if self.Image~=nil then + self.ImageHeigth=self.Image:getHeight() + self.ImageWidth=self.Image:getWidth() + self.Quad=love.graphics.newQuad(0,0,self.width,self.height,self.ImageWidth,self.ImageHeigth) + end + return self.ImageWidth,self.ImageHeigth +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/UpdateImage.int b/GuiManager/Image-Animation/UpdateImage.int new file mode 100644 index 0000000..be4cfd7 --- /dev/null +++ b/GuiManager/Image-Animation/UpdateImage.int @@ -0,0 +1,5 @@ +function gui:UpdateImage() + self.ImageHeigth=self.Image:getHeight() + self.ImageWidth=self.Image:getWidth() + self.Quad=love.graphics.newQuad(0,0,self.width,self.height,self.ImageWidth,self.ImageHeigth) +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/getTile.int b/GuiManager/Image-Animation/getTile.int new file mode 100644 index 0000000..6b6fcae --- /dev/null +++ b/GuiManager/Image-Animation/getTile.int @@ -0,0 +1,20 @@ +function gui:getTile(i,x,y,w,h)-- returns imagedata + if type(i)=="string" then + i=love.graphics.newImage(i) + elseif type(i)=="userdata" then + -- do nothing + elseif string.find(self.Type,"Image",1,true) then + local i,x,y,w,h=self.Image,i,x,y,w + else + error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") + end + local iw,ih=i:getDimensions() + local id,_id=i:getData(),love.image.newImageData(w,h) + for _x=x,w+x-1 do + for _y=y,h+y-1 do + -- + _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) + end + end + return love.graphics.newImage(_id) +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newAnim.int b/GuiManager/Image-Animation/newAnim.int new file mode 100644 index 0000000..30850aa --- /dev/null +++ b/GuiManager/Image-Animation/newAnim.int @@ -0,0 +1,57 @@ +function gui:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) + local x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) + c.Visibility=0 + c.ImageVisibility=1 + c.delay=delay or .05 + c.files={} + c.AnimStart={} + c.AnimEnd={} + local _files=alphanumsort(love.filesystem.getDirectoryItems(file)) + for i=1,#_files do + if string.sub(_files[i],-1,-1)~="b" then + table.insert(c.files,love.graphics.newImage(file.."/".._files[i])) + end + end + c.step=multi:newTStep(1,#c.files,1,c.delay) + c.step.parent=c + c.rotation=0 + c.step:OnStart(function(step) + for i=1,#step.parent.AnimStart do + step.parent.AnimStart[i](step.parent) + end + end) + c.step:OnStep(function(pos,step) + step.parent:SetImage(step.parent.files[pos]) + end) + c.step:OnEnd(function(step) + for i=1,#step.parent.AnimEnd do + step.parent.AnimEnd[i](step.parent) + end + end) + function c:OnAnimStart(func) + table.insert(self.AnimStart,func) + end + function c:OnAnimEnd(func) + table.insert(self.AnimEnd,func) + end + function c:Pause() + self.step:Pause() + end + function c:Resume() + self.step:Resume() + end + function c:Reset() + self.step.pos=1 + end + function c:getFrames() + return #self.files + end + function c:getFrame() + return self.step.pos + end + function c:setFrame(n) + return self:SetImage(self.files[n]) + end + return c +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newAnimFromData.int b/GuiManager/Image-Animation/newAnimFromData.int new file mode 100644 index 0000000..02c85c7 --- /dev/null +++ b/GuiManager/Image-Animation/newAnimFromData.int @@ -0,0 +1,52 @@ +function gui:newAnimFromData(data,delay, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageAnimation","FromFile", x, y, w, h, sx ,sy ,sw ,sh) + c.Visibility=0 + c.ImageVisibility=1 + c.delay=delay or .05 + c.files=data + c.AnimStart={} + c.AnimEnd={} + c:SetImage(c.files[1]) + c.step=multi:newTStep(1,#c.files,1,c.delay) + c.step.parent=c + c.rotation=0 + c.step:OnStart(function(step) + for i=1,#step.parent.AnimStart do + step.parent.AnimStart[i](step.parent) + end + end) + c.step:OnStep(function(pos,step) + step.parent:SetImage(step.parent.files[pos]) + end) + c.step:OnEnd(function(step) + for i=1,#step.parent.AnimEnd do + step.parent.AnimEnd[i](step.parent) + end + end) + function c:OnAnimStart(func) + table.insert(self.AnimStart,func) + end + function c:OnAnimEnd(func) + table.insert(self.AnimEnd,func) + end + function c:Pause() + self.step:Pause() + end + function c:Resume() + self.step:Resume() + end + function c:Reset() + self.step.pos=1 + end + function c:getFrames() + return #self.files + end + function c:getFrame() + return self.step.pos + end + function c:setFrame(n) + return self:SetImage(self.files[n]) + end + return c +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newAnimFromTiles.int b/GuiManager/Image-Animation/newAnimFromTiles.int new file mode 100644 index 0000000..70aea2c --- /dev/null +++ b/GuiManager/Image-Animation/newAnimFromTiles.int @@ -0,0 +1,59 @@ +function gui:newAnimFromTiles(file,xd,yd,delay, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) + local im=love.graphics.newImage(file) + local _x,_y=im:getDimensions() + c.Visibility=0 + c.ImageVisibility=1 + c.delay=delay or .05 + c.files={} + c.AnimStart={} + c.AnimEnd={} + for i=0,_y/yd-1 do + for j=0,_x/xd-1 do + table.insert(c.files,gui:getTile(im,j*xd,i*yd,xd,yd)) + end + end + c:SetImage(c.files[1]) + c.step=multi:newTStep(1,#c.files,1,c.delay) + c.step.parent=c + c.rotation=0 + c.step:OnStart(function(step) + for i=1,#step.parent.AnimStart do + step.parent.AnimStart[i](step.parent) + end + end) + c.step:OnStep(function(pos,step) + step.parent:SetImage(step.parent.files[pos]) + end) + c.step:OnEnd(function(step) + for i=1,#step.parent.AnimEnd do + step.parent.AnimEnd[i](step.parent) + end + end) + function c:OnAnimStart(func) + table.insert(self.AnimStart,func) + end + function c:OnAnimEnd(func) + table.insert(self.AnimEnd,func) + end + function c:Pause() + self.step:Pause() + end + function c:Resume() + self.step:Resume() + end + function c:Reset() + self.step.pos=1 + end + function c:getFrames() + return #self.files + end + function c:getFrame() + return self.step.pos + end + function c:setFrame(n) + return self:SetImage(self.files[n]) + end + return c +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newFullImageLabel.int b/GuiManager/Image-Animation/newFullImageLabel.int new file mode 100644 index 0000000..953f480 --- /dev/null +++ b/GuiManager/Image-Animation/newFullImageLabel.int @@ -0,0 +1,3 @@ +function gui:newFullImageLabel(i,name) + return self:newImageLabel(i,name,0,0,0,0,0,0,1,1) +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newImageButton.int b/GuiManager/Image-Animation/newImageButton.int new file mode 100644 index 0000000..6d0e51d --- /dev/null +++ b/GuiManager/Image-Animation/newImageButton.int @@ -0,0 +1,25 @@ +function gui:newImageButton(i,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageButton",name, x, y, w, h, sx ,sy ,sw ,sh) + if type(i)=="string" then + c.Image=love.graphics.newImage(i) + else + c.Image=i + end + c.Visibility=0 + c.ImageVisibility=1 + c.rotation=0 + if c.Image~=nil then + c.ImageHeigth=c.Image:getHeight() + c.ImageHeight=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + end + c:OnEnter(function() + love.mouse.setCursor(_GuiPro.CursorH) + end) + c:OnExit(function() + love.mouse.setCursor(_GuiPro.CursorN) + end) + return c +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newImageLabel.int b/GuiManager/Image-Animation/newImageLabel.int new file mode 100644 index 0000000..47323e1 --- /dev/null +++ b/GuiManager/Image-Animation/newImageLabel.int @@ -0,0 +1,18 @@ +function gui:newImageLabel(i,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageLabel",name, x, y, w, h, sx ,sy ,sw ,sh) + if type(i)=="string" then + c.Image=love.graphics.newImage(i) + else + c.Image=i + end + c.Visibility=0 + c.ImageVisibility=1 + c.rotation=0 + if c.Image~=nil then + c.ImageHeigth=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + end + return c +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newVideo.int b/GuiManager/Image-Animation/newVideo.int new file mode 100644 index 0000000..de2c379 --- /dev/null +++ b/GuiManager/Image-Animation/newVideo.int @@ -0,0 +1,62 @@ +function gui:newVideo(name,i,x,y,w,h,sx,sy,sw,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("Video",name, x, y, w, h, sx ,sy ,sw ,sh) + if type(i)=="string" then + c.Video=love.graphics.newVideo(i) + else + c.Video=i + end + c.Visibility=0 + c.VideoVisibility=1 + c.rotation=0 + if c.Video~=nil then + c.VideoHeigth=c.Video:getHeight() + c.VideoWidth=c.Video:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.VideoWidth,c.VideoHeigth) + end + c.funcV={} + function c:Play() + self.handStart=true + self.Video:play() + end + function c:Pause() + self.Video:pause() + end + c.Resume=c.Play + function c:Stop() + self.handStart=false + self:Pause() + self:Rewind() + for i=1,# self.funcV do + self.funcV[i](self) + end + end + function c:OnVideoStopped(func) + table.insert(self.funcV,func) + end + function c:Rewind() + self.Video:rewind() + end + function c:Restart() + self:Rewind() + self:Play() + end + function c:Seek(o) + self.Video:seek(o) + end + function c:Tell() + self.Video:tell() + end + function c:SetFilter(min, mag, anisotropy) + self.Video:setFilter(min, mag, anisotropy) + end + function c:IsPlaying() + return self.Video:isPlaying() + end + c:OnUpdate(function(self) + if self.Video:isPlaying()==false and self.handStart == true then + self:Stop() + end + end) + return c +end \ No newline at end of file diff --git a/GuiManager/Item/newDragItem.int b/GuiManager/Item/newDragItem.int new file mode 100644 index 0000000..162341c --- /dev/null +++ b/GuiManager/Item/newDragItem.int @@ -0,0 +1,51 @@ +function gui:newDragItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextImageButtonFrameDrag",name, x, y, w, h, sx ,sy ,sw ,sh) + c.WasBeingDragged=false + c.IsBeingDragged=false + c.Draggable=true + c.funcD={} + if type(i)=="string" then + c.Image=love.graphics.newImage(i) + c.ImageVisibility=1 + c.ImageHeigth=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + elseif type(i)=="image" then + c.Image=i + c.ImageVisibility=1 + c.ImageHeigth=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + end + c:OnDragStart(function(self,x,y) + if _GuiPro.hasDrag==false then + self:setParent(_GuiPro) + self:SetDualDim(x,y) + self:TopStack() + end + end) + c.rotation=0 + c.Tween=0 + c.XTween=0 + c.text = t + c.AutoScaleText=false + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.TextVisibility=1 + c.TextColor = {0, 0, 0} + function c:OnDropped(func) + table.insert(self.funcD,func) + end + c:OnUpdate(function(self) + if love.mouse.isDown("m" or self.dragbut)==false and self==_GuiPro.DragItem and self.hovering==false then + _GuiPro.DragItem={} + for i=1,#self.func7 do + self.func7[i](self,(love.mouse.getX())-self.width/2,(love.mouse.getY())-self.height/2) + end + end + end) + return c +end \ No newline at end of file diff --git a/GuiManager/Item/newItem.int b/GuiManager/Item/newItem.int new file mode 100644 index 0000000..57a68d5 --- /dev/null +++ b/GuiManager/Item/newItem.int @@ -0,0 +1,28 @@ +function gui:newItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextImageButtonFrame",name, x, y, w, h, sx ,sy ,sw ,sh) + if type(i)=="string" then + c.Image=love.graphics.newImage(i) + else + c.Image=i + end + c.rotation=0 + c.ImageVisibility=1 + c.Draggable=false + if c.Image~=nil then + c.ImageHeigth=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + end + c.Tween=0 + c.XTween=0 + c.text = t + c.AutoScaleText=false + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) + c.TextColor = {0, 0, 0} + return c +end \ No newline at end of file diff --git a/GuiManager/Misc/AdvTextBox.int b/GuiManager/Misc/AdvTextBox.int new file mode 100644 index 0000000..08a3499 --- /dev/null +++ b/GuiManager/Misc/AdvTextBox.int @@ -0,0 +1,45 @@ +function gui:AdvTextBox(txt,x,y,w,h,sx,sy,sw,sh) + name="AdvTextBox" + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("AdvTextBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) + c.Draggable=true + c.dragbut="r" + c.BorderSize=0 + c:ApplyGradient{Color.Blue,Color.sexy_purple} + c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple + c.funcO={} + c.funcX={} + c:OnDragStart(function(self) + self:TopStack() + end) + --local temp = c:newTextButton("X","Close",-25,5,20,20,1) + --temp.Tween=-5 + --temp.XTween=-2 + --temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) + --temp.Color=Color.Red + c.tLink=c:newTextBox("puttext","TextBox",5,h-95,-40,30,0,1,1,1) + c.tLink.Color=Color.light_gray + c.tLink.ClearOnFocus=true + c.tLink:OnFocus(function(self) self.ClearOnFocus=false end) + local temp=c:newTextButton("OK","Ok",-35,h-65,30,30,1,1) + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent,self.Parent.tLink.text) end end) + temp.Color=Color.Green + temp.XTween=-2 + local temp=c:newTextButton("X","Cancel",-35,h-95,30,30,1,1) + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent,self.Parent.tLink.text) end end) + temp.Color=Color.Red + temp.XTween=-2 + function c:Close() + self.Visible=false + end + function c:Open() + self.Visible=true + end + function c:OnOk(func) + table.insert(self.funcO,func) + end + function c:OnX(func) + table.insert(self.funcX,func) + end + return c +end \ No newline at end of file diff --git a/GuiManager/Misc/ApplyGradient.int b/GuiManager/Misc/ApplyGradient.int new file mode 100644 index 0000000..e092739 --- /dev/null +++ b/GuiManager/Misc/ApplyGradient.int @@ -0,0 +1,36 @@ +function _GuiPro.gradient(colors) + local direction = colors.direction or "horizontal" + colors.direction=nil + trans = colors.trans or 255 + trans=math.floor(trans) + if direction == "horizontal" then + direction = true + elseif direction == "vertical" then + direction = false + else + error("Invalid direction '" .. tostring(direction) "' for gradient. Horizontal or vertical expected.") + end + local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1) + for __i, color in ipairs(colors) do + local x, y + if direction then + x, y = 0, __i - 1 + else + x, y = __i - 1, 0 + end + result:setPixel(x, y, color[1], color[2], color[3], trans) + end + result = love.graphics.newImage(result) + result:setFilter('linear', 'linear') + return result +end +function _GuiPro.drawinrect(img, x, y, w, h, r, ox, oy, kx, ky) + love.graphics.draw(img, x, y, r, w / img:getWidth(), h / img:getHeight(), ox, oy, kx, ky) +end +function gui:ApplyGradient(rules) + self.Image=nil + self.Type=self.Type.."w/GradImage" + self.rotation=0 + self.ImageVisibility=rules.visibility or 1 + self:SetImage(_GuiPro.gradient(rules)) +end \ No newline at end of file diff --git a/GuiManager/Misc/BottomStack.int b/GuiManager/Misc/BottomStack.int new file mode 100644 index 0000000..b339ec4 --- /dev/null +++ b/GuiManager/Misc/BottomStack.int @@ -0,0 +1,10 @@ +function gui:BottomStack() + childs=self.Parent:getChildren() + for i=1,#childs do + if childs[i]==self then + table.remove(self.Parent.Children,i) + table.insert(self.Parent.Children,1,self) + break + end + end +end \ No newline at end of file diff --git a/GuiManager/Misc/Center.int b/GuiManager/Misc/Center.int new file mode 100644 index 0000000..0089c93 --- /dev/null +++ b/GuiManager/Misc/Center.int @@ -0,0 +1,4 @@ +function gui:Center() + local x,y=self:getFullSize() + self:SetDualDim(-math.floor(x/2),-math.floor(y/2),nil,nil,.5,.5) +end \ No newline at end of file diff --git a/GuiManager/Misc/Destroy.int b/GuiManager/Misc/Destroy.int new file mode 100644 index 0000000..9c524f1 --- /dev/null +++ b/GuiManager/Misc/Destroy.int @@ -0,0 +1,9 @@ +function gui:Destroy() + check=self.Parent:getChildren() + local cc=0 + for cc=1,#check do + if check[cc]==self then + table.remove(self.Parent.Children,cc) + end + end +end \ No newline at end of file diff --git a/GuiManager/Misc/GetAllChildren.int b/GuiManager/Misc/GetAllChildren.int new file mode 100644 index 0000000..b3a0ae4 --- /dev/null +++ b/GuiManager/Misc/GetAllChildren.int @@ -0,0 +1,25 @@ +function gui:GetAllChildren() + local Stuff = {} + function Seek(Items) + for i=1,#Items do + if Items[i].Visible==true then + table.insert(Stuff,Items[i]) + local NItems = Items[i]:getChildren() + if NItems ~= nil then + Seek(NItems) + end + end + end + end + local Objs = self:getChildren() + for i=1,#Objs do + if Objs[i].Visible==true then + table.insert(Stuff,Objs[i]) + local Items = Objs[i]:getChildren() + if Items ~= nil then + Seek(Items) + end + end + end + return Stuff +end \ No newline at end of file diff --git a/GuiManager/Misc/GetChild.int b/GuiManager/Misc/GetChild.int new file mode 100644 index 0000000..d434f40 --- /dev/null +++ b/GuiManager/Misc/GetChild.int @@ -0,0 +1,3 @@ +function gui:GetChild(name) + return self.Children[name] or self +end \ No newline at end of file diff --git a/GuiManager/Misc/InGrid.int b/GuiManager/Misc/InGrid.int new file mode 100644 index 0000000..4e097a7 --- /dev/null +++ b/GuiManager/Misc/InGrid.int @@ -0,0 +1,3 @@ +function InGrid(i,x,y,s) + return math.floor((i-1)/x)*s,(i-1)*s-(math.floor((i-1)/y)*(s*x)) +end \ No newline at end of file diff --git a/GuiManager/Misc/InGridX.int b/GuiManager/Misc/InGridX.int new file mode 100644 index 0000000..c4aadc2 --- /dev/null +++ b/GuiManager/Misc/InGridX.int @@ -0,0 +1,5 @@ +function InGridX(i,w,h,xs,ys) + local xc,yc=math.floor(w/xs),math.floor(h/ys) + local xi,yi=(i-1)%xc,math.floor((i-1)/xc) + return xi*xs,yi*ys +end \ No newline at end of file diff --git a/GuiManager/Misc/InGridY.int b/GuiManager/Misc/InGridY.int new file mode 100644 index 0000000..555c72a --- /dev/null +++ b/GuiManager/Misc/InGridY.int @@ -0,0 +1,5 @@ +function InGridY(i,w,h,xs,ys) + local xc,yc=math.floor(w/xs),math.floor(h/ys) + local xi,yi=math.floor((i-1)/yc),(i-1)%yc + return xi*xs,yi*ys +end \ No newline at end of file diff --git a/GuiManager/Misc/IsHovering.int b/GuiManager/Misc/IsHovering.int new file mode 100644 index 0000000..072bb54 --- /dev/null +++ b/GuiManager/Misc/IsHovering.int @@ -0,0 +1,3 @@ +function gui:IsHovering() + return (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height) +end \ No newline at end of file diff --git a/GuiManager/Misc/Move.int b/GuiManager/Misc/Move.int new file mode 100644 index 0000000..6f32db9 --- /dev/null +++ b/GuiManager/Misc/Move.int @@ -0,0 +1,4 @@ +function gui:Move(x,y) + self.offset.pos.x=self.offset.pos.x+x + self.offset.pos.y=self.offset.pos.y+y +end \ No newline at end of file diff --git a/GuiManager/Misc/SetDualDim.int b/GuiManager/Misc/SetDualDim.int new file mode 100644 index 0000000..0774965 --- /dev/null +++ b/GuiManager/Misc/SetDualDim.int @@ -0,0 +1,46 @@ +function gui:SetDualDim(x, y, w, h, sx ,sy ,sw ,sh) + if _GuiPro.DPI_ENABLED then + if x then + x=self.DPI*x + end + if y then + y=self.DPI*y + end + if w then + w=self.DPI*w + end + if h then + h=self.DPI*h + end + end + if sx then + self.scale.pos.x=sx + end + if sy then + self.scale.pos.y=sy + end + if x then + self.offset.pos.x=x + end + if y then + self.offset.pos.y=y + end + if sw then + self.scale.size.x=sw + end + if sh then + self.scale.size.y=sh + end + if w then + self.offset.size.x=w + end + if h then + self.offset.size.y=h + end + if self.Image then + self:SetImage(self.Image) + end +end +function gui:setDualDim(...) + self:SetDualDim(...) +end \ No newline at end of file diff --git a/GuiManager/Misc/SetHand.int b/GuiManager/Misc/SetHand.int new file mode 100644 index 0000000..8171f2c --- /dev/null +++ b/GuiManager/Misc/SetHand.int @@ -0,0 +1,5 @@ +_GuiPro.CursorN=love.mouse.getSystemCursor("arrow") +_GuiPro.CursorH=love.mouse.getSystemCursor("hand") +function gui:SetHand(img,x,y) + _GuiPro.CursorN=love.mouse.newCursor(img,x,y) +end \ No newline at end of file diff --git a/GuiManager/Misc/SetHover.int b/GuiManager/Misc/SetHover.int new file mode 100644 index 0000000..956e593 --- /dev/null +++ b/GuiManager/Misc/SetHover.int @@ -0,0 +1,3 @@ +function gui:SetHover(img,x,y) + _GuiPro.CursorH=love.mouse.newCursor(img,x,y) +end \ No newline at end of file diff --git a/GuiManager/Misc/SetName.int b/GuiManager/Misc/SetName.int new file mode 100644 index 0000000..1e69edd --- /dev/null +++ b/GuiManager/Misc/SetName.int @@ -0,0 +1,4 @@ +function gui:SetName(name) + self.Parent.Children[name]=self + self.Name=name +end \ No newline at end of file diff --git a/GuiManager/Misc/TopStack.int b/GuiManager/Misc/TopStack.int new file mode 100644 index 0000000..a1db016 --- /dev/null +++ b/GuiManager/Misc/TopStack.int @@ -0,0 +1,10 @@ +function gui:TopStack() + childs=self.Parent:getChildren() + for i=1,#childs do + if childs[i]==self then + table.remove(self.Parent.Children,i) + table.insert(self.Parent.Children,self) + break + end + end +end \ No newline at end of file diff --git a/GuiManager/Misc/addDominance.int b/GuiManager/Misc/addDominance.int new file mode 100644 index 0000000..5a55975 --- /dev/null +++ b/GuiManager/Misc/addDominance.int @@ -0,0 +1,3 @@ +function gui:addDominance() + _GuiPro.TopHovered=self +end \ No newline at end of file diff --git a/GuiManager/Misc/addHotKey.int b/GuiManager/Misc/addHotKey.int new file mode 100644 index 0000000..0ec05e0 --- /dev/null +++ b/GuiManager/Misc/addHotKey.int @@ -0,0 +1,6 @@ +function gui:addHotKey(key) + local temp=self:newFrame(0,0,0,0) + temp.Visible=false + temp:setHotKey(key) + return temp +end \ No newline at end of file diff --git a/GuiManager/Misc/alphanumsort.int b/GuiManager/Misc/alphanumsort.int new file mode 100644 index 0000000..3b36133 --- /dev/null +++ b/GuiManager/Misc/alphanumsort.int @@ -0,0 +1,7 @@ +function alphanumsort(o) + local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") + return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) + end + table.sort(o, function(a,b) return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b)< tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) + return o +end \ No newline at end of file diff --git a/GuiManager/Misc/anchorRight.int b/GuiManager/Misc/anchorRight.int new file mode 100644 index 0000000..91251ad --- /dev/null +++ b/GuiManager/Misc/anchorRight.int @@ -0,0 +1,3 @@ +function gui:anchorRight(n) + self:SetDualDim(-(self.width+n),nil,nil,nil,1) +end \ No newline at end of file diff --git a/GuiManager/Misc/centerX.int b/GuiManager/Misc/centerX.int new file mode 100644 index 0000000..ea1f599 --- /dev/null +++ b/GuiManager/Misc/centerX.int @@ -0,0 +1,3 @@ +function gui:centerX() + self:SetDualDim(-(self.width/2),nil,nil,nil,.5) +end \ No newline at end of file diff --git a/GuiManager/Misc/centerY.int b/GuiManager/Misc/centerY.int new file mode 100644 index 0000000..c998589 --- /dev/null +++ b/GuiManager/Misc/centerY.int @@ -0,0 +1,3 @@ +function gui:centerY() + self:SetDualDim(nil,-(self.height/2),nil,nil,nil,.5) +end \ No newline at end of file diff --git a/GuiManager/Misc/disrespectHierarchy.int b/GuiManager/Misc/disrespectHierarchy.int new file mode 100644 index 0000000..d25162d --- /dev/null +++ b/GuiManager/Misc/disrespectHierarchy.int @@ -0,0 +1,3 @@ +function gui:disrespectHierarchy() + _GuiPro.Hierarchy=false +end \ No newline at end of file diff --git a/GuiManager/Misc/getChildren.int b/GuiManager/Misc/getChildren.int new file mode 100644 index 0000000..295c5fc --- /dev/null +++ b/GuiManager/Misc/getChildren.int @@ -0,0 +1,3 @@ +function gui:getChildren() + return self.Children +end \ No newline at end of file diff --git a/GuiManager/Misc/getColor.int b/GuiManager/Misc/getColor.int new file mode 100644 index 0000000..bef482e --- /dev/null +++ b/GuiManager/Misc/getColor.int @@ -0,0 +1,3 @@ +function gui:getColor(cindex) + return Color[cindex] +end \ No newline at end of file diff --git a/GuiManager/Misc/getFullSize.int b/GuiManager/Misc/getFullSize.int new file mode 100644 index 0000000..294667a --- /dev/null +++ b/GuiManager/Misc/getFullSize.int @@ -0,0 +1,12 @@ +function gui:getFullSize() + local maxx,maxy=-math.huge,-math.huge + local temp = self:GetAllChildren() + for i=1,#temp do + if temp[i].width>maxx then + maxx=temp[i].width+temp[i].offset.pos.x + elseif temp[i].height>maxy then + maxy=temp[i].height+temp[i].offset.pos.y + end + end + return maxx,maxy +end \ No newline at end of file diff --git a/GuiManager/Misc/getHighest.int b/GuiManager/Misc/getHighest.int new file mode 100644 index 0000000..df7121a --- /dev/null +++ b/GuiManager/Misc/getHighest.int @@ -0,0 +1,5 @@ +function gui:getHighest() + if self.Children[#self.Children]~=nil then + return self.Children[#self.Children] + end +end \ No newline at end of file diff --git a/GuiManager/Misc/getLowest.int b/GuiManager/Misc/getLowest.int new file mode 100644 index 0000000..5319544 --- /dev/null +++ b/GuiManager/Misc/getLowest.int @@ -0,0 +1,5 @@ +function gui:getLowest() + if self.Children[1]~=nil then + return self.Children[1] + end +end \ No newline at end of file diff --git a/GuiManager/Misc/isDescendant.int b/GuiManager/Misc/isDescendant.int new file mode 100644 index 0000000..5c9c2a5 --- /dev/null +++ b/GuiManager/Misc/isDescendant.int @@ -0,0 +1,9 @@ +function gui:isDescendant(obj) + local things=obj:GetAllChildren() + for i=1,#things do + if things[i]==self then + return true + end + end + return false +end \ No newline at end of file diff --git a/GuiManager/Misc/isHighest.int b/GuiManager/Misc/isHighest.int new file mode 100644 index 0000000..0453c16 --- /dev/null +++ b/GuiManager/Misc/isHighest.int @@ -0,0 +1,3 @@ +function gui:isHighest() + return (self==self.Parent:getHighest()) +end \ No newline at end of file diff --git a/GuiManager/Misc/isLowest.int b/GuiManager/Misc/isLowest.int new file mode 100644 index 0000000..a210883 --- /dev/null +++ b/GuiManager/Misc/isLowest.int @@ -0,0 +1,3 @@ +function gui:isLowest() + return (self==self.Parent:getLowest()) +end \ No newline at end of file diff --git a/GuiManager/Misc/massMutate.int b/GuiManager/Misc/massMutate.int new file mode 100644 index 0000000..1c75aee --- /dev/null +++ b/GuiManager/Misc/massMutate.int @@ -0,0 +1,6 @@ +function gui.massMutate(t,...) + local mut={...} + for i=1,#mut do + mut[i]:Mutate(t) + end +end \ No newline at end of file diff --git a/GuiManager/Misc/newCheckBox.int b/GuiManager/Misc/newCheckBox.int new file mode 100644 index 0000000..ccd530c --- /dev/null +++ b/GuiManager/Misc/newCheckBox.int @@ -0,0 +1,41 @@ +if love.filesystem.exists("CheckBoxes.png") then + _GuiPro.UC=gui:getTile("CheckBoxes.png",0,0,16,16) + _GuiPro.C=gui:getTile("CheckBoxes.png",16,0,16,16) + _GuiPro.UCH=gui:getTile("CheckBoxes.png",0,16,16,16) + _GuiPro.CH=gui:getTile("CheckBoxes.png",16,16,16,16) +end +function gui:newCheckBox(name,x,y) + if not(_GuiPro.UC) then error("CheckBoxes.png not found! Cannot currently use checkbox without the data") end + if type(name)~="String" then + x,y,name=name,x,"CheckBox" + end + local c=self:newImageLabel(_GuiPro.UC,name, x, y, 16,16) + c.Visibility=0 + c.check=false + c:OnEnter(function(self) + if self.check then + self:SetImage(_GuiPro.CH) + else + self:SetImage(_GuiPro.UCH) + end + end) + function c:isChecked() + return self.check + end + c:OnExit(function(self) + if self.check then + self:SetImage(_GuiPro.C) + else + self:SetImage(_GuiPro.UC) + end + end) + c:OnReleased(function(b,self) + self.check=not(self.check) + if self.check then + self:SetImage(_GuiPro.CH) + else + self:SetImage(_GuiPro.UCH) + end + end) + return c +end \ No newline at end of file diff --git a/GuiManager/Misc/newMessageBox.int b/GuiManager/Misc/newMessageBox.int new file mode 100644 index 0000000..6b11a5a --- /dev/null +++ b/GuiManager/Misc/newMessageBox.int @@ -0,0 +1,36 @@ +function gui:newMessageBox(txt,x,y,w,h,sx,sy,sw,sh) + name="MessageBox" + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("MessageBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) + c.Draggable=true + c.dragbut="r" + c:ApplyGradient{Color.Blue,Color.sexy_purple} + c.BorderSize=0 + c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple + c.funcO={} + c.funcX={} + c:OnDragStart(function(self) + self:TopStack() + end) + local temp = c:newTextButton("X","Close",-25,5,20,20,1) + temp.Tween=-5 + temp.XTween=-2 + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) + temp.Color=Color.Red + local temp=c:newTextButton("OK","Ok",0,h-65,0,30,.25,1,.5) + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent) end end) + temp.Color=Color.Green + function c:Close() + self.Visible=false + end + function c:Open() + self.Visible=true + end + function c:OnOk(func) + table.insert(self.funcO,func) + end + function c:OnX(func) + table.insert(self.funcX,func) + end + return c +end \ No newline at end of file diff --git a/GuiManager/Misc/newPart.int b/GuiManager/Misc/newPart.int new file mode 100644 index 0000000..79bd3e5 --- /dev/null +++ b/GuiManager/Misc/newPart.int @@ -0,0 +1,49 @@ +function gui:newPart(x, y,w ,h , sx ,sy ,sw ,sh) + local c = {} + setmetatable(c, gui) + if self==gui then + c.Parent=_GuiPro + else + c.Parent=self + end + c.funcs={} + c.funcs2={} + c.funcs3={} + c.funcs4={} + c.funcs5={} + c.func6={} + c.func7={} + c.func8={} + c.func9={} + c.func10={} + c.form="rectangle" + c.Color = {255, 255, 255} + c.scale={} + c.scale.size={} + c.scale.size.x=sw or 0 + c.scale.size.y=sh or 0 + c.offset={} + c.offset.size={} + c.offset.size.x=w or 0 + c.offset.size.y=h or 0 + c.scale.pos={} + c.scale.pos.x=sx or 0 + c.scale.pos.y=sy or 0 + c.offset.pos={} + c.offset.pos.x=x or 0 + c.offset.pos.y=y or 0 + c.VIS=true + c.Visible=true + c.Visibility=1 + c.BorderColor={0,0,0} + c.BorderSize=0 + c.Type="Part" + c.Name="GuiPart" + _GuiPro.count=_GuiPro.count+1 + c.x=(c.Parent.width*c.scale.pos.x)+c.offset.pos.x+c.Parent.x + c.y=(c.Parent.height*c.scale.pos.y)+c.offset.pos.y+c.Parent.y + c.width=(c.Parent.width*c.scale.size.x)+c.offset.size.x + c.height=(c.Parent.height*c.scale.size.y)+c.offset.size.y + table.insert(c.Parent.Children,c) + return c +end \ No newline at end of file diff --git a/GuiManager/Misc/newProgressBar.int b/GuiManager/Misc/newProgressBar.int new file mode 100644 index 0000000..2f82f9f --- /dev/null +++ b/GuiManager/Misc/newProgressBar.int @@ -0,0 +1,45 @@ +function gui:newProgressBar(txt,x,y,w,h,sx,sy,sw,sh) + name="newProgressBar" + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("newProgressBarFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) + c.Draggable=true + c.dragbut="r" + c.BorderSize=0 + c:ApplyGradient{Color.Blue,Color.sexy_purple} + c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple + c.funcO={} + c.funcX={} + c:OnDragStart(function(self) + self:TopStack() + end) + local temp = c:newTextButton("X","Close",-25,5,20,20,1) + temp.Tween=-5 + temp.XTween=-2 + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) + temp.Color=Color.Red + c.BarBG=c:newTextButton("",5,h-65,-10,30,0,1,1) + c.BarBG:ApplyGradient{Color.Red,Color.light_red} + c.Bar=c.BarBG:newTextLabel("",0,0,0,0,0,0,0,1) + c.Bar:ApplyGradient{Color.Green,Color.light_green} + c.BarDisp=c.BarBG:newTextLabel("0%","0%",0,0,0,0,0,0,1,1) + c.BarDisp.Visibility=0 + c.BarDisp.Link=c.Bar + c.BarDisp:OnUpdate(function(self) + self.text=self.Link.scale.size.x*100 .."%" + end) + c.Func1={} + function c:On100(func) + table.insert(self.Func1,func) + end + c:OnUpdate(function(self) + if self.Bar.scale.size.x*100>=100 then + for P=1,#self.Func1 do + self.Func1[P](self) + end + end + end) + function c:SetPercentage(n) + self.Bar:SetDualDim(0,0,0,0,0,0,n/100,1) + end + return c +end \ No newline at end of file diff --git a/GuiManager/Misc/newScrollBar.int b/GuiManager/Misc/newScrollBar.int new file mode 100644 index 0000000..6fa810a --- /dev/null +++ b/GuiManager/Misc/newScrollBar.int @@ -0,0 +1,42 @@ +function gui:newScrollBar(color1,color2) + local scrollbar=self:newFrame(-20,0,20,0,1,0,0,1) + scrollbar.funcS={} + scrollbar.Color=color1 or Color.saddle_brown + scrollbar:OnClicked(function(b,self,x,y) + love.mouse.setX(self.x+10) + if y>=10 and y<=self.height-10 then + self.mover:SetDualDim(0,y-10) + end + if y<10 then + love.mouse.setY(10+self.y) + end + if y>self.height-10 then + love.mouse.setY((self.height-10)+self.y) + end + for i=1,#self.funcS do + self.funcS[i](self,self:getPosition()) + end + end) + scrollbar:OnEnter(function(self) + self:addDominance() + end) + scrollbar:OnExit(function(self) + self:removeDominance() + end) + scrollbar.mover=scrollbar:newTextButton("","",0,0,20,20) + scrollbar.mover.Color=color2 or Color.light_brown + function scrollbar:getPosition() + return ((self.mover.offset.pos.y)/(self.height-20))*100 + end + function scrollbar:setPosition(n) + print((self.height-20),n) + self.mover.offset.pos.y=((self.height-20)/(100/n)) + for i=1,#self.funcS do + self.funcS[i](self,self:getPosition()) + end + end + function scrollbar:OnScroll(func) + table.insert(self.funcS,func) + end + return scrollbar +end \ No newline at end of file diff --git a/GuiManager/Misc/newScrollMenu.int b/GuiManager/Misc/newScrollMenu.int new file mode 100644 index 0000000..3dbfdaf --- /dev/null +++ b/GuiManager/Misc/newScrollMenu.int @@ -0,0 +1,98 @@ +function gui:newScrollMenu(title,tabN,onloop,x, y, w, h, sx ,sy ,sw ,sh) + local Main = self:newFrame(x, y, w, h, sx ,sy ,sw ,sh) + local Title=Main:newTextButton(title,"Title",0,0,0,20,0,0,1) + Title.Tween=-4 + Title.FontSize=12 + Title:OnReleased(function(b,self) + self.Parent.Tick=not(self.Parent.Tick) + end) + local scroll=Main:newTextButton("","Scroll",-20,20,20,-20,1,0,0,1) + scroll:OnClicked(function(b,self,x,y) + self.Parent.Mover:SetDualDim(0,y-10,20,20) + if self.Parent.Mover.offset.pos.y<0 then + self.Parent.Mover:SetDualDim(0,0,20,20) + end + if self.Parent.Mover.offset.pos.y>self.Parent.height-40 then + self.Parent.Mover:SetDualDim(0,self.Parent.height-40,20,20) + end + local temp = #self.Parent.TList + self.Parent.pos=(math.floor((temp*self.Parent.Mover.offset.pos.y)/self.height))+1 + end) + Main:OnUpdate(function(self) + if self.Tick==false then + self.Visibility=0 + end + end) + scroll:OnUpdate(function(self) + self.Visible=self.Parent.Tick + end) + local Mover=scroll:newTextLabel("",0,0,20,20) + Main.Mover=Mover + Main.TList=tabN + Main.pos=1 + Main.Tick=true + function Main:Update(title,tabN,onloop) + ch=self:getChildren() + for i=#ch,1,-1 do + ch[i]:Destroy() + end + Title=Main:newTextButton(title,"Title",0,0,0,20,0,0,1) + Title.Tween=-4 + Title.FontSize=12 + Title:OnReleased(function(b,self) + self.Parent.Tick=not(self.Parent.Tick) + end) + scroll=Main:newTextButton("","Scroll",-20,20,20,-20,1,0,0,1) + scroll:OnClicked(function(b,self,x,y) + self.Parent.Mover:SetDualDim(0,y-10,20,20) + if self.Parent.Mover.offset.pos.y<0 then + self.Parent.Mover:SetDualDim(0,0,20,20) + end + if self.Parent.Mover.offset.pos.y>self.Parent.height-40 then + self.Parent.Mover:SetDualDim(0,self.Parent.height-40,20,20) + end + local temp = #self.Parent.TList + self.Parent.pos=(math.floor((temp*self.Parent.Mover.offset.pos.y)/self.height))+1 + end) + local Mover=scroll:newTextLabel("",0,0,20,20) + Main.Mover=Mover + Main.TList=tabN + Main.pos=1 + Main.Tick=true + scroll:OnUpdate(function(self) + self.Visible=self.Parent.Tick + end) + for i=1,math.floor(Main.height/20)-1 do + local temp=Main:newTextButton("","Item"..i,0,i*20,-20,20,0,0,1) + temp.FontSize=10 + temp.Tween=-4 + temp.pos=i + temp:OnUpdate(function(self) + self.text=self.Parent.TList[(self.Parent.pos+self.pos)-1] + self.Visible=self.Parent.Tick + end) + if onloop then + onloop(temp,i) + end + end + end + io.write(tostring(Main.height).."\n") + for i=1,math.floor(Main.height/20)-1 do + local temp=Main:newTextButton("Item"..i,0,i*20,-20,20,0,0,1) + temp.FontSize=10 + temp.Tween=-4 + temp.pos=i + temp:OnUpdate(function(self) + if self.Parent.TList[(self.Parent.pos+self.pos)-1]~=nil then + self.text=self.Parent.TList[(self.Parent.pos+self.pos)-1] + else + self.text="" + end + self.Visible=self.Parent.Tick + end) + if onloop then + onloop(temp,i) + end + end + return Main +end \ No newline at end of file diff --git a/GuiManager/Misc/removeAllChildren.int b/GuiManager/Misc/removeAllChildren.int new file mode 100644 index 0000000..8d0d99e --- /dev/null +++ b/GuiManager/Misc/removeAllChildren.int @@ -0,0 +1,6 @@ +function gui:destroyAllChildren() + local c=self.Children + for i=1,#c do + c[i]:Destroy() + end +end \ No newline at end of file diff --git a/GuiManager/Misc/removeDominance.int b/GuiManager/Misc/removeDominance.int new file mode 100644 index 0000000..c42b2e1 --- /dev/null +++ b/GuiManager/Misc/removeDominance.int @@ -0,0 +1,3 @@ +function gui:removeDominance() + _GuiPro.TopHovered=nil +end \ No newline at end of file diff --git a/GuiManager/Misc/respectHierarchy.int b/GuiManager/Misc/respectHierarchy.int new file mode 100644 index 0000000..656a992 --- /dev/null +++ b/GuiManager/Misc/respectHierarchy.int @@ -0,0 +1,3 @@ +function gui:respectHierarchy() + _GuiPro.Hierarchy=true +end \ No newline at end of file diff --git a/GuiManager/Misc/round.int b/GuiManager/Misc/round.int new file mode 100644 index 0000000..f06ad57 --- /dev/null +++ b/GuiManager/Misc/round.int @@ -0,0 +1,4 @@ +function gui.round(num, idp) + local mult = 10^(idp or 0) + return math.floor(num * mult + 0.5) / mult +end \ No newline at end of file diff --git a/GuiManager/Misc/setBG.int b/GuiManager/Misc/setBG.int new file mode 100644 index 0000000..c82f045 --- /dev/null +++ b/GuiManager/Misc/setBG.int @@ -0,0 +1,3 @@ +function gui.setBG(i) + gui.ff:SetImage(i) +end \ No newline at end of file diff --git a/GuiManager/Misc/setColor.int b/GuiManager/Misc/setColor.int new file mode 100644 index 0000000..7a81a6f --- /dev/null +++ b/GuiManager/Misc/setColor.int @@ -0,0 +1,14 @@ +function gui:setColor(a,b,c) + if type(a)=="string" then + self.Color=Color[a] + elseif type(a)=="number" then + self.Color=Color.new(a,b,c) + end +end +function gui:setTextColor(a,b,c) + if type(a)=="string" then + self.TextColor=Color[a] + elseif type(a)=="number" then + self.TextColor=Color.new(a,b,c) + end +end \ No newline at end of file diff --git a/GuiManager/Misc/setDefualtFont.int b/GuiManager/Misc/setDefualtFont.int new file mode 100644 index 0000000..001b9f7 --- /dev/null +++ b/GuiManager/Misc/setDefualtFont.int @@ -0,0 +1,3 @@ +function gui:setDefualtFont(font) + _defaultfont = font +end \ No newline at end of file diff --git a/GuiManager/Misc/setHotKey.int b/GuiManager/Misc/setHotKey.int new file mode 100644 index 0000000..5866cfc --- /dev/null +++ b/GuiManager/Misc/setHotKey.int @@ -0,0 +1,24 @@ +function gui:setHotKey(key) + local tab=key:split("+") + self.hotkeys=tab + self.cooldown=false + self.Alarm=multi:newAlarm(1) + self.Alarm.parent=self + self.args={} + self.funcHK=multi:newConnection() + self.Alarm:OnRing(function(alarm) alarm.parent.cooldown=false end) + function self:OnHotKey(func) + self.funcHK:connect(func) + end + self:OnUpdate(function(self) + if self.cooldown then return end + for i=1,#self.hotkeys do + if not(love.keyboard.isDown(self.hotkeys[i])) then + return + end + end + self.cooldown=true + self.funcHK:Fire(self) + self.Alarm:Reset() + end) +end \ No newline at end of file diff --git a/GuiManager/Misc/setNewFont.int b/GuiManager/Misc/setNewFont.int new file mode 100644 index 0000000..93d95c5 --- /dev/null +++ b/GuiManager/Misc/setNewFont.int @@ -0,0 +1,3 @@ +function gui:setNewFont(FontSize) + self.Font=love.graphics.setNewFont(tonumber(FontSize)) +end \ No newline at end of file diff --git a/GuiManager/Misc/setParent.int b/GuiManager/Misc/setParent.int new file mode 100644 index 0000000..37ddb6e --- /dev/null +++ b/GuiManager/Misc/setParent.int @@ -0,0 +1,14 @@ +function gui:setParent(parent,name)-- Needs fixing!!! + local temp=self.Parent:getChildren() + for i=1,#temp do + if temp[i]==self then + table.remove(self.Parent.Children,i) + break + end + end + table.insert(parent.Children,self) + self.Parent=parent + if name then + self:SetName(name) + end +end \ No newline at end of file diff --git a/GuiManager/Misc/setVisibility.int b/GuiManager/Misc/setVisibility.int new file mode 100644 index 0000000..ca6008c --- /dev/null +++ b/GuiManager/Misc/setVisibility.int @@ -0,0 +1,14 @@ +function gui:setVisiblity(val) + self.Visible=val + self.oV=val + doto=self:GetAllChildren() + if val==false then + for i=1,#doto do + doto[i].Visible=val + end + else + for i=1,#doto do + doto[i].Visible=doto[i].oV + end + end +end \ No newline at end of file diff --git a/GuiManager/Misc/setgetText.int b/GuiManager/Misc/setgetText.int new file mode 100644 index 0000000..bb4afc6 --- /dev/null +++ b/GuiManager/Misc/setgetText.int @@ -0,0 +1,6 @@ +function gui:setText(txt) + self.text=txt +end +function gui:getText(txt) + return self.text +end \ No newline at end of file diff --git a/GuiManager/Text/newTextBox.int b/GuiManager/Text/newTextBox.int new file mode 100644 index 0000000..c98b847 --- /dev/null +++ b/GuiManager/Text/newTextBox.int @@ -0,0 +1,178 @@ +function string:insert(p,s) + return ("%s%s%s"):format(self:sub(1,p), s, self:sub(p+1)) +end +function string:remove(p,l) + l=l or 1 + return ("%s%s"):format(self:sub(1,p-1), self:sub(p+l)) +end +function gui:newTextBox(t,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextBox",name, x, y, w, h, sx ,sy ,sw ,sh) + c.ClearOnFocus=false + c.LoseFocusOnEnter=true + c.Tween=0 + c.XTween=0 + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.text = t + c.ttext= t + c.AutoScaleText=false + c.TextVisibility=1 + c.Color = {220, 220, 220} + c.TextColor = {0, 0, 0} + c.Active=false + c.hidden=false + c.cursor={0,1} + c.mark=nil + c.arrowkeys=false + c.funcF={function() + love.keyboard.setTextInput(true,0,200,400,200) + end} + c.cooldown=false + c.cooldown2=false + c.funcE={function() + love.keyboard.setTextInput(false) + end} + function c:triggerEnter() + for cc=1,#self.funcE do + self.funcE[cc](self,self.ttext) + end + self.text="" + self.ttext="" + end + c.Enter=true + c.Alarm=multi:newAlarm(.1) + c.Alarm.parent=c + c.Alarm:OnRing(function(alarm) alarm.parent.cooldown=false end) + c.Alarm2=multi:newAlarm(.5) + c.Alarm2.parent=c + c.Alarm2:OnRing(function(alarm) alarm.parent.cooldown2=false end) + c.ArrowAlarm=multi:newAlarm(.1) + c.ArrowAlarm.parent=c + c.ArrowAlarm:OnRing(function(alarm) alarm.parent.arrowkeys=false end) + function c:OnFocus(func) + table.insert(self.funcF,func) + end + function c:OnEnter(func) + table.insert(self.funcE,func) + end + c:OnClicked(function(b,self) + for cc=1,#self.funcF do + self.funcF[cc](self) + end + if self.Active==false then + if self.ClearOnFocus==true then + self.text="" + self.ttext="" + end + for tb=1,#gui.TB do + if gui.TB[tb]~=nil then + gui.TB[tb].Active=false + end + end + self.Active=true + end + end) + c:OnClicked(function(b,self,x,y) + local dwidth, wrappedtext = _defaultfont:getWrap(self.text:sub(1,self.cursor[1]), self.width) + local height = _defaultfont:getHeight() + if #wrappedtext>=1 then + width= _defaultfont:getWidth(wrappedtext[#wrappedtext]) + self.cursor[2]=#wrappedtext + else + self.cursor[2]=1 + width=0 + end + yc=math.ceil(((y/self.DPI)-(self.FontHeight/2)+self.Tween-self.y)/height) + xc=math.floor(x) + end) + c:AddDrawRuleE(function(self) + if self.Active then + local dwidth, wrappedtext = _defaultfont:getWrap(self.text:sub(1,self.cursor[1]), self.width) + local height = _defaultfont:getHeight() + if #wrappedtext>=1 then + width= _defaultfont:getWidth(wrappedtext[#wrappedtext]) + self.cursor[2]=#wrappedtext + else + self.cursor[2]=1 + width=0 + end + x1=width+2+self.x+self.XTween + y1=(self.y+(height*(self.cursor[2]-1))+(self.FontHeight/2)+self.Tween)*self.DPI + x2=width+2+self.x+self.XTween + y2=(self.y+(self.FontHeight/2)+self.Tween*self.DPI)+height*self.cursor[2] + love.graphics.line(x1,y1,x2,y2) + end + end) + c:OnUpdate(function(self) + if love.keyboard.isDown("backspace") and self.Active and self.cooldown==false then + if #self.text>0 then + self.text = self.text:remove(self.cursor[1]) + self.ttext = self.ttext:remove(self.cursor[1]) + self.cursor[1]=self.cursor[1]-1 + end + self.cooldown=true + self.Alarm:Reset() + elseif love.keyboard.isDown("backspace")==false then + self.cooldown=false + end + if love.keyboard.isDown("left") and self.arrowkeys==false and self.Active then + self.arrowkeys=true + self.cursor[1]=self.cursor[1]-1 + if self.cursor[1]<0 then + self.cursor[1]=0 + end + self.ArrowAlarm:Reset() + elseif love.keyboard.isDown("right") and self.arrowkeys==false and self.Active then + self.arrowkeys=true + self.cursor[1]=self.cursor[1]+1 + if self.cursor[1]>#self.text then + self.cursor[1]=#self.text + end + self.ArrowAlarm:Reset() + end + if love.keyboard.isDown("delete") and self.Active then + if #self.text>0 then + self.text = "" + self.ttext = "" + self.cursor[1]=1 + end + elseif (love.keyboard.isDown("lshift") or love.keyboard.isDown("rshift")) and love.keyboard.isDown("return") and self.cooldown2==false then + self.text=self.text.."\n" + self.ttext=self.ttext.."\n" + self.cooldown2=true + c.Alarm2:Reset() + elseif (love.keyboard.isDown("return") or love.keyboard.isDown("enter") or love.keyboard.isDown("kpenter")) and self.Active and self.Enter and not(love.keyboard.isDown("lshift") or love.keyboard.isDown("rshift")) then + if self.LoseFocusOnEnter then + self.Active=false + else + self.Active=true + end + for cc=1,#self.funcE do + self.funcE[cc](self,self.ttext) + end + end + end) + table.insert(gui.TB,c) + return c +end +--TEXT BOX HELPER FUNCTION +function love.textinput(t) + for tb=1,#gui.TB do + if gui.TB[tb]~=nil then + if gui.TB[tb].Active then + if gui.TB[tb].hidden then + --gui.TB[tb].text=gui.TB[tb].text.."*" + gui.TB[tb].text=gui.TB[tb].text:insert(gui.TB[tb].cursor[1],"*") + else + --gui.TB[tb].text=gui.TB[tb].text..t + gui.TB[tb].text=gui.TB[tb].text:insert(gui.TB[tb].cursor[1],t) + end + gui.TB[tb].ttext=gui.TB[tb].ttext:insert(gui.TB[tb].cursor[1],t) + gui.TB[tb].cursor[1]=gui.TB[tb].cursor[1]+1 + end + end + end +end \ No newline at end of file diff --git a/GuiManager/Text/newTextButton.int b/GuiManager/Text/newTextButton.int new file mode 100644 index 0000000..da2f3f6 --- /dev/null +++ b/GuiManager/Text/newTextButton.int @@ -0,0 +1,22 @@ +function gui:newTextButton(t,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextButton",name, x, y, w, h, sx ,sy ,sw ,sh) + c.Tween=0 + c.XTween=0 + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.text = t + c.AutoScaleText=false + c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) + c.Color = {220, 220, 220} + c.TextColor = {0, 0, 0} + c:OnEnter(function() + love.mouse.setCursor(_GuiPro.CursorH) + end) + c:OnExit(function() + love.mouse.setCursor(_GuiPro.CursorN) + end) + return c +end \ No newline at end of file diff --git a/GuiManager/Text/newTextLabel.int b/GuiManager/Text/newTextLabel.int new file mode 100644 index 0000000..4424d0e --- /dev/null +++ b/GuiManager/Text/newTextLabel.int @@ -0,0 +1,16 @@ +function gui:newTextLabel(t,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextLabel",name, x, y, w, h, sx ,sy ,sw ,sh) + c.Tween=0 + c.XTween=0 + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.text = t + c.AutoScaleText=false + c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) + c.Color = {220, 220, 220} + c.TextColor = {0, 0, 0} + return c +end \ No newline at end of file diff --git a/GuiManager/init.lua b/GuiManager/init.lua new file mode 100644 index 0000000..c9c33db --- /dev/null +++ b/GuiManager/init.lua @@ -0,0 +1,56 @@ +utf8 = require("utf8") +_defaultfont = love.graphics.getFont() +gui = {} +gui.__index = gui +gui.TB={} +gui.Version="VERSION" -- Is it really ready for release? +_GuiPro={GBoost=true,hasDrag=false,DragItem={},Children={},Visible=true,count=0,x=0,y=0,height=0,width=0,update=function(self) local things=GetAllChildren2(self) UpdateThings(things) end,draw=function(self) local things=GetAllChildren(self) DrawThings(things) end,getChildren=function(self) return self.Children end} +_GuiPro.Clips={} +_GuiPro.rotate=0 +setmetatable(_GuiPro, gui) +function gui:LoadInterface(file) + local add=".int" + if string.find(file,".",1,true) then add="" end + if love.filesystem.exists(file..add) then + a,b=pcall(love.filesystem.load(file..add)) + if a then + print("Loaded: "..file) + else + print("Error loading file: "..file) + print(a,b) + end + else + print("File does not exist!") + return false + end +end +function gui.LoadAll(dir) + files=love.filesystem.getDirectoryItems(dir) + for i=1,#files do + if string.sub(files[i],-4)==".int" then + gui:LoadInterface(dir.."/"..files[i]) + end + end +end +-- Start Of Load + +gui.LoadAll("GuiManager/Core") +gui.LoadAll("GuiManager/Image-Animation") +gui.LoadAll("GuiManager/Frame") +gui.LoadAll("GuiManager/Item") +gui.LoadAll("GuiManager/Misc") +gui.LoadAll("GuiManager/Text") +gui.LoadAll("GuiManager/Drawing") + +multi.boost=2 + +-- End of Load +gui:respectHierarchy() +_GuiPro.width,_GuiPro.height=love.graphics.getDimensions() +multi:newLoop():OnLoop(function() _GuiPro.width,_GuiPro.height=love.graphics.getDimensions() _GuiPro:update() end) +multi:onDraw(function() _GuiPro:draw() end) +gui.ff=gui:newFrame("",0,0,0,0,0,0,1,1) +gui.ff.Color={255,255,255} +gui.ff:OnUpdate(function(self) + self:BottomStack() +end) diff --git a/Interface/colorpicker.int b/Interface/colorpicker.int new file mode 100644 index 0000000..2c58170 --- /dev/null +++ b/Interface/colorpicker.int @@ -0,0 +1,5 @@ +function gui:newColorPicker(x,y,w) + local c=self:newFrame("ColorPicker",x,y,w,w) + c.wheel=c:newImageLabel("Resources/wheel.png","Wheel",0,0,w,w) + return c +end \ No newline at end of file diff --git a/Interface/console.int b/Interface/console.int new file mode 100644 index 0000000..b05bba4 --- /dev/null +++ b/Interface/console.int @@ -0,0 +1,40 @@ +function gui:newConsole(x,y,w,h) + local c=self:newTextLabel("Console","Console",x,y,w,20,sx,sy,sw) + c.dragbut="l" + c.Draggable=true + c.Tween=-3 + c.BG=c:newTextLabel("","",0,20,0,h,0,0,1,1) + c.BG.ClipDescendants=true + c.output=c.BG:newTextLabel("","",0,0,0,0,0,0,1,1) + c.output.Visibility=0 + c.scroll=c.BG:newScrollBar() + c.scroll.output=c.output + c.output.Tween=-3 + c.output.TextColor=Color.sexy_purple + c.input=c:newTextBox("> ","> ",0,h+20,-20,20,0,0,1) + c.input.Tween=-3 + c.input.TextFormat="left" + c.output.TextFormat="left" + c.output.count=0 + c:ApplyGradient({Color.Red,Color.Darken(Color.Red,.25)}) + c.BG:ApplyGradient({Color.Black,Color.Lighten(Color.Black,.15)}) + c.input:ApplyGradient({Color.Gray,Color.Darken(Color.Gray,.25)}) + c.scroll:OnScroll(function(self,pos) + self.output:SetDualDim(0,0,0,0,0,-((pos/(h*8))*self.output.count)) + end) + c.input:OnEnter(function(self,text) + self.Parent.output.text=self.Parent.output.text..text.."\n" + self.text="> " + self.Parent.output.count=self.Parent.output.count+1 + end) + c.input:OnFocus(function(self) + self.text="> " + end) + function c:showConsole() + self.Parent.Visible=true + end + function c:hideConsole() + self.Parent.Visible=false + end + return c +end diff --git a/Interface/header.int b/Interface/header.int new file mode 100644 index 0000000..3d6f2be --- /dev/null +++ b/Interface/header.int @@ -0,0 +1,81 @@ +function gui:newHeader() + local header=self:newFrame(0,0,0,20,0,0,1) + header:ApplyGradient({Color.white,Color.light_blue,Color.blue,trans=200}) + header.last={x=0,width=0} + function header:newTab(name) + local font=love.graphics.getFont() + local tab=self:newTextButton(name,self.last.x+self.last.width,0,font:getWidth(name)+6,20) + self.last=tab + tab.Visibility=0 + tab.Tween=-3 + tab.XTween=-2 + tab.Color=Color.white + tab.largest={x=0,width=0} + tab.Options=tab:newFrame("Options",0,20) + tab.Options.Visible=false + tab.Options.Color=Color.light_gray + tab:OnEnter(function(self) + self.Visibility=.5 + end) + tab:OnExit(function(self) + self.Visibility=0 + end) + tab:OnReleased(function(b,self) + if b=="l" then + self.Options.Visible=true + self:addDominance() + end + end) + tab.Options:OnExit(function(self) + self.Visible=false + self:removeDominance() + end) + function tab:newOption(name,func,HK) + local opt=self.Options:newTextButton(name,0,#self.Options:getChildren()*20,0,20,0,0,1) + if HK then + if type(HK)=="table" then + for i=1,#HK do + opt:addHotKey(HK[i]):OnHotKey(func) + name=name.."\t\t\t\t\t\t" + local temp=opt:newTextLabel(HK[i],-(font:getWidth(HK[i])+2),0,font:getWidth(HK[i])+2,20,1) + temp.Visibility=0 + temp.Tween=-3 + temp.XTween=-2 + opt.text=name + end + else + opt:setHotKey(HK) + opt:OnHotKey(func) + name=name.."\t\t\t\t\t\t" + local temp=opt:newTextLabel(HK,-(font:getWidth(HK)+2),0,font:getWidth(HK)+2,20,1) + temp.Visibility=0 + temp.Tween=-3 + temp.XTween=-2 + opt.text=name + end + end + opt.TextFormat="left" + opt.Visibility=0 + opt.Color=Color.white + opt.Tween=-3 + opt:OnEnter(function(self) + self.Visibility=.5 + end) + opt:OnExit(function(self) + self.Visibility=0 + end) + local font=love.graphics.getFont() + local c=self:getChildren() + if font:getWidth(name)+6>self.largest.width then + self.largest={width=font:getWidth(name)+6} + end + self.Options:SetDualDim(0,20,self.largest.width,#self.Options:getChildren()*20) + if func then + opt:OnReleased(func) + end + return opt + end + return tab + end + return header +end \ No newline at end of file diff --git a/Interface/player.int b/Interface/player.int new file mode 100644 index 0000000..91fa354 --- /dev/null +++ b/Interface/player.int @@ -0,0 +1,20 @@ +function gui:newPlayer(source,x,y,w,h,sx,sy,sw,sh) + local c=self:newFrame("MediaPlayer",x,y,w,h,sx,sy,sw,sh) + c.visuals=c:newFrame(0,0,0,-20,0,0,1,1) + c.bar=c:newFrame(40,-20,-40,20,0,1,1) + c.bar:ApplyGradient{Color.blue,Color.Darken(Color.blue,.25)} + c.action=c:newTextButton("Play",0,-20,40,20,0,1) + c.action:ApplyGradient{Color.blue,Color.Darken(Color.blue,.25)} + c.action:OnReleased(function(b,self) + if self.text=="Play" then + self.Parent.Source:play() + self.text="Pause" + else + self.Parent.Source:pause() + self.text="Play" + end + end) + c.action.Tween=-3 + c.VPush=multi:newStep(0,1,1,10) + c.Source=audio:new(source) +end \ No newline at end of file diff --git a/Interface/system.int b/Interface/system.int new file mode 100644 index 0000000..e0fc435 --- /dev/null +++ b/Interface/system.int @@ -0,0 +1,77 @@ +function gui:addTip(tip,n,padding) + local font=love.graphics.getFont() + self.t=gui:newTextLabel(tip,"Tooltip",0,0,font:getWidth(tip)+(padding or 4),14) + self.t:setNewFont(10) + self.t.Visible=false + self.t.Tween=1 + self.t.Color=Color.tan + self.alarm=multi:newAlarm(0) + self.alarm:Pause() + self.alarm.parent=self + self.time=n or 2 + self.padding=padding or 4 + self.alarm:OnRing(function(alarm) + alarm.parent.t:SetDualDim(love.mouse.getX()-2,love.mouse.getY()-2) + alarm.parent.t.Visible=true + alarm.parent.t:addDominance() + end) + self:OnEnter(function(self) + self.Visibility=.5 + self.alarm:Reset(self.time) + end) + self:OnExit(function(self) + self.alarm:Pause() + self.Visibility=0 + end) + self.t:OnExit(function(self) + self.Visible=false + self:removeDominance() + end) +end +function gui:newWindow(name) + local win=self:newFrame(0,0,400,20) + win.Draggable=true + win.dragbut="r" + win:OnDragStart(function(self) + self:TopStack() + end) + if name then + local font=love.graphics.getFont() + win.title=win:newTextLabel(name,0,0,font:getWidth(name),20) + win.title.TextFormat="left" + win.title.Visibility=0 + win.title.XTween=3 + win.title.Tween=-3 + end + win:ApplyGradient({Color.white,Color.light_blue,Color.blue,trans=200}) + win.close=win:newImageButton("icons/cancel.png",-20,2,16,16,1) + win.close:OnEnter(function(self) + self.Parent:removeDominance() + self:addDominance() + end) + win.close:OnReleased(function(b,self) + self.Parent:Destroy() + self:removeDominance() + love.mouse.setCursor() + end) + win.close:OnExit(function(self) + self:removeDominance() + end) + win.holder=win:newFrame(0,0,0,280,0,1,1) + win:OnUpdate(function(self) + if self.y<40 then self:SetDualDim(nil,0) love.mouse.setY(50) end + end) + win:OnEnter(function(self) + self:addDominance() + end) + win:OnExit(function(self) + self:removeDominance() + end) + win.holder:OnEnter(function(self) + self:addDominance() + end) + win.holder:OnExit(function(self) + self:removeDominance() + end) + return win.holder,win +end \ No newline at end of file diff --git a/Libs/AudioManager.lua b/Libs/AudioManager.lua new file mode 100644 index 0000000..fceda6c --- /dev/null +++ b/Libs/AudioManager.lua @@ -0,0 +1,212 @@ +audio = {} +audio.__index = audio +function audio:new(f,t) + local obj={} + setmetatable(obj, audio) + obj.source=love.audio.newSource(f,t) + obj.f=f + obj.t=t or "stream" + obj.endEvent=multi:newLoop() + obj.endEvent.Pare=obj + obj.wasPlaying=false + obj.func={} + obj.func2={} + obj.func3={} + obj.func4={} + obj.endEvent:OnLoop(function(time,loop) + if not(loop.Pare:isPlaying()) and loop.Pare.wasPlaying==true and not(loop.Pare:isPaused()) then + for i=1,#loop.Pare.func do + loop.Pare:stop() + loop.Pare.wasPlaying=false + loop.Pare.endEvent:Pause() + loop.Pare.func[i](loop.Pare) + end + end + end) + obj.endEvent:Pause() + return obj +end +function audio:clone() + local _temp=audio:new(self.f,self.t) + _temp.source=self.source:clone() + return _temp +end +--Mutators +function audio:play() + if self:isPaused() then + for i=1,#self.func4 do + self.func4[i](self) + end + self:resume() + else + for i=1,#self.func3 do + self.func3[i](self) + end + self.source:play() + self.wasPlaying=true + self.endEvent:Resume() + end +end +function audio:stop() + self.source:stop() + self.wasPlaying=true + self.endEvent:Pause() +end +function audio:pause() + for i=1,#self.func2 do + self.func2[i](self) + end + self.source:pause() +end +function audio:resume() + self.source:resume() +end +function audio:rewind() + self.source:rewind() +end +function audio:setAttenuationDistances(r,m) + self.source:setAttenuationDistances(r,m) +end +function audio:setCone(innerAngle, outerAngle, outerVolume) + self.source:setCone(innerAngle, outerAngle, outerVolume) +end +function audio:setDirection(x, y, z) + self.source:setDirection(x, y, z) +end +function audio:setLooping(loop) + self.source:setLooping(loop) +end +function audio:setPitch(pitch) + self.source:setPitch(pitch) +end +function audio:setPosition(x, y, z) + self.source:setPosition(x, y, z) +end +function audio:setRelative(enable) + self.source:setRelative(enable) +end +function audio:setRolloff(rolloff) + self.source:setRolloff(rolloff) +end +function audio:setVelocity(x, y, z) + self.source:setVelocity(x, y, z) +end +function audio:setVolume(volume) + self.source:setVolume(volume) +end +function audio:setVolumeLimits(min, max) + self.source:setVolumeLimits(min, max) +end +function audio:seek(offset,unit) + self.source:seek(offset,unit) +end +--Assessors +function audio:isPlaying() + return self.source:isPlaying() +end +function audio:isPaused() + return self.source:isPaused() +end +function audio:isStopped() + return self.source:isStopped() +end +function audio:isLooping() + return self.source:isLooping() +end +function audio:isStatic() + return self.source:isStatic() +end +function audio:isRelative() + return self.source:isRelative() +end +function audio:getAttenuationDistances() + return self.source:getAttenuationDistances() +end +function audio:getChannels() + return self.source:getChannels() +end +function audio:getCone() + return self.source:getCone() +end +function audio:getDirection() + return self.source:getDirection() +end +function audio:getPitch() + return self.source:getPitch() +end +function audio:getPosition() + return self.source:getPosition() +end +function audio:getRolloff() + return self.source:getRolloff() +end +function audio:getVelocity() + return self.source:getVelocity() +end +function audio:getVolume() + return self.source:getVolume() +end +function audio:getVolumeLimits() + return self.source:getVolumeLimits() +end +function audio:tell(unit) + return self.source:tell(unit) +end +function audio:type() + return self.source:type() +end +function audio:typeOf() + return self.source:typeOf() +end +--Events +function audio:onResume(func) + table.insert(self.func4,func) +end +function audio:onPlay(func) + table.insert(self.func3,func) +end +function audio:onPause(func) + table.insert(self.func2,func) +end +function audio:onStop(func) + table.insert(self.func,func) +end +--[[ +Object:type |Done +Object:typeOf |Done +Source:clone |Done +Source:getAttenuationDistances |Done +Source:getChannels |Done +Source:getCone |Done +Source:getDirection |Done +Source:getPitch |Done +Source:getPosition |Done +Source:getRolloff |Done +Source:getVelocity |Done +Source:getVolume |Done +Source:getVolumeLimits |Done +Source:isLooping |Done +Source:isPaused |Done +Source:isPlaying |Done +Source:isRelative |Done +Source:isStatic |Done +Source:isStopped |Done +Source:pause |Done +Source:play |Done +Source:resume |Done +Source:rewind |Done +Source:seek |Done +Source:setAttenuationDistances |Done +Source:setCone |Done +Source:setDirection |Done +Source:setLooping |Done +Source:setPitch |Done +Source:setPosition |Done +Source:setRelative |Done +Source:setRolloff |Done +Source:setVelocity |Done +Source:setVolume |Done +Source:setVolumeLimits |Done +Source:stop |Done +Source:tell |Done +]] diff --git a/Libs/Library.lua b/Libs/Library.lua new file mode 100644 index 0000000..8260136 --- /dev/null +++ b/Libs/Library.lua @@ -0,0 +1,319 @@ +if table.unpack then + unpack=table.unpack +end +function table.val_to_str ( v ) + if "string" == type( v ) then + v = string.gsub( v, "\n", "\\n" ) + if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then + return "'" .. v .. "'" + end + return '"' .. string.gsub(v,'"', '\\"' ) .. '"' + else + return "table" == type( v ) and table.tostring( v ) or + tostring( v ) + end +end + +function table.key_to_str ( k ) + if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then + return k + else + return "[" .. table.val_to_str( k ) .. "]" + end +end + +function table.tostring( tbl ) + local result, done = {}, {} + for k, v in ipairs( tbl ) do + table.insert( result, table.val_to_str( v ) ) + done[ k ] = true + end + for k, v in pairs( tbl ) do + if not done[ k ] then + table.insert( result, + table.key_to_str( k ) .. "=" .. table.val_to_str( v ) ) + end + end + return "{" .. table.concat( result, "," ) .. "}" +end +function table.merge(t1, t2) + t1,t2= t1 or {},t2 or {} + for k,v in pairs(t2) do + if type(v) == "table" then + if type(t1[k] or false) == "table" then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 +end +Library={} +function Library.optimize(func) + local test=Library.convert(func) + rawset(test,"link",{}) + rawset(test,"last","") + rawset(test,"org",func) + test:inject(function(...) + rawset(test,"last",table.tostring({...})) + if test.link[test.last]~=nil then + return Library.forceReturn(unpack(test.link[test.last])) + end + return {...} + end,1) + test:inject(function(...) + test.link[test.last]={test.org(...)} + return test.org(...) + end) + return test +end +function Library.forceReturn(...) + return {[0]="\1\7\6\3\2\99\125",...} +end +function Library.inject(lib,dat,arg) + if type(lib)=="table" then + if type(dat)=="table" then + table.merge(lib,dat) + elseif type(dat)=="string" then + if lib.Version and dat:match("(%d-)%.(%d-)%.(%d-)") then + lib.Version={dat:match("(%d+)%.(%d+)%.(%d+)")} + elseif dat=="meta" and type(arg)=="table" then + local _mt=getmetatable(lib) or {} + local mt={} + table.merge(mt,arg) + table.merge(_mt,mt) + setmetatable(lib,_mt) + elseif dat=="compat" then + lib["getVersion"]=function(self) return self.Version[1].."."..self.Version[2].."."..self.Version[3] end + if not lib.Version then + lib.Version={1,0,0} + end + elseif dat=="inhert" then + if not(lib["!%"..arg.."%!"]) then print("Wrong Password!!") return end + lib["!%"..arg.."%!"].__index=lib["!!%"..arg.."%!!"] + end + elseif type(dat)=="function" then + for i,v in pairs(lib) do + dat(lib,i,v) + end + end + elseif type(lib)=="function" or type(lib)=="userdata" then + if lib==unpack then + print("function unpack cannot yet be injected!") + return unpack + elseif lib==pairs then + print("function pairs cannot yet be injected!") + return lib + elseif lib==ipairs then + print("function ipairs cannot yet be injected!") + return lib + elseif lib==type then + print("function type cannot yet be injected!") + return lib + end + temp={} + local mt={ + __call=function(t,...) + local consume,MainRet,init={},{},{...} + local tt={} + for i=1,#t.__Link do + tt={} + if t.__Link[i]==t.__Main then + if #consume~=0 then + MainRet={t.__Link[i](unpack(consume))} + else + MainRet={t.__Link[i](unpack(init))} + end + else + if i==1 then + consume=(t.__Link[i](unpack(init))) + else + if type(MainRet)=="table" then + table.merge(tt,MainRet) + end + if type(consume)=="table" then + table.merge(tt,consume) + end + consume={t.__Link[i](unpack(tt))} + end + if i==#t.__Link then + return unpack(consume) + end + if consume then if consume[0]=="\1\7\6\3\2\99\125" then consume[0]=nil return unpack(consume) end end + end + end + if type(MainRet)=="table" then + table.merge(tt,MainRet) + end + if type(consume)=="table" then + table.merge(tt,consume) + end + return unpack(tt) + end, + } + temp.__Link={lib} + temp.__Main=lib + temp.__self=temp + function temp:inject(func,i) + if i then + table.insert(self.__Link,i,func) + else + table.insert(self.__Link,func) + end + end + function temp:consume(func) + for i=1,#self.__Link do + if self.__Link[i]==self.__Main then + self.__Link[i]=func + self.__self.__Main=func + return true + end + end + return false + end + setmetatable(temp,mt) + Library.protect(temp,"lolz") + return temp + else + return "arg1 must be a table or a function" + end +end +function Library.parse(lib) + for i,v in pairs(lib) do + print(i,v) + end +end +function Library.protect(lib,pass) + pass=pass or "*" + local mt={} + local test={ + __index = lib, + __newindex = function(tab, key, value) + local t,b=key:find(tab["!%"..pass.."%!"].__pass,1,true) + if t then + local _k=key:sub(b+1) + rawset(tab,_k,value) + else + error("Cannot alter a protected library!") + end + end, + __metatable = false, + __pass=pass or "*" + } + local _mt=getmetatable(lib) or {} + table.merge(mt,_mt) + table.merge(mt,test) + lib["!%"..pass.."%!"]=test + lib["!!%"..pass.."%!!"]=lib + local temp=setmetatable({},mt) + for i,v in pairs(_G) do + if v==lib then + _G[i]=temp + Library(function(link) + link[i]=v + end) + end + end +end +function Library.unprotect(lib,pass) + if not(lib["!%"..pass.."%!"]) then print("Wrong Password or Library is not Protected!") return end + if lib["!%"..pass.."%!"].__pass==pass then + lib["!%"..pass.."%!"].__newindex=lib["!!%"..pass.."%!!"] + lib["!%"..pass.."%!"].__index=nil + lib["!%"..pass.."%!"].__newindex=nil + lib["!%"..pass.."%!"].__metatable = true + setmetatable(lib["!!%"..pass.."%!!"],lib["!%"..pass.."%!"]) + for i,v in pairs(_G) do + if v==lib then + _G[i]=lib["!!%"..pass.."%!!"] + end + end + lib["!!%"..pass.."%!!"]["!%"..pass.."%!"]=nil + lib["!!%"..pass.."%!!"]["!!%"..pass.."%!!"]=nil + else + print("Wrong Password!!!") + end +end +function Library.addPoll(lib,polldata,ref) + lib.__polldata={} + Library.inject(lib.__polldata,polldata) + if type(ref)=="table" then + Library.inject(ref,"meta",{__newindex=function(t,k,v) + t[k].__polldata=polldata + end}) + end +end +function Library.newPollData(t) + local temp={} + temp.__onPolled=function() end + temp.__pollData=false + temp.__advDisc="" + temp.__pollcalls=-1 -- infinte + for i,v in pairs(t) do + if type(v)=="string" then + temp.__advDisc=v + elseif type(v)=="number" then + temp.__pollcalls=v + elseif type(v)=="table" then + temp[v[1]]=v[2] + elseif type(v)=="function" then + temp.__onPolled=v + elseif type(v)=="boolean" then + temp.__pollData=v + else + temp.__userdata=v + end + end + return temp +end +function Library.convert(...) + local temp,rets={...},{} + for i=1,#temp do + if type(temp[i])=="function" then + table.insert(rets,Library.inject(temp[i])) + else + error("Takes only functions and returns in order from functions given. arg # "..i.." is not a function!!! It is a "..type(temp[i])) + end + end + return unpack(rets) +end +function Library.convertIn(...) + local temp,list={...},{} + for i=1,#temp do + if type(temp[i])=="table" then + for k,v in pairs(temp[i]) do + if type(v)=="function" then + temp[i][k]=Library.inject(temp[i][k]) + end + end + else + error("Takes only tables! Arg "..i.." isn't it is a "..type(temp[i])) + end + end +end +function Library.newInjectedFunction() + return Library.convert(function(...) return unpack{...} end) +end +function Library.capulate(lib) + Library.inject(lib,"meta",{ + __index=function(t,k,v) + for i,_v in pairs(t) do + if k:lower()==i:lower() then + return t[i] + end + end + end, + __newindex=function(t,k,v) + rawset(t,k:lower(),v) + end + }) +end +local link={MainLibrary=Library} +Library.inject(Library,"meta",{ + __Link=link, + __call=function(self,func) func(link) end, +}) +--Library.protect(Library,"N@#P!KLkk1(93320") diff --git a/Libs/MultiManager.lua b/Libs/MultiManager.lua new file mode 100644 index 0000000..d3a2dd2 --- /dev/null +++ b/Libs/MultiManager.lua @@ -0,0 +1,1391 @@ +if not bin then + print('Warning the \'bin\' library wasn\'t required! multi:tofile(path) and the multi:fromfile(path,int) features will not work!') +end +if table.unpack then + unpack=table.unpack +end +function table.merge(t1, t2) + for k,v in pairs(t2) do + if type(v) == 'table' then + if type(t1[k] or false) == 'table' then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 +end +multi = {} +multi.Version={'A',0,1}-- History: EventManager,EventManager+,MultiManager <-- Current After 6.3.0 Versioning scheme was altered. A.0.0 +multi.help=[[ +For a list of features do print(multi.Features) +For a list of changes do print(multi.changelog) +For current version do print(multi.Version) +For current stage do print(multi.stage) +For help do print(multi.help) :D +]] +multi.stage='stable' +multi.Features='Current Version: '..multi.Version[1]..'.'..multi.Version[2]..'.'..multi.Version[3]..' '..multi.stage..[[ +MultiManager has 19 Objects: # indicates most commonly used 1-19 1 being the most used by me ++Events #7 ++Alarms #2 ++Loops #3 ++Steps #4 ++TSteps #6 ++Triggers #16 ++Tasks #12 ++Connections #1 -- This is a rather new feature of this library, but has become the most useful for async handling. Knowing this is already 50% of this library ++Timers #14 -- this was tricky because these make up both Alarms and TSteps, but in purly using this standalone is almost non existent ++Jobs #11 ++Process #10 ++Conditions #15 ++Ranges #8 ++Threads #13 ++Functions #5 ++Queuers #17 ++Updaters #9 ++Watchers #18 ++CustomObjects #19 + +Constructors [Runners] +---------------------- Note: multi is the main Processor Obj It cannot be paused or destroyed (kinda) +intObj=multi:newProcess([string: FILE defualt: nil]) +intObj=multi:newQueuer([string: FILE defualt: nil]) + +Constructors [ACTORS] +--------------------- Note: everything is a multiObj! +eventObj=multi:newEvent([function: TASK defualt: function() end]) +alarmObj=multi:newAlarm([number: SET defualt: 0]) +loopObj=multi:newLoop([function: FUNC]) +stepObj=multi:newStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SKIP defualt: 0]) +tstepObj=multi:newTStep([number: START defualt: 0],[number: RESET defualt: inf],[number: COUNT defualt: 1],[number: SET defualt: 1]) +updaterObj=multi:newUpdater([number: SKIP defualt: 0]) +watcherObj=multi:newWatcher(table: NAMESPACE,string: NAME) +multiObj=multi:newCustomObject([table: OBJREF],[string: T='process']) +void=multi:newThread(string: name,function: func) + +Constructors [Semi-ACTORS] +-------------------------- +multi:newJob(function: func,[string: name]) +multi:newRange(number: a,number: b,[number: c]) +multi:newCondition(func) + +Constructors [NON-ACTORS] +------------------------- +multi:newTrigger(function: func) +multi:newTask(function: func) +multi:newConnection() +multi:newTimer() +multi:newFunction(function: func) +]] +multi.changelog=[[Changelog starts at Version A.0.0 +New in A.0.0 + Nothing really however a changelog will now be recorded! Feel free to remove this extra strings if space is a requriment + version.major.minor +New in A.1.0 + Changed: multi:newConnection(protect) method + Changed the way you are able to interact with it by adding the __call metamethod + Old usage: + + OnUpdate=multi:newConnection() + OnUpdate:connect(function(...) + print("Updating",...) + end) + OnUpdate:Fire(1,2,3) + + New usage: notice that connect is no longer needed! Both ways still work! and always will work :) + + OnUpdate=multi:newConnection() + OnUpdate(function(...) + print("Updating",...) + end) + OnUpdate:Fire(1,2,3) +]] +multi.__index = multi +multi.Mainloop={} +multi.Tasks={} +multi.Tasks2={} +multi.Garbage={} +multi.ender={} +multi.Children={} +multi.Paused={} +multi.Active=true +multi.fps=60 +multi.Id=-1 +multi.Type='mainprocess' +multi.Rest=0 +multi._type=type +multi.Jobs={} +multi.queue={} +multi.jobUS=2 +multi.clock=os.clock +multi.time=os.time +multi.LinkedPath=multi +multi.queuefinal=function(self) + self:Destroy() + if self.Parent.Mainloop[#self.Parent.Mainloop] then + self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() + else + for i=1,#self.Parent.funcE do + self.Parent.funcE[i](self) + end + self.Parent:Remove() + end +end +--Do not change these ever...Any other number will not work (Unless you are using enablePriority2() then change can be made. Just ensure that Priority_Idle is the greatest and Priority_Core is 1!) +multi.Priority_Core=1 +multi.Priority_High=4 +multi.Priority_Above_Normal=16 +multi.Priority_Normal=64 +multi.Priority_Below_Normal=256 +multi.Priority_Low=1024 +multi.Priority_Idle=4096 +multi.PList={multi.Priority_Core,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Idle} +multi.PStep=1 +--^^^^ +multi.PriorityTick=1 -- Between 1 and 4 any greater and problems arise +multi.Priority=multi.Priority_Core +function multi:setDomainName(name) + self[name]={} +end +function multi:linkDomain(name) + return self[name] +end +function multi:_Pause() + self.Active=false +end +function multi:setPriority(s) + if type(s)==number then + self.Priority=s + elseif type(s)=='string' then + if s:lower()=='core' or s:lower()=='c' then + self.Priority=self.Priority_Core + elseif s:lower()=='high' or s:lower()=='h' then + self.Priority=self.Priority_High + elseif s:lower()=='above' or s:lower()=='an' then + self.Priority=self.Priority_Above_Normal + elseif s:lower()=='normal' or s:lower()=='n' then + self.Priority=self.Priority_Normal + elseif s:lower()=='below' or s:lower()=='bn' then + self.Priority=self.Priority_Below_Normal + elseif s:lower()=='low' or s:lower()=='l' then + self.Priority=self.Priority_Low + elseif s:lower()=='idle' or s:lower()=='i' then + self.Priority=self.Priority_Idle + end + end +end +-- System +function os.getOS() + if package.config:sub(1,1)=='\\' then + return 'windows' + else + return 'unix' + end +end +if os.getOS()=='windows' then + function os.sleep(n) + if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end + end +else + function os.sleep(n) + os.execute('sleep ' .. tonumber(n)) + end +end +function multi:getParentProcess() + return self.Mainloop[self.CID] +end +function multi:Stop() + self.Active=false +end +function multi:condition(cond) + if not self.CD then + self:Pause() + self.held=true + self.CD=cond.condition + elseif not(cond.condition()) then + self.held=false + self:Resume() + self.CD=nil + return false + end + self.Parent:Do_Order() + return true +end +function multi:isHeld() + return self.held +end +function multi.executeFunction(name,...) + if type(_G[name])=='function' then + _G[name](...) + else + print('Error: Not a function') + end +end +function multi:waitFor(obj) + self:hold(function() return obj:isActive() end) +end +function multi:reboot(r) + local before=collectgarbage('count') + self.Mainloop={} + self.Tasks={} + self.Tasks2={} + self.Garbage={} + self.Children={} + self.Paused={} + self.Active=true + self.Id=-1 + if r then + for i,v in pairs(_G) do + if type(i)=='table' then + if i.Parent and i.Id and i.Act then + i={} + end + end + end + end + collectgarbage() + local after=collectgarbage('count') + print([[Before rebooting total Ram used was ]]..before..[[Kb +After rebooting total Ram used is ]]..after..[[ Kb +A total of ]]..(before-after)..[[Kb was cleaned up]]) +end +function multi:getChildren() + return self.Mainloop +end +--Processor +function multi:getError() + if self.error then + return self.error + end +end +function multi:Do_Order() + local Loop=self.Mainloop + _G.ID=0 + for _D=#Loop,1,-1 do + if Loop[_D] then + if Loop[_D].Active then + Loop[_D].Id=_D + self.CID=_D + Loop[_D]:Act() + end + end + end +end +function multi:enablePriority() + function self:Do_Order() + local Loop=self.Mainloop + _G.ID=0 + local PS=self + for _D=#Loop,1,-1 do + if Loop[_D] then + if (PS.PList[PS.PStep])%Loop[_D].Priority==0 then + if Loop[_D].Active then + Loop[_D].Id=_D + self.CID=_D + Loop[_D]:Act() + end + end + end + end + PS.PStep=PS.PStep+1 + if PS.PStep>7 then + PS.PStep=1 + end + end +end +function multi:enablePriority2() + function self:Do_Order() + local Loop=self.Mainloop + _G.ID=0 + local PS=self + for _D=#Loop,1,-1 do + if Loop[_D] then + if (PS.PStep)%Loop[_D].Priority==0 then + if Loop[_D].Active then + Loop[_D].Id=_D + self.CID=_D + Loop[_D]:Act() + end + end + end + end + PS.PStep=PS.PStep+1 + if PS.PStep>self.Priority_Idle then + PS.PStep=1 + end + end +end +multi.disablePriority=multi.unProtect +function multi:fromfile(path,int) + int=int or self + local test2={} + local test=bin.load(path) + local tp=test:getBlock('s') + if tp=='event' then + test2=int:newEvent(test:getBlock('f')) + local t=test:getBlock('t') + for i=1,#t do + test2:OnEvent(t[i]) + end + elseif tp=='alarm' then + test2=int:newAlarm(test:getBlock('n')) + elseif tp=='loop' then + test2=int:newLoop(test:getBlock('t')[1]) + elseif tp=='step' or tp=='tstep' then + local func=test:getBlock('t') + local funcE=test:getBlock('t') + local funcS=test:getBlock('t') + local tab=test:getBlock('t') + test2=int:newStep() + table.merge(test2,tab) + test2.funcE=funcE + test2.funcS=funcS + test2.func=func + elseif tp=='trigger' then + test2=int:newTrigger(test:getBlock('f')) + elseif tp=='connector' then + test2=int:newConnection() + test2.func=test:getBlock('t') + elseif tp=='timer' then + test2=int:newTimer() + test2.count=tonumber(test:getBlock('n')) + else + print('Error: The file you selected is not a valid multi file object!') + return false + end + return test2 +end +function multi:benchMark(sec,p) + local temp=self:newLoop(function(t,self) + if self.clock()-self.init>self.sec then + print(self.c..' steps in '..self.sec..' second(s)') + self.tt(self.sec) + self:Destroy() + else + self.c=self.c+1 + end + end) + temp.Priority=p or 1 + function temp:OnBench(func) + self.tt=func + end + self.tt=function() end + temp.sec=sec + temp.init=self.clock() + temp.c=0 + return temp +end +function multi:tofile(path) + local items=self:getChildren() + io.mkDir(io.getName(path)) + for i=1,#items do + items[i]:tofile(io.getName(path)..'\\item'..item[i]..'.dat') + end + local int=bin.new() + int:addBlock('process') + int:addBlock(io.getName(path)) + int:addBlock(#self.Mainloop) + int:addBlock(self.Active) + int:addBlock(self.Rest) + int:addBlock(self.Jobs) + int:tofile() +end +function multi.startFPSMonitior() + if not multi.runFPS then + multi.doFPS(s) + multi.runFPS=true + end +end +function multi.doFPS(s) + multi:benchMark(1):OnBench(doFPS) + if s then + multi.fps=s + end +end +--Helpers +function multi:OnMainConnect(func) + table.insert(self.func,func) +end +function multi:protect() + function self:Do_Order() + local Loop=self.Mainloop + for _D=#Loop,1,-1 do + if Loop[_D]~=nil then + Loop[_D].Id=_D + self.CID=_D + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err and not(Loop[_D].error) then + Loop[_D].error=err + self.OnError:Fire(err,Loop[_D]) + end + end + end + end +end +function multi:unProtect() + local Loop=self.Mainloop + _G.ID=0 + for _D=#Loop,1,-1 do + if Loop[_D] then + if Loop[_D].Active then + Loop[_D].Id=_D + self.CID=_D + Loop[_D]:Act() + end + end + end +end +function multi:setJobSpeed(n) + self.jobUS=n +end +function multi:hasJobs() + return #self.Jobs>0,#self.Jobs +end +function multi:getJobs() + return #self.Jobs +end +function multi:removeJob(name) + for i=#self.Jobs,1,-1 do + if self.Jobs[i][2]==name then + table.remove(self.Jobs,i) + end + end +end +function multi:FreeMainEvent() + self.func={} +end +function multi:connectFinal(func) + if self.Type=='event' then + self:OnEvent(func) + elseif self.Type=='alarm' then + self:OnRing(func) + elseif self.Type=='step' or self.Type=='tstep' then + self:OnEnd(func) + else + print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(function) to trigger it's final event!") + self:OnBreak(func) + end +end +function multi:Break() + self:Pause() + self.Active=nil + for i=1,#self.ender do + if self.ender[i] then + self.ender[i](self) + end + end +end +function multi:OnBreak(func) + table.insert(self.ender,func) +end +function multi:isPaused() + return not(self.Active) +end +function multi:isActive() + return self.Active +end +function multi:getType() + return self.Type +end +function multi:Sleep(n) + self:hold(n) +end +function multi:Pause() + if self.Type=='mainprocess' then + print("You cannot pause the main process. Doing so will stop all methods and freeze your program! However if you still want to use multi:_Pause()") + else + self.Active=false + if self.Parent.Mainloop[self.Id]~=nil then + table.remove(self.Parent.Mainloop,self.Id) + table.insert(self.Parent.Paused,self) + self.PId=#self.Parent.Paused + end + end +end +function multi:Resume() + if self.Type=='process' or self.Type=='mainprocess' then + self.Active=true + local c=self:getChildren() + for i=1,#c do + c[i]:Resume() + end + else + if self:isPaused() then + table.remove(self.Parent.Paused,self.PId) + table.insert(self.Parent.Mainloop,self) + self.Id=#self.Parent.Mainloop + self.Active=true + end + end +end +function multi:resurrect() + table.insert(self.Parent.Mainloop,self) + self.Active=true +end +function multi:Destroy() + if self.Type=='process' or self.Type=='mainprocess' then + local c=self:getChildren() + for i=1,#c do + self.OnObjectDestroyed:Fire(c[i]) + c[i]:Destroy() + end + else + for i=1,#self.Parent.Mainloop do + if self.Parent.Mainloop[i]==self then + self.Parent.OnObjectDestroyed:Fire(self) + table.remove(self.Parent.Mainloop,i) + break + end + end + self.Active=false + end +end + +function multi:hold(task) + self:Pause() + self.held=true + if type(task)=='number' then + local alarm=self.Parent:newAlarm(task) + while alarm.Active==true do + if love then + self.Parent:lManager() + else + self.Parent:Do_Order() + end + end + alarm:Destroy() + self:Resume() + self.held=false + elseif type(task)=='function' then + local env=self.Parent:newEvent(task) + env:OnEvent(function(envt) envt:Pause() envt.Active=false end) + while env.Active do + if love then + self.Parent:lManager() + else + self.Parent:Do_Order() + end + end + env:Destroy() + self:Resume() + self.held=false + else + print('Error Data Type!!!') + end +end +function multi:oneTime(func,...) + if not(self.Type=='mainprocess' or self.Type=='process') then + for _k=1,#self.Parent.Tasks2 do + if self.Parent.Tasks2[_k]==func then + return false + end + end + table.insert(self.Parent.Tasks2,func) + func(...) + return true + else + for _k=1,#self.Tasks2 do + if self.Tasks2[_k]==func then + return false + end + end + table.insert(self.Tasks2,func) + func(...) + return true + end +end +function multi:Reset(n) + self:Resume() +end +function multi:isDone() + return self.Active~=true +end +function multi:create(ref) + multi.OnObjectCreated:Fire(ref) +end +--Constructors [CORE] +function multi:newBase(ins) + if not(self.Type=='mainprocess' or self.Type=='process' or self.Type=='queue') then error('Can only create an object on multi or an interface obj') return false end + local c = {} + if self.Type=='process' or self.Type=='queue' then + setmetatable(c, self.Parent) + else + setmetatable(c, self) + end + c.Active=true + c.func={} + c.ender={} + c.Id=0 + c.PId=0 + c.Act=function() end + c.Parent=self + c.held=false + if ins then + table.insert(self.Mainloop,ins,c) + else + table.insert(self.Mainloop,c) + end + return c +end +function multi:newProcess(file) + if not(self.Type=='mainprocess') then error('Can only create an interface on the multi obj') return false end + local c = {} + setmetatable(c, self) + c.Parent=self + c.Active=true + c.func={} + c.Id=0 + c.Type='process' + c.Mainloop={} + c.Tasks={} + c.Tasks2={} + c.Garbage={} + c.Children={} + c.Paused={} + c.Active=true + c.Id=-1 + c.Rest=0 + c.Jobs={} + c.queue={} + c.jobUS=2 + function c:Start() + if self.l then + self.l:Resume() + else + self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) + end + end + function c:Pause() + if self.l then + self.l:Pause() + end + end + function c:Remove() + self:Destroy() + self.l:Destroy() + end + if file then + self.Cself=c + loadstring('local interface=multi.Cself '..io.open(file,'rb'):read('*all'))() + end + self:create(c) + return c +end +function multi:newQueuer(file) + local c=self:newProcess() + c.Type='queue' + c.last={} + c.funcE={} + function c:OnQueueCompleted(func) + table.insert(self.funcE,func) + end + if file then + self.Cself=c + loadstring('local queue=multi.Cself '..io.open(file,'rb'):read('*all'))() + end + self:create(c) + return c +end +--Constructors [ACTORS] +function multi:newCustomObject(objRef,t) + local c={} + if t=='process' then + if self.Type=='queue' then + c=self:newBase(1) + self.last=c + print("This Custom Object was created on a queue! Ensure that it has a way to end! All objects have a obj:Break() method!") + else + c=self:newBase() + end + if type(objRef)=='table' then + table.merge(c,objRef) + end + if not c.Act then + function c:Act() + -- Empty function + end + end + else + c=objRef or {} + end + if not c.Type then + c.Type='coustomObject' + end + if self.Type=='queue' then + if #self.Mainloop>1 then + c:Pause() + end + c:connectFinal(multi.queuefinal) + end + self:create(c) + return c +end +function multi:newEvent(task) + local c={} + if self.Type=='queue' then + c=self:newBase(1) + self.last=c + else + c=self:newBase() + end + c.Type='event' + c.Task=task or function() end + function c:Act() + if self.Task(self) then + self:Pause() + for _E=1,#self.func do + self.func[_E](self) + end + end + end + function c:OnEvent(func) + table.insert(self.func,func) + end + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.Task) + m:addBlock(self.func) + m:addBlock(self.Active) + m:tofile(path) + end + if self.Type=='queue' then + if #self.Mainloop>1 then + c:Pause() + end + c:connectFinal(multi.queuefinal) + end + self:create(c) + return c +end +function multi:newAlarm(set) + local c={} + if self.Type=='queue' then + c=self:newBase(1) + self.last=c + else + c=self:newBase() + end + c.Type='alarm' + c.Priority=self.Priority_Low + c.timer=self:newTimer() + c.set=set or 0 + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.set) + m:addBlock(self.Active) + m:tofile(path) + end + function c:Act() + if self.timer:Get()>=self.set then + self:Pause() + self.Active=false + for i=1,#self.func do + self.func[i](self) + end + end + end + function c:Resume() + self.Parent.Resume(self) + self.timer:Resume() + end + function c:Reset(n) + if n then self.set=n end + self:Resume() + self.timer:Reset() + end + function c:OnRing(func) + table.insert(self.func,func) + end + function c:Pause() + self.timer:Pause() + self.Parent.Pause(self) + end + if self.Type=='queue' then + c:Pause() + c:connectFinal(multi.queuefinal) + else + c.timer:Start() + end + self:create(c) + return c +end +function multi:newLoop(func) + local c={} + if self.Type=='queue' then + c=self:newBase(1) + self.last=c + else + c=self:newBase() + end + c.Type='loop' + c.Start=self.clock() + if func then + c.func={func} + end + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.func) + m:addBlock(self.Active) + m:tofile(path) + end + function c:Act() + for i=1,#self.func do + self.func[i](self.Parent.clock()-self.Start,self) + end + end + function c:OnLoop(func) + table.insert(self.func,func) + end + if self.Type=='queue' then + if #self.Mainloop>1 then + c:Pause() + end + c:connectFinal(multi.queuefinal) + end + self:create(c) + return c +end +function multi:newUpdater(skip) + local c={} + if self.Type=='queue' then + c=self:newBase(1) + self.last=c + else + c=self:newBase() + end + c.Type='updater' + c.pos=1 + c.skip=skip or 1 + function c:Act() + if self.pos>=self.skip then + self.pos=0 + for i=1,#self.func do + self.func[i](self) + end + end + self.pos=self.pos+1 + end + function c:setSkip(n) + self.skip=n + end + c.OnUpdate=self.OnMainConnect + if self.Type=='queue' then + if #self.Mainloop>1 then + c:Pause() + end + c:connectFinal(multi.queuefinal) + end + self:create(c) + return c +end +function multi:newStep(start,reset,count,skip) + local c={} + if self.Type=='queue' then + c=self:newBase(1) + self.last=c + else + c=self:newBase() + end + think=1 + c.Type='step' + c.pos=start or 1 + c.endAt=reset or math.huge + c.skip=skip or 0 + c.spos=0 + c.count=count or 1*think + c.funcE={} + c.funcS={} + c.start=start or 1 + if start~=nil and reset~=nil then + if start>reset then + think=-1 + end + end + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.func) + m:addBlock(self.funcE) + m:addBlock(self.funcS) + m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start}) + m:addBlock(self.Active) + m:tofile(path) + end + function c:Act() + if self~=nil then + if self.spos==0 then + if self.pos==self.start then + for fe=1,#self.funcS do + self.funcS[fe](self) + end + end + for i=1,#self.func do + self.func[i](self.pos,self) + end + self.pos=self.pos+self.count + if self.pos-self.count==self.endAt then + self:Pause() + for fe=1,#self.funcE do + self.funcE[fe](self) + end + self.pos=self.start + end + end + end + self.spos=self.spos+1 + if self.spos>=self.skip then + self.spos=0 + end + end + c.Reset=c.Resume + function c:OnStart(func) + table.insert(self.funcS,func) + end + function c:OnStep(func) + table.insert(self.func,1,func) + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Break() + self.Active=nil + end + function c:Update(start,reset,count,skip) + self.start=start or self.start + self.endAt=reset or self.endAt + self.skip=skip or self.skip + self.count=count or self.count + self:Resume() + end + if self.Type=='queue' then + if #self.Mainloop>1 then + c:Pause() + end + c:connectFinal(multi.queuefinal) + end + self:create(c) + return c +end +function multi:newTStep(start,reset,count,set) + local c={} + if self.Type=='queue' then + c=self:newBase(1) + self.last=c + else + c=self:newBase() + end + think=1 + c.Type='tstep' + c.Priority=self.Priority_Low + c.start=start or 1 + local reset = reset or math.huge + c.endAt=reset + c.pos=start or 1 + c.skip=skip or 0 + c.count=count or 1*think + c.funcE={} + c.timer=self.clock() + c.set=set or 1 + c.funcS={} + function c:Update(start,reset,count,set) + self.start=start or self.start + self.pos=self.start + self.endAt=reset or self.endAt + self.set=set or self.set + self.count=count or self.count or 1 + self.timer=self.clock() + self:Resume() + end + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.func) + m:addBlock(self.funcE) + m:addBlock(self.funcS) + m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set}) + m:addBlock(self.Active) + m:tofile(path) + end + function c:Act() + if self.clock()-self.timer>=self.set then + self:Reset() + if self.pos==self.start then + for fe=1,#self.funcS do + self.funcS[fe](self) + end + end + for i=1,#self.func do + self.func[i](self.pos,self) + end + self.pos=self.pos+self.count + if self.pos-self.count==self.endAt then + self:Pause() + for fe=1,#self.funcE do + self.funcE[fe](self) + end + self.pos=self.start + end + end + end + function c:OnStart(func) + table.insert(self.funcS,func) + end + function c:OnStep(func) + table.insert(self.func,func) + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Break() + self.Active=nil + end + function c:Reset(n) + if n then self.set=n end + self.timer=self.clock() + self:Resume() + end + if self.Type=='queue' then + if #self.Mainloop>1 then + c:Pause() + end + c:connectFinal(multi.queuefinal) + end + self:create(c) + return c +end +function multi:newWatcher(namespace,name) + local function WatcherObj(ns,n) + if self.Type=='queue' then + print("Cannot create a watcher on a queue! Creating on 'multi' instead!") + self=multi + end + local c=self:newBase() + c.Type='watcher' + c.ns=ns + c.n=n + c.cv=ns[n] + function c:OnValueChanged(func) + table.insert(self.func,func) + end + function c:Act() + if self.cv~=self.ns[self.n] then + for i=1,#self.func do + self.func[i](self,self.cv,self.ns[self.n]) + end + self.cv=self.ns[self.n] + end + end + self:create(c) + return c + end + if type(namespace)~='table' and type(namespace)=='string' then + return WatcherObj(_G,namespace) + elseif type(namespace)=='table' and (type(name)=='string' or 'number') then + return WatcherObj(namespace,name) + else + print('Warning, invalid arguments! Nothing returned!') + end +end +function multi:newThread(name,func) + local c={} + c.ref={} + c.Name=name + c.thread=coroutine.create(func) + c.sleep=1 + c.firstRunDone=false + c.timer=multi.scheduler:newTimer() + c.ref.Globals=self:linkDomain("Globals") + function c.ref:send(name,val) + ret=coroutine.yield({Name=name,Value=val}) + self:syncGlobals(ret) + end + function c.ref:get(name) + return self.Globals[name] + end + function c.ref:kill() + err=coroutine.yield({"_kill_"}) + if err then + error("Failed to kill a thread! Exiting...") + end + end + function c.ref:sleep(n) + n = tonumber(n) or 0 + ret=coroutine.yield({"_sleep_",n}) + self:syncGlobals(ret) + end + function c.ref:syncGlobals(v) + self.Globals=v + end + table.insert(self:linkDomain("Threads"),c) + if not multi.scheduler:isActive() then + multi.scheduler:Resume() + end +end +-- Constructors [SEMI-ACTORS] +function multi:newJob(func,name) + if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end + local c = {} + if self.Type=='process' then + setmetatable(c, self.Parent) + else + setmetatable(c, self) + end + c.Active=true + c.func={} + c.Id=0 + c.PId=0 + c.Parent=self + c.Type='job' + c.trigfunc=func or function() end + function c:Act() + self:trigfunc(self) + end + table.insert(self.Jobs,{c,name}) + if self.JobRunner==nil then + self.JobRunner=self:newAlarm(self.jobUS) + self.JobRunner:OnRing(function(self) + if #self.Parent.Jobs>0 then + if self.Parent.Jobs[1] then + self.Parent.Jobs[1][1]:Act() + table.remove(self.Parent.Jobs,1) + end + end + self:Reset(self.Parent.jobUS) + end) + end +end +function multi:newRange() + selflink=self + local temp={ + getN = function(self) selflink:Do_Order() self.n=self.n+self.c if self.n>self.b then self.Link.held=false self.Link:Resume() return nil end return self.n end, + } + setmetatable(temp,{ + __call=function(self,a,b,c) + self.c=c or 1 + self.n=a-self.c + self.a=a + self.b=b + self.Link=selflink.Parent.Mainloop[selflink.CID] + self.Link:Pause() + self.Link.held=true + return function() return self:getN() end + end + }) + self:create(temp) + return temp +end +function multi:newCondition(func) + local c={['condition']=func} + self:create(c) + return c +end +-- Constructors [NON-ACTORS] +function multi:newFunction(func) + local c={} + c.func=func + mt={ + __index=multi, + __call=function(self,...) if self.Active then return self:func(...) end local t={...} return "PAUSED" end + } + c.Parent=self + function c:Pause() + self.Active=false + end + function c:Resume() + self.Active=true + end + setmetatable(c,mt) + self:create(c) + return c +end +function multi:newTimer() + local c={} + c.Type='timer' + c.time=0 + c.count=0 + function c:Start() + self.time=os.clock() + end + function c:Get() + return (os.clock()-self.time)+self.count + end + c.Reset=c.Start + function c:Pause() + self.time=self:Get() + end + function c:Resume() + self.time=os.clock()-self.time + end + function c:tofile(path) + local m=bin.new() + self.count=self.count+self:Get() + m:addBlock(self.Type) + m:addBlock(self.count) + m:tofile(path) + end + self:create(c) + return c +end +function multi:newTask(func) + table.insert(self.Tasks,func) +end +function multi:newTrigger(func) + local c={} + c.Type='trigger' + c.trigfunc=func or function() end + function c:Fire(...) + self:trigfunc(self,...) + end + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.trigfunc) + m:tofile(path) + end + self:create(c) + return c +end +function multi:newConnection(protect) + local c={} + setmetatable(c,{__call=function(self,...) self:connect(...) end}) + c.Type='connector' + c.func={} + c.ID=0 + c.protect=protect or true + function c:Fire(...) + local ret={} + for i=#self.func,1,-1 do + if self.protect then + local temp={pcall(self.func[i][1],...)} + if temp[1] then + table.remove(temp,1) + table.insert(ret,temp) + else + print(temp[2]) + end + else + table.insert(ret,{self.func[i][1](...)}) + end + end + return ret + end + function c:bind(t) + self.func=t + end + function c:remove() + self.func={} + end + function c:connect(func) + self.ID=self.ID+1 + table.insert(self.func,1,{func,self.ID}) + return { + Link=self.func, + ID=self.ID, + remove=function(self) + for i=1,#self.Link do + if self.Link[i][2]~=nil then + if self.Link[i][2]==self.ID then + table.remove(self.Link,i) + self.remove=function() end + self.Link=nil + self.ID=nil + return true + end + end + end + end + } + end + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.func) + m:tofile(path) + end + return c +end +multi.OnObjectCreated=multi:newConnection() +multi.OnObjectDestroyed=multi:newConnection() +--Managers +function multi:mainloop() + for i=1,#self.Tasks do + self.Tasks[i](self) + end + rawset(self,'Start',self.clock()) + while self.Active do + self:Do_Order() + end + print("Did you call multi:Stop()? This method should not be used when using multi:mainloop()! You now need to restart the multiManager, by using multi:reboot() and calling multi:mainloop() again or by using multi:uManager()") +end +function multi._tFunc(self,dt) + for i=1,#self.Tasks do + self.Tasks[i](self) + end + if dt then + self.pump=true + end + self.pumpvar=dt + rawset(self,'Start',self.clock()) +end +function multi:uManager(dt) + if self.Active then + self:oneTime(self._tFunc,self,dt) + function self:uManager(dt) + self:Do_Order() + end + self:Do_Order() + end +end +--Thread Setup Stuff +multi:setDomainName("Threads") +multi:setDomainName("Globals") +-- Scheduler +multi.scheduler=multi:newUpdater() +multi.scheduler.Type="scheduler" +function multi.scheduler:setStep(n) + self.skip=tonumber(n) or 24 +end +multi.scheduler.Threads=multi:linkDomain("Threads") +multi.scheduler.Globals=multi:linkDomain("Globals") +multi.scheduler:OnUpdate(function(self) + for i=#self.Threads,1,-1 do + ret={} + if coroutine.status(self.Threads[i].thread)=="dead" then + table.remove(self.Threads,i) + else + if self.Threads[i].timer:Get()>=self.Threads[i].sleep then + if self.Threads[i].firstRunDone==false then + self.Threads[i].firstRunDone=true + self.Threads[i].timer:Start() + _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) + else + _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) + end + if ret==true or ret==false then + print("Thread Ended!!!") + ret={} + end + end + if ret then + if ret[1]=="_kill_" then + table.remove(self.Threads,i) + elseif ret[1]=="_sleep_" then + self.Threads[i].timer:Reset() + self.Threads[i].sleep=ret[2] + elseif ret.Name then + self.Globals[ret.Name]=ret.Value + end + end + end + end +end) +multi.scheduler:setStep() +multi.scheduler:Pause() +multi.OnError=multi:newConnection() diff --git a/Libs/README.txt b/Libs/README.txt new file mode 100644 index 0000000..02b5fb6 --- /dev/null +++ b/Libs/README.txt @@ -0,0 +1,2 @@ +These libraries Namely the MultiManager, bin, and the Library, libraries will be documented because i plan on sharing them +everything else will mostlikely not be documented \ No newline at end of file diff --git a/Libs/T1.lua b/Libs/T1.lua new file mode 100644 index 0000000..f861efa --- /dev/null +++ b/Libs/T1.lua @@ -0,0 +1,598 @@ +require("love.timer") +require("love.system") +require("love.sound") +require("love.physics") +require("love.mouse") +require("love.math") +require("love.keyboard") +require("love.joystick") +require("love.image") +require("love.font") +require("love.filesystem") +require("love.event") +require("love.audio") +require("love.graphics") +require("love.window") +_defaultfont = love.graphics.getFont() +gui = {} +function gui.getTile(i,x,y,w,h)-- returns imagedata + if type(i)=="userdata" then + -- do nothing + else + error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") + end + local iw,ih=i:getDimensions() + local id,_id=i:getData(),love.image.newImageData(w,h) + for _x=x,w+x-1 do + for _y=y,h+y-1 do + _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) + end + end + return love.graphics.newImage(_id) +end +multi = {} +multi.Version="4.0.0" +multi.__index = multi +multi.Mainloop={} +multi.Tasks={} +multi.Tasks2={} +multi.Garbage={} +multi.Children={} +multi.Paused={} +multi.MasterId=0 +multi.Active=true +multi.Id=-1 +multi.Type="MainInt" +multi.Rest=0 +-- System +os.sleep=love.timer.sleep +function multi:newBase(ins) + if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end + local c = {} + if self.Type=="int" then + setmetatable(c, self.Parent) + else + setmetatable(c, self) + end + c.Active=true + c.func={} + c.Id=0 + c.Act=function() end + c.Parent=self + if ins then + table.insert(self.Mainloop,ins,c) + else + table.insert(self.Mainloop,c) + end + self.MasterId=self.MasterId+1 + return c +end +function multi:reboot(r) + self.Mainloop={} + self.Tasks={} + self.Tasks2={} + self.Garbage={} + self.Children={} + self.Paused={} + self.MasterId=0 + self.Active=true + self.Id=-1 + if r then + for i,v in pairs(_G) do + if type(i)=="table" then + if i.Parent and i.Id and i.Act then + i={} + end + end + end + end +end +function multi:getChildren() + return self.Mainloop +end +--Processor +function multi:Do_Order() + for _D=#self.Mainloop,1,-1 do + if self.Mainloop[_D]~=nil then + self.Mainloop[_D].Id=_D + self.Mainloop[_D]:Act() + end + if self.Mainloop[_D].rem then + table.remove(self.Mainloop,_D) + end + end + if self.Rest>0 then + os.sleep(self.Rest) + end +end +function multi:benchMark(sec) + local temp=self:newLoop(function(t,self) + if os.clock()-self.init>self.sec then + print(self.c.." steps in "..self.sec.." second(s)") + self.tt(self.sec) + self:Destroy() + else + self.c=self.c+1 + end + end) + function temp:OnBench(func) + self.tt=func + end + self.tt=function() end + temp.sec=sec + temp.init=os.clock() + temp.c=0 + return temp +end +function multi:newInterface() + if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end + local c = {} + setmetatable(c, self) + c.Parent=self + c.Active=true + c.func={} + c.Id=0 + c.Type="int" + c.Mainloop={} + c.Tasks={} + c.Tasks2={} + c.Garbage={} + c.Children={} + c.Paused={} + c.MasterId=0 + c.Active=true + c.Id=-1 + c.Rest=0 + function c:Start() + if self.l then + self.l:Resume() + else + self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) + end + end + function c:Stop() + if self.l then + self.l:Pause() + end + end + function c:Remove() + self:Destroy() + self.l:Destroy() + end + return c +end +--Helpers +function multi:FreeMainEvent() + self.func={} +end +function multi:isPaused() + return not(self.Active) +end +function multi:Pause(n) + if self.Type=="int" or self.Type=="MainInt" then + self.Active=false + if not(n) then + local c=self:getChildren() + for i=1,#c do + c[i]:Pause() + end + else + self:hold(n) + end + else + if not(n) then + self.Active=false + if self.Parent.Mainloop[self.Id]~=nil then + table.remove(self.Parent.Mainloop,self.Id) + table.insert(self.Parent.Paused,self) + self.Id=#self.Parent.Paused + end + else + self:hold(n) + end + end +end +function multi:Resume() + if self.Type=="int" or self.Type=="MainInt" then + self.Active=true + local c=self:getChildren() + for i=1,#c do + c[i]:Resume() + end + else + if self:isPaused() then + self.Active=true + for i=1,#self.Parent.Paused do + if self.Parent.Paused[i]==self then + table.remove(self.Parent.Paused,i) + return + end + end + table.insert(self.Parent.Mainloop,self) + end + end +end +function multi:Destroy() + if self.Type=="int" or self.Type=="MainInt" then + local c=self:getChildren() + for i=1,#c do + c[i]:Destroy() + end + else + self.rem=true + end +end +function multi:hold(task) + self:Pause() + if type(task)=="number" then + local alarm=self:newAlarm(task) + while alarm.Active==true do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + alarm:Destroy() + self:Resume() + elseif type(task)=="function" then + local env=self.Parent:newEvent(task) + env:OnEvent(function(envt) envt:Pause() envt:Stop() end) + while env.Active do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + env:Destroy() + self:Resume() + else + print("Error Data Type!!!") + end +end +function multi:oneTime(func,...) + if not(self.Type=="MainInt" or self.Type=="int") then + for _k=1,#self.Parent.Tasks2 do + if self.Parent.Tasks2[_k]==func then + return false + end + end + table.insert(self.Parent.Tasks2,func) + func(...) + return true + else + for _k=1,#self.Tasks2 do + if self.Tasks2[_k]==func then + return false + end + end + table.insert(self.Tasks2,func) + func(...) + return true + end +end +--Constructors +function multi:newEvent(task) + local c=self:newBase() + c.Type="Event" + c.Task=task or function() end + function c:Act() + if self.Task(self) and self.Active==true then + self:Pause() + for _E=1,#self.func do + self.func[_E](self) + end + end + end + function c:OnEvent(func) + table.insert(self.func,func) + end + return c +end +function multi:newAlarm(set) + local c=self:newBase() + c.Type="Alarm" + c.timer=os.clock() + c.set=set or 0 + function c:Act() + if self.Active==true then + if os.clock()-self.timer>=self.set then + self:Pause() + for i=1,#self.func do + self.func[i](self) + end + end + end + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnRing(func) + table.insert(self.func,func) + end + return c +end +function multi:newTask(func) + table.insert(self.Tasks,func) +end +function multi:newLoop(func) + local c=self:newBase() + c.Type="Loop" + if func then + c.func={func} + end + function c:Act() + if self.Active==true then + for i=1,#self.func do + self.func[i](os.clock()-self.Parent.Start,self) + end + end + end + function c:OnLoop(func) + table.insert(self.func,func) + end + return c +end +function multi:newStep(start,reset,count,skip) + local c=self:newBase() + think=1 + c.Type="Step" + c.pos=start or 1 + c.endAt=reset or math.huge + c.skip=skip or 0 + c.spos=0 + c.count=count or 1*think + c.funcE={} + c.start=start or 1 + if start~=nil and reset~=nil then + if start>reset then + think=-1 + end + end + function c:Act() + if self~=nil then + if self.spos==0 then + if self.Active==true then + for i=1,#self.func do + self.func[i](self.pos,self) + end + self.pos=self.pos+self.count + end + end + end + self.spos=self.spos+1 + if self.spos>=self.skip then + self.spos=0 + end + end + function c:OnStep(func) + table.insert(self.func,1,func) + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Update(start,reset,count,skip) + self.start=start or self.start + self.endAt=reset or self.endAt + self.skip=skip or self.skip + self.count=count or self.count + self:Resume() + end + c:OnStep(function(p,s) + if s.count>0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + elseif s.count<0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + end + end) + return c +end +function multi:newTStep(start,reset,count,set) + local c=self:newBase() + think=1 + c.Type="TStep" + c.start=start or 1 + local reset = reset or math.huge + c.endAt=reset + c.pos=start or 1 + c.skip=skip or 0 + c.count=count or 1*think + c.funcE={} + c.timer=os.clock() + c.set=set or 1 + function c:Update(start,reset,count,set) + self.start=start or self.start + self.pos=start + self.endAt=reset or self.endAt + self.set=set or self.set + self.count=count or self.count or 1 + self.timer=os.clock() + self:Resume() + end + function c:Act() + if self.Active then + if os.clock()-self.timer>=self.set then + self:Reset() + for i=1,#self.func do + self.func[i](self.pos,self) + end + if self.endAt==self.pos then + for fe=1,#self.funcE do + self.funcE[fe](self) + end + self.pos=self.start-1 + end + self.pos=self.pos+self.count + end + end + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnStep(func) + table.insert(self.func,func) + end + return c +end +function multi:newTrigger(func) + local c=self:newBase() + c.Type="Trigger" + c.trigfunc=func or function() end + function c:Fire(...) + self:trigfunc(self,...) + end + return c +end +--Managers +function multi:mainloop() + for i=1,#self.Tasks do + self.Tasks[i](self) + end + self.Start=os.clock() + while self.Active do + self:Do_Order() + end +end +function multi._tFunc(self,dt) + for i=1,#self.Tasks do + self.Tasks[i](self) + end + print("once!") + if dt then + self.pump=true + end + self.pumpvar=dt + self.Start=os.clock() +end +function multi:uManager(dt) + self:oneTime(self._tFunc,self,dt) + self:Do_Order() +end +multi.drawF={} +function multi:dManager() + for ii=1,#multi.drawF do + multi.drawF[ii]() + end +end +function multi:onDraw(func) + table.insert(self.drawF,func) +end +function multi:lManager() + if love.event then + love.event.pump() + for e,a,b,c,d in love.event.poll() do + if e == "quit" then + if not love.quit or not love.quit() then + if love.audio then + love.audio.stop() + end + return nil + end + end + love.handlers[e](a,b,c,d) + end + end + if love.timer then + love.timer.step() + dt = love.timer.getDelta() + end + if love.update then love.update(dt) end + multi:uManager(dt) + if love.window and love.graphics and love.window.isCreated() then + love.graphics.clear() + love.graphics.origin() + if love.draw then love.draw() end + multi.dManager() + love.graphics.setColor(255,255,255,255) + if multi.draw then multi.draw() end + love.graphics.present() + end +end +Thread={} +Thread.Name="Thread 1" +Thread.ChannelThread = love.thread.getChannel("Easy1") +Thread.ChannelMain = love.thread.getChannel("EasyMain") +Thread.Global = {} +function Thread:packTable(G) + function escapeStr(str) + local temp="" + for i=1,#str do + temp=temp.."\\"..string.byte(string.sub(str,i,i)) + end + return temp + end + function ToStr(t) + local dat="{" + for i,v in pairs(t) do + if type(i)=="number" then + i="["..i.."]=" + else + i=i.."=" + end + if type(v)=="string" then + dat=dat..i.."\""..v.."\"," + elseif type(v)=="number" then + dat=dat..i..v.."," + elseif type(v)=="boolean" then + dat=dat..i..tostring(v).."," + elseif type(v)=="table" and not(G==v) then + dat=dat..i..ToStr(v).."," + --elseif type(v)=="table" and G==v then + -- dat=dat..i.."assert(loadstring(\"return self\"))," + elseif type(v)=="function" then + dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," + end + end + return string.sub(dat,1,-2).."}" + end + return "return "..ToStr(G) +end +function Thread:Send(name,var) + arg3="1" + if type(var)=="table" then + var=Thread:packTable(var) + arg3="table" + end + self.ChannelMain:push({name,var,arg3}) +end +function Thread:UnPackChannel() + local c=self.ChannelThread:getCount() + for i=1,c do + local temp=self.ChannelThread:pop() + if temp[1] and temp[2] then + if temp[1]=="func" and type(temp[2])=="string" then + loadstring(temp[2])(temp[3]) + elseif temp[1]=="table" then + _G[temp[3]]=loadstring(temp[2])() + else + _G[temp[1]]=temp[2] + end + end + end + if #multi:getChildren()<2 then + os.sleep(.05) + end +end +function Thread:boost(func,name) + self:Send(name,string.dump(func)) +end +function Thread.mainloop() + Thread:UnPackChannel() +end +Thread.MainThread=false +multi:newLoop():OnLoop(Thread.mainloop) +multi:mainloop() diff --git a/Libs/T2.lua b/Libs/T2.lua new file mode 100644 index 0000000..44e2fbf --- /dev/null +++ b/Libs/T2.lua @@ -0,0 +1,598 @@ +require("love.timer") +require("love.system") +require("love.sound") +require("love.physics") +require("love.mouse") +require("love.math") +require("love.keyboard") +require("love.joystick") +require("love.image") +require("love.font") +require("love.filesystem") +require("love.event") +require("love.audio") +require("love.graphics") +require("love.window") +_defaultfont = love.graphics.getFont() +gui = {} +function gui.getTile(i,x,y,w,h)-- returns imagedata + if type(i)=="userdata" then + -- do nothing + else + error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") + end + local iw,ih=i:getDimensions() + local id,_id=i:getData(),love.image.newImageData(w,h) + for _x=x,w+x-1 do + for _y=y,h+y-1 do + _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) + end + end + return love.graphics.newImage(_id) +end +multi = {} +multi.Version="4.0.0" +multi.__index = multi +multi.Mainloop={} +multi.Tasks={} +multi.Tasks2={} +multi.Garbage={} +multi.Children={} +multi.Paused={} +multi.MasterId=0 +multi.Active=true +multi.Id=-1 +multi.Type="MainInt" +multi.Rest=0 +-- System +os.sleep=love.timer.sleep +function multi:newBase(ins) + if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end + local c = {} + if self.Type=="int" then + setmetatable(c, self.Parent) + else + setmetatable(c, self) + end + c.Active=true + c.func={} + c.Id=0 + c.Act=function() end + c.Parent=self + if ins then + table.insert(self.Mainloop,ins,c) + else + table.insert(self.Mainloop,c) + end + self.MasterId=self.MasterId+1 + return c +end +function multi:reboot(r) + self.Mainloop={} + self.Tasks={} + self.Tasks2={} + self.Garbage={} + self.Children={} + self.Paused={} + self.MasterId=0 + self.Active=true + self.Id=-1 + if r then + for i,v in pairs(_G) do + if type(i)=="table" then + if i.Parent and i.Id and i.Act then + i={} + end + end + end + end +end +function multi:getChildren() + return self.Mainloop +end +--Processor +function multi:Do_Order() + for _D=#self.Mainloop,1,-1 do + if self.Mainloop[_D]~=nil then + self.Mainloop[_D].Id=_D + self.Mainloop[_D]:Act() + end + if self.Mainloop[_D].rem then + table.remove(self.Mainloop,_D) + end + end + if self.Rest>0 then + os.sleep(self.Rest) + end +end +function multi:benchMark(sec) + local temp=self:newLoop(function(t,self) + if os.clock()-self.init>self.sec then + print(self.c.." steps in "..self.sec.." second(s)") + self.tt(self.sec) + self:Destroy() + else + self.c=self.c+1 + end + end) + function temp:OnBench(func) + self.tt=func + end + self.tt=function() end + temp.sec=sec + temp.init=os.clock() + temp.c=0 + return temp +end +function multi:newInterface() + if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end + local c = {} + setmetatable(c, self) + c.Parent=self + c.Active=true + c.func={} + c.Id=0 + c.Type="int" + c.Mainloop={} + c.Tasks={} + c.Tasks2={} + c.Garbage={} + c.Children={} + c.Paused={} + c.MasterId=0 + c.Active=true + c.Id=-1 + c.Rest=0 + function c:Start() + if self.l then + self.l:Resume() + else + self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) + end + end + function c:Stop() + if self.l then + self.l:Pause() + end + end + function c:Remove() + self:Destroy() + self.l:Destroy() + end + return c +end +--Helpers +function multi:FreeMainEvent() + self.func={} +end +function multi:isPaused() + return not(self.Active) +end +function multi:Pause(n) + if self.Type=="int" or self.Type=="MainInt" then + self.Active=false + if not(n) then + local c=self:getChildren() + for i=1,#c do + c[i]:Pause() + end + else + self:hold(n) + end + else + if not(n) then + self.Active=false + if self.Parent.Mainloop[self.Id]~=nil then + table.remove(self.Parent.Mainloop,self.Id) + table.insert(self.Parent.Paused,self) + self.Id=#self.Parent.Paused + end + else + self:hold(n) + end + end +end +function multi:Resume() + if self.Type=="int" or self.Type=="MainInt" then + self.Active=true + local c=self:getChildren() + for i=1,#c do + c[i]:Resume() + end + else + if self:isPaused() then + self.Active=true + for i=1,#self.Parent.Paused do + if self.Parent.Paused[i]==self then + table.remove(self.Parent.Paused,i) + return + end + end + table.insert(self.Parent.Mainloop,self) + end + end +end +function multi:Destroy() + if self.Type=="int" or self.Type=="MainInt" then + local c=self:getChildren() + for i=1,#c do + c[i]:Destroy() + end + else + self.rem=true + end +end +function multi:hold(task) + self:Pause() + if type(task)=="number" then + local alarm=self:newAlarm(task) + while alarm.Active==true do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + alarm:Destroy() + self:Resume() + elseif type(task)=="function" then + local env=self.Parent:newEvent(task) + env:OnEvent(function(envt) envt:Pause() envt:Stop() end) + while env.Active do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + env:Destroy() + self:Resume() + else + print("Error Data Type!!!") + end +end +function multi:oneTime(func,...) + if not(self.Type=="MainInt" or self.Type=="int") then + for _k=1,#self.Parent.Tasks2 do + if self.Parent.Tasks2[_k]==func then + return false + end + end + table.insert(self.Parent.Tasks2,func) + func(...) + return true + else + for _k=1,#self.Tasks2 do + if self.Tasks2[_k]==func then + return false + end + end + table.insert(self.Tasks2,func) + func(...) + return true + end +end +--Constructors +function multi:newEvent(task) + local c=self:newBase() + c.Type="Event" + c.Task=task or function() end + function c:Act() + if self.Task(self) and self.Active==true then + self:Pause() + for _E=1,#self.func do + self.func[_E](self) + end + end + end + function c:OnEvent(func) + table.insert(self.func,func) + end + return c +end +function multi:newAlarm(set) + local c=self:newBase() + c.Type="Alarm" + c.timer=os.clock() + c.set=set or 0 + function c:Act() + if self.Active==true then + if os.clock()-self.timer>=self.set then + self:Pause() + for i=1,#self.func do + self.func[i](self) + end + end + end + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnRing(func) + table.insert(self.func,func) + end + return c +end +function multi:newTask(func) + table.insert(self.Tasks,func) +end +function multi:newLoop(func) + local c=self:newBase() + c.Type="Loop" + if func then + c.func={func} + end + function c:Act() + if self.Active==true then + for i=1,#self.func do + self.func[i](os.clock()-self.Parent.Start,self) + end + end + end + function c:OnLoop(func) + table.insert(self.func,func) + end + return c +end +function multi:newStep(start,reset,count,skip) + local c=self:newBase() + think=1 + c.Type="Step" + c.pos=start or 1 + c.endAt=reset or math.huge + c.skip=skip or 0 + c.spos=0 + c.count=count or 1*think + c.funcE={} + c.start=start or 1 + if start~=nil and reset~=nil then + if start>reset then + think=-1 + end + end + function c:Act() + if self~=nil then + if self.spos==0 then + if self.Active==true then + for i=1,#self.func do + self.func[i](self.pos,self) + end + self.pos=self.pos+self.count + end + end + end + self.spos=self.spos+1 + if self.spos>=self.skip then + self.spos=0 + end + end + function c:OnStep(func) + table.insert(self.func,1,func) + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Update(start,reset,count,skip) + self.start=start or self.start + self.endAt=reset or self.endAt + self.skip=skip or self.skip + self.count=count or self.count + self:Resume() + end + c:OnStep(function(p,s) + if s.count>0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + elseif s.count<0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + end + end) + return c +end +function multi:newTStep(start,reset,count,set) + local c=self:newBase() + think=1 + c.Type="TStep" + c.start=start or 1 + local reset = reset or math.huge + c.endAt=reset + c.pos=start or 1 + c.skip=skip or 0 + c.count=count or 1*think + c.funcE={} + c.timer=os.clock() + c.set=set or 1 + function c:Update(start,reset,count,set) + self.start=start or self.start + self.pos=start + self.endAt=reset or self.endAt + self.set=set or self.set + self.count=count or self.count or 1 + self.timer=os.clock() + self:Resume() + end + function c:Act() + if self.Active then + if os.clock()-self.timer>=self.set then + self:Reset() + for i=1,#self.func do + self.func[i](self.pos,self) + end + if self.endAt==self.pos then + for fe=1,#self.funcE do + self.funcE[fe](self) + end + self.pos=self.start-1 + end + self.pos=self.pos+self.count + end + end + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnStep(func) + table.insert(self.func,func) + end + return c +end +function multi:newTrigger(func) + local c=self:newBase() + c.Type="Trigger" + c.trigfunc=func or function() end + function c:Fire(...) + self:trigfunc(self,...) + end + return c +end +--Managers +function multi:mainloop() + for i=1,#self.Tasks do + self.Tasks[i](self) + end + self.Start=os.clock() + while self.Active do + self:Do_Order() + end +end +function multi._tFunc(self,dt) + for i=1,#self.Tasks do + self.Tasks[i](self) + end + print("once!") + if dt then + self.pump=true + end + self.pumpvar=dt + self.Start=os.clock() +end +function multi:uManager(dt) + self:oneTime(self._tFunc,self,dt) + self:Do_Order() +end +multi.drawF={} +function multi:dManager() + for ii=1,#multi.drawF do + multi.drawF[ii]() + end +end +function multi:onDraw(func) + table.insert(self.drawF,func) +end +function multi:lManager() + if love.event then + love.event.pump() + for e,a,b,c,d in love.event.poll() do + if e == "quit" then + if not love.quit or not love.quit() then + if love.audio then + love.audio.stop() + end + return nil + end + end + love.handlers[e](a,b,c,d) + end + end + if love.timer then + love.timer.step() + dt = love.timer.getDelta() + end + if love.update then love.update(dt) end + multi:uManager(dt) + if love.window and love.graphics and love.window.isCreated() then + love.graphics.clear() + love.graphics.origin() + if love.draw then love.draw() end + multi.dManager() + love.graphics.setColor(255,255,255,255) + if multi.draw then multi.draw() end + love.graphics.present() + end +end +Thread={} +Thread.Name="Thread 2" +Thread.ChannelThread = love.thread.getChannel("Easy2") +Thread.ChannelMain = love.thread.getChannel("EasyMain") +Thread.Global = {} +function Thread:packTable(G) + function escapeStr(str) + local temp="" + for i=1,#str do + temp=temp.."\\"..string.byte(string.sub(str,i,i)) + end + return temp + end + function ToStr(t) + local dat="{" + for i,v in pairs(t) do + if type(i)=="number" then + i="["..i.."]=" + else + i=i.."=" + end + if type(v)=="string" then + dat=dat..i.."\""..v.."\"," + elseif type(v)=="number" then + dat=dat..i..v.."," + elseif type(v)=="boolean" then + dat=dat..i..tostring(v).."," + elseif type(v)=="table" and not(G==v) then + dat=dat..i..ToStr(v).."," + --elseif type(v)=="table" and G==v then + -- dat=dat..i.."assert(loadstring(\"return self\"))," + elseif type(v)=="function" then + dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," + end + end + return string.sub(dat,1,-2).."}" + end + return "return "..ToStr(G) +end +function Thread:Send(name,var) + arg3="2" + if type(var)=="table" then + var=Thread:packTable(var) + arg3="table" + end + self.ChannelMain:push({name,var,arg3}) +end +function Thread:UnPackChannel() + local c=self.ChannelThread:getCount() + for i=1,c do + local temp=self.ChannelThread:pop() + if temp[1] and temp[2] then + if temp[1]=="func" and type(temp[2])=="string" then + loadstring(temp[2])(temp[3]) + elseif temp[1]=="table" then + _G[temp[3]]=loadstring(temp[2])() + else + _G[temp[1]]=temp[2] + end + end + end + if #multi:getChildren()<2 then + os.sleep(.05) + end +end +function Thread:boost(func,name) + self:Send(name,string.dump(func)) +end +function Thread.mainloop() + Thread:UnPackChannel() +end +Thread.MainThread=false +multi:newLoop():OnLoop(Thread.mainloop) +multi:mainloop() diff --git a/Libs/T3.lua b/Libs/T3.lua new file mode 100644 index 0000000..171eff0 --- /dev/null +++ b/Libs/T3.lua @@ -0,0 +1,596 @@ +require("love.timer") +require("love.system") +require("love.sound") +require("love.physics") +require("love.mouse") +require("love.math") +require("love.keyboard") +require("love.joystick") +require("love.image") +require("love.font") +require("love.filesystem") +require("love.event") +require("love.audio") +require("love.graphics") +require("love.window") +_defaultfont = love.graphics.getFont() +gui = {} +function gui.getTile(i,x,y,w,h)-- returns imagedata + if type(i)=="userdata" then + -- do nothing + else + error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") + end + local iw,ih=i:getDimensions() + local id,_id=i:getData(),love.image.newImageData(w,h) + for _x=x,w+x-1 do + for _y=y,h+y-1 do + _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) + end + end + return love.graphics.newImage(_id) +end +multi = {} +multi.Version="4.0.0" +multi.__index = multi +multi.Mainloop={} +multi.Tasks={} +multi.Tasks2={} +multi.Garbage={} +multi.Children={} +multi.Paused={} +multi.MasterId=0 +multi.Active=true +multi.Id=-1 +multi.Type="MainInt" +multi.Rest=0 +-- System +os.sleep=love.timer.sleep +function multi:newBase(ins) + if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end + local c = {} + if self.Type=="int" then + setmetatable(c, self.Parent) + else + setmetatable(c, self) + end + c.Active=true + c.func={} + c.Id=0 + c.Act=function() end + c.Parent=self + if ins then + table.insert(self.Mainloop,ins,c) + else + table.insert(self.Mainloop,c) + end + self.MasterId=self.MasterId+1 + return c +end +function multi:reboot(r) + self.Mainloop={} + self.Tasks={} + self.Tasks2={} + self.Garbage={} + self.Children={} + self.Paused={} + self.MasterId=0 + self.Active=true + self.Id=-1 + if r then + for i,v in pairs(_G) do + if type(i)=="table" then + if i.Parent and i.Id and i.Act then + i={} + end + end + end + end +end +function multi:getChildren() + return self.Mainloop +end +--Processor +function multi:Do_Order() + for _D=#self.Mainloop,1,-1 do + if self.Mainloop[_D]~=nil then + self.Mainloop[_D].Id=_D + self.Mainloop[_D]:Act() + end + if self.Mainloop[_D].rem then + table.remove(self.Mainloop,_D) + end + end + if self.Rest>0 then + os.sleep(self.Rest) + end +end +function multi:benchMark(sec) + local temp=self:newLoop(function(t,self) + if os.clock()-self.init>self.sec then + print(self.c.." steps in "..self.sec.." second(s)") + self.tt(self.sec) + self:Destroy() + else + self.c=self.c+1 + end + end) + function temp:OnBench(func) + self.tt=func + end + self.tt=function() end + temp.sec=sec + temp.init=os.clock() + temp.c=0 + return temp +end +function multi:newInterface() + if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end + local c = {} + setmetatable(c, self) + c.Parent=self + c.Active=true + c.func={} + c.Id=0 + c.Type="int" + c.Mainloop={} + c.Tasks={} + c.Tasks2={} + c.Garbage={} + c.Children={} + c.Paused={} + c.MasterId=0 + c.Active=true + c.Id=-1 + c.Rest=0 + function c:Start() + if self.l then + self.l:Resume() + else + self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) + end + end + function c:Stop() + if self.l then + self.l:Pause() + end + end + function c:Remove() + self:Destroy() + self.l:Destroy() + end + return c +end +--Helpers +function multi:FreeMainEvent() + self.func={} +end +function multi:isPaused() + return not(self.Active) +end +function multi:Pause(n) + if self.Type=="int" or self.Type=="MainInt" then + self.Active=false + if not(n) then + local c=self:getChildren() + for i=1,#c do + c[i]:Pause() + end + else + self:hold(n) + end + else + if not(n) then + self.Active=false + if self.Parent.Mainloop[self.Id]~=nil then + table.remove(self.Parent.Mainloop,self.Id) + table.insert(self.Parent.Paused,self) + self.Id=#self.Parent.Paused + end + else + self:hold(n) + end + end +end +function multi:Resume() + if self.Type=="int" or self.Type=="MainInt" then + self.Active=true + local c=self:getChildren() + for i=1,#c do + c[i]:Resume() + end + else + if self:isPaused() then + self.Active=true + for i=1,#self.Parent.Paused do + if self.Parent.Paused[i]==self then + table.remove(self.Parent.Paused,i) + return + end + end + table.insert(self.Parent.Mainloop,self) + end + end +end +function multi:Destroy() + if self.Type=="int" or self.Type=="MainInt" then + local c=self:getChildren() + for i=1,#c do + c[i]:Destroy() + end + else + self.rem=true + end +end +function multi:hold(task) + self:Pause() + if type(task)=="number" then + local alarm=self:newAlarm(task) + while alarm.Active==true do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + alarm:Destroy() + self:Resume() + elseif type(task)=="function" then + local env=self.Parent:newEvent(task) + env:OnEvent(function(envt) envt:Pause() envt:Stop() end) + while env.Active do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + env:Destroy() + self:Resume() + else + print("Error Data Type!!!") + end +end +function multi:oneTime(func,...) + if not(self.Type=="MainInt" or self.Type=="int") then + for _k=1,#self.Parent.Tasks2 do + if self.Parent.Tasks2[_k]==func then + return false + end + end + table.insert(self.Parent.Tasks2,func) + func(...) + return true + else + for _k=1,#self.Tasks2 do + if self.Tasks2[_k]==func then + return false + end + end + table.insert(self.Tasks2,func) + func(...) + return true + end +end +--Constructors +function multi:newEvent(task) + local c=self:newBase() + c.Type="Event" + c.Task=task or function() end + function c:Act() + if self.Task(self) and self.Active==true then + self:Pause() + for _E=1,#self.func do + self.func[_E](self) + end + end + end + function c:OnEvent(func) + table.insert(self.func,func) + end + return c +end +function multi:newAlarm(set) + local c=self:newBase() + c.Type="Alarm" + c.timer=os.clock() + c.set=set or 0 + function c:Act() + if self.Active==true then + if os.clock()-self.timer>=self.set then + self:Pause() + for i=1,#self.func do + self.func[i](self) + end + end + end + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnRing(func) + table.insert(self.func,func) + end + return c +end +function multi:newTask(func) + table.insert(self.Tasks,func) +end +function multi:newLoop(func) + local c=self:newBase() + c.Type="Loop" + if func then + c.func={func} + end + function c:Act() + if self.Active==true then + for i=1,#self.func do + self.func[i](os.clock()-self.Parent.Start,self) + end + end + end + function c:OnLoop(func) + table.insert(self.func,func) + end + return c +end +function multi:newStep(start,reset,count,skip) + local c=self:newBase() + think=1 + c.Type="Step" + c.pos=start or 1 + c.endAt=reset or math.huge + c.skip=skip or 0 + c.spos=0 + c.count=count or 1*think + c.funcE={} + c.start=start or 1 + if start~=nil and reset~=nil then + if start>reset then + think=-1 + end + end + function c:Act() + if self~=nil then + if self.spos==0 then + if self.Active==true then + for i=1,#self.func do + self.func[i](self.pos,self) + end + self.pos=self.pos+self.count + end + end + end + self.spos=self.spos+1 + if self.spos>=self.skip then + self.spos=0 + end + end + function c:OnStep(func) + table.insert(self.func,1,func) + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Update(start,reset,count,skip) + self.start=start or self.start + self.endAt=reset or self.endAt + self.skip=skip or self.skip + self.count=count or self.count + self:Resume() + end + c:OnStep(function(p,s) + if s.count>0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + elseif s.count<0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + end + end) + return c +end +function multi:newTStep(start,reset,count,set) + local c=self:newBase() + think=1 + c.Type="TStep" + c.start=start or 1 + local reset = reset or math.huge + c.endAt=reset + c.pos=start or 1 + c.skip=skip or 0 + c.count=count or 1*think + c.funcE={} + c.timer=os.clock() + c.set=set or 1 + function c:Update(start,reset,count,set) + self.start=start or self.start + self.pos=start + self.endAt=reset or self.endAt + self.set=set or self.set + self.count=count or self.count or 1 + self.timer=os.clock() + self:Resume() + end + function c:Act() + if self.Active then + if os.clock()-self.timer>=self.set then + self:Reset() + for i=1,#self.func do + self.func[i](self.pos,self) + end + if self.endAt==self.pos then + for fe=1,#self.funcE do + self.funcE[fe](self) + end + self.pos=self.start-1 + end + self.pos=self.pos+self.count + end + end + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnStep(func) + table.insert(self.func,func) + end + return c +end +function multi:newTrigger(func) + local c=self:newBase() + c.Type="Trigger" + c.trigfunc=func or function() end + function c:Fire(...) + self:trigfunc(self,...) + end + return c +end +--Managers +function multi:mainloop() + for i=1,#self.Tasks do + self.Tasks[i](self) + end + self.Start=os.clock() + while self.Active do + self:Do_Order() + end +end +function multi._tFunc(self,dt) + for i=1,#self.Tasks do + self.Tasks[i](self) + end + print("once!") + if dt then + self.pump=true + end + self.pumpvar=dt + self.Start=os.clock() +end +function multi:uManager(dt) + self:oneTime(self._tFunc,self,dt) + self:Do_Order() +end +multi.drawF={} +function multi:dManager() + for ii=1,#multi.drawF do + multi.drawF[ii]() + end +end +function multi:onDraw(func) + table.insert(self.drawF,func) +end +function multi:lManager() + if love.event then + love.event.pump() + for e,a,b,c,d in love.event.poll() do + if e == "quit" then + if not love.quit or not love.quit() then + if love.audio then + love.audio.stop() + end + return nil + end + end + love.handlers[e](a,b,c,d) + end + end + if love.timer then + love.timer.step() + dt = love.timer.getDelta() + end + if love.update then love.update(dt) end + multi:uManager(dt) + if love.window and love.graphics and love.window.isCreated() then + love.graphics.clear() + love.graphics.origin() + if love.draw then love.draw() end + multi.dManager() + love.graphics.setColor(255,255,255,255) + if multi.draw then multi.draw() end + love.graphics.present() + end +end +Thread={} +Thread.Name="Thread 3" +Thread.ChannelThread = love.thread.getChannel("Easy3") +Thread.ChannelMain = love.thread.getChannel("EasyMain") +Thread.Global = {} +function Thread:packTable(G) + function escapeStr(str) + local temp="" + for i=1,#str do + temp=temp.."\\"..string.byte(string.sub(str,i,i)) + end + return temp + end + function ToStr(t) + local dat="{" + for i,v in pairs(t) do + if type(i)=="number" then + i="["..i.."]=" + else + i=i.."=" + end + if type(v)=="string" then + dat=dat..i.."\""..v.."\"," + elseif type(v)=="number" then + dat=dat..i..v.."," + elseif type(v)=="boolean" then + dat=dat..i..tostring(v).."," + elseif type(v)=="table" and not(G==v) then + dat=dat..i..ToStr(v).."," + --elseif type(v)=="table" and G==v then + -- dat=dat..i.."assert(loadstring(\"return self\"))," + elseif type(v)=="function" then + dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," + end + end + return string.sub(dat,1,-2).."}" + end + return "return "..ToStr(G) +end +function Thread:Send(name,var) + arg3="3" + if type(var)=="table" then + var=Thread:packTable(var) + arg3="table" + end + self.ChannelMain:push({name,var,arg3}) +end +function Thread:UnPackChannel() + local c=self.ChannelThread:getCount() + for i=1,c do + local temp=self.ChannelThread:pop() + if temp[1] and temp[2] then + if temp[1]=="func" and type(temp[2])=="string" then + loadstring(temp[2])(temp[3]) + else + _G[temp[1]]=temp[2] + end + end + end + if #multi:getChildren()<2 then + os.sleep(.05) + end +end +function Thread:boost(func,name) + self:Send(name,string.dump(func)) +end +function Thread.mainloop() + Thread:UnPackChannel() +end +Thread.MainThread=false +multi:newLoop():OnLoop(Thread.mainloop) +multi:mainloop() diff --git a/Libs/T4.lua b/Libs/T4.lua new file mode 100644 index 0000000..a8d3203 --- /dev/null +++ b/Libs/T4.lua @@ -0,0 +1,596 @@ +require("love.timer") +require("love.system") +require("love.sound") +require("love.physics") +require("love.mouse") +require("love.math") +require("love.keyboard") +require("love.joystick") +require("love.image") +require("love.font") +require("love.filesystem") +require("love.event") +require("love.audio") +require("love.graphics") +require("love.window") +_defaultfont = love.graphics.getFont() +gui = {} +function gui.getTile(i,x,y,w,h)-- returns imagedata + if type(i)=="userdata" then + -- do nothing + else + error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") + end + local iw,ih=i:getDimensions() + local id,_id=i:getData(),love.image.newImageData(w,h) + for _x=x,w+x-1 do + for _y=y,h+y-1 do + _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) + end + end + return love.graphics.newImage(_id) +end +multi = {} +multi.Version="4.0.0" +multi.__index = multi +multi.Mainloop={} +multi.Tasks={} +multi.Tasks2={} +multi.Garbage={} +multi.Children={} +multi.Paused={} +multi.MasterId=0 +multi.Active=true +multi.Id=-1 +multi.Type="MainInt" +multi.Rest=0 +-- System +os.sleep=love.timer.sleep +function multi:newBase(ins) + if not(self.Type=="MainInt" or self.Type=="int") then error("Can only create an object on multi or an interface obj") return false end + local c = {} + if self.Type=="int" then + setmetatable(c, self.Parent) + else + setmetatable(c, self) + end + c.Active=true + c.func={} + c.Id=0 + c.Act=function() end + c.Parent=self + if ins then + table.insert(self.Mainloop,ins,c) + else + table.insert(self.Mainloop,c) + end + self.MasterId=self.MasterId+1 + return c +end +function multi:reboot(r) + self.Mainloop={} + self.Tasks={} + self.Tasks2={} + self.Garbage={} + self.Children={} + self.Paused={} + self.MasterId=0 + self.Active=true + self.Id=-1 + if r then + for i,v in pairs(_G) do + if type(i)=="table" then + if i.Parent and i.Id and i.Act then + i={} + end + end + end + end +end +function multi:getChildren() + return self.Mainloop +end +--Processor +function multi:Do_Order() + for _D=#self.Mainloop,1,-1 do + if self.Mainloop[_D]~=nil then + self.Mainloop[_D].Id=_D + self.Mainloop[_D]:Act() + end + if self.Mainloop[_D].rem then + table.remove(self.Mainloop,_D) + end + end + if self.Rest>0 then + os.sleep(self.Rest) + end +end +function multi:benchMark(sec) + local temp=self:newLoop(function(t,self) + if os.clock()-self.init>self.sec then + print(self.c.." steps in "..self.sec.." second(s)") + self.tt(self.sec) + self:Destroy() + else + self.c=self.c+1 + end + end) + function temp:OnBench(func) + self.tt=func + end + self.tt=function() end + temp.sec=sec + temp.init=os.clock() + temp.c=0 + return temp +end +function multi:newInterface() + if not(self.Type=="MainInt") then error("Can only create an interface on the multi obj") return false end + local c = {} + setmetatable(c, self) + c.Parent=self + c.Active=true + c.func={} + c.Id=0 + c.Type="int" + c.Mainloop={} + c.Tasks={} + c.Tasks2={} + c.Garbage={} + c.Children={} + c.Paused={} + c.MasterId=0 + c.Active=true + c.Id=-1 + c.Rest=0 + function c:Start() + if self.l then + self.l:Resume() + else + self.l=self.Parent:newLoop(function(dt) c:uManager(dt) end) + end + end + function c:Stop() + if self.l then + self.l:Pause() + end + end + function c:Remove() + self:Destroy() + self.l:Destroy() + end + return c +end +--Helpers +function multi:FreeMainEvent() + self.func={} +end +function multi:isPaused() + return not(self.Active) +end +function multi:Pause(n) + if self.Type=="int" or self.Type=="MainInt" then + self.Active=false + if not(n) then + local c=self:getChildren() + for i=1,#c do + c[i]:Pause() + end + else + self:hold(n) + end + else + if not(n) then + self.Active=false + if self.Parent.Mainloop[self.Id]~=nil then + table.remove(self.Parent.Mainloop,self.Id) + table.insert(self.Parent.Paused,self) + self.Id=#self.Parent.Paused + end + else + self:hold(n) + end + end +end +function multi:Resume() + if self.Type=="int" or self.Type=="MainInt" then + self.Active=true + local c=self:getChildren() + for i=1,#c do + c[i]:Resume() + end + else + if self:isPaused() then + self.Active=true + for i=1,#self.Parent.Paused do + if self.Parent.Paused[i]==self then + table.remove(self.Parent.Paused,i) + return + end + end + table.insert(self.Parent.Mainloop,self) + end + end +end +function multi:Destroy() + if self.Type=="int" or self.Type=="MainInt" then + local c=self:getChildren() + for i=1,#c do + c[i]:Destroy() + end + else + self.rem=true + end +end +function multi:hold(task) + self:Pause() + if type(task)=="number" then + local alarm=self:newAlarm(task) + while alarm.Active==true do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + alarm:Destroy() + self:Resume() + elseif type(task)=="function" then + local env=self.Parent:newEvent(task) + env:OnEvent(function(envt) envt:Pause() envt:Stop() end) + while env.Active do + if love then + self.Parent.lManager() + else + self.Parent.Do_Order() + end + end + env:Destroy() + self:Resume() + else + print("Error Data Type!!!") + end +end +function multi:oneTime(func,...) + if not(self.Type=="MainInt" or self.Type=="int") then + for _k=1,#self.Parent.Tasks2 do + if self.Parent.Tasks2[_k]==func then + return false + end + end + table.insert(self.Parent.Tasks2,func) + func(...) + return true + else + for _k=1,#self.Tasks2 do + if self.Tasks2[_k]==func then + return false + end + end + table.insert(self.Tasks2,func) + func(...) + return true + end +end +--Constructors +function multi:newEvent(task) + local c=self:newBase() + c.Type="Event" + c.Task=task or function() end + function c:Act() + if self.Task(self) and self.Active==true then + self:Pause() + for _E=1,#self.func do + self.func[_E](self) + end + end + end + function c:OnEvent(func) + table.insert(self.func,func) + end + return c +end +function multi:newAlarm(set) + local c=self:newBase() + c.Type="Alarm" + c.timer=os.clock() + c.set=set or 0 + function c:Act() + if self.Active==true then + if os.clock()-self.timer>=self.set then + self:Pause() + for i=1,#self.func do + self.func[i](self) + end + end + end + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnRing(func) + table.insert(self.func,func) + end + return c +end +function multi:newTask(func) + table.insert(self.Tasks,func) +end +function multi:newLoop(func) + local c=self:newBase() + c.Type="Loop" + if func then + c.func={func} + end + function c:Act() + if self.Active==true then + for i=1,#self.func do + self.func[i](os.clock()-self.Parent.Start,self) + end + end + end + function c:OnLoop(func) + table.insert(self.func,func) + end + return c +end +function multi:newStep(start,reset,count,skip) + local c=self:newBase() + think=1 + c.Type="Step" + c.pos=start or 1 + c.endAt=reset or math.huge + c.skip=skip or 0 + c.spos=0 + c.count=count or 1*think + c.funcE={} + c.start=start or 1 + if start~=nil and reset~=nil then + if start>reset then + think=-1 + end + end + function c:Act() + if self~=nil then + if self.spos==0 then + if self.Active==true then + for i=1,#self.func do + self.func[i](self.pos,self) + end + self.pos=self.pos+self.count + end + end + end + self.spos=self.spos+1 + if self.spos>=self.skip then + self.spos=0 + end + end + function c:OnStep(func) + table.insert(self.func,1,func) + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Update(start,reset,count,skip) + self.start=start or self.start + self.endAt=reset or self.endAt + self.skip=skip or self.skip + self.count=count or self.count + self:Resume() + end + c:OnStep(function(p,s) + if s.count>0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + elseif s.count<0 and s.endAt==p then + for fe=1,#s.funcE do + s.funcE[fe](s) + end + s.pos=s.start-1 + end + end) + return c +end +function multi:newTStep(start,reset,count,set) + local c=self:newBase() + think=1 + c.Type="TStep" + c.start=start or 1 + local reset = reset or math.huge + c.endAt=reset + c.pos=start or 1 + c.skip=skip or 0 + c.count=count or 1*think + c.funcE={} + c.timer=os.clock() + c.set=set or 1 + function c:Update(start,reset,count,set) + self.start=start or self.start + self.pos=start + self.endAt=reset or self.endAt + self.set=set or self.set + self.count=count or self.count or 1 + self.timer=os.clock() + self:Resume() + end + function c:Act() + if self.Active then + if os.clock()-self.timer>=self.set then + self:Reset() + for i=1,#self.func do + self.func[i](self.pos,self) + end + if self.endAt==self.pos then + for fe=1,#self.funcE do + self.funcE[fe](self) + end + self.pos=self.start-1 + end + self.pos=self.pos+self.count + end + end + end + function c:OnEnd(func) + table.insert(self.funcE,func) + end + function c:Reset(n) + if n then self.set=n end + self.timer=os.clock() + self:Resume() + end + function c:OnStep(func) + table.insert(self.func,func) + end + return c +end +function multi:newTrigger(func) + local c=self:newBase() + c.Type="Trigger" + c.trigfunc=func or function() end + function c:Fire(...) + self:trigfunc(self,...) + end + return c +end +--Managers +function multi:mainloop() + for i=1,#self.Tasks do + self.Tasks[i](self) + end + self.Start=os.clock() + while self.Active do + self:Do_Order() + end +end +function multi._tFunc(self,dt) + for i=1,#self.Tasks do + self.Tasks[i](self) + end + print("once!") + if dt then + self.pump=true + end + self.pumpvar=dt + self.Start=os.clock() +end +function multi:uManager(dt) + self:oneTime(self._tFunc,self,dt) + self:Do_Order() +end +multi.drawF={} +function multi:dManager() + for ii=1,#multi.drawF do + multi.drawF[ii]() + end +end +function multi:onDraw(func) + table.insert(self.drawF,func) +end +function multi:lManager() + if love.event then + love.event.pump() + for e,a,b,c,d in love.event.poll() do + if e == "quit" then + if not love.quit or not love.quit() then + if love.audio then + love.audio.stop() + end + return nil + end + end + love.handlers[e](a,b,c,d) + end + end + if love.timer then + love.timer.step() + dt = love.timer.getDelta() + end + if love.update then love.update(dt) end + multi:uManager(dt) + if love.window and love.graphics and love.window.isCreated() then + love.graphics.clear() + love.graphics.origin() + if love.draw then love.draw() end + multi.dManager() + love.graphics.setColor(255,255,255,255) + if multi.draw then multi.draw() end + love.graphics.present() + end +end +Thread={} +Thread.Name="Thread 4" +Thread.ChannelThread = love.thread.getChannel("Easy4") +Thread.ChannelMain = love.thread.getChannel("EasyMain") +Thread.Global = {} +function Thread:packTable(G) + function escapeStr(str) + local temp="" + for i=1,#str do + temp=temp.."\\"..string.byte(string.sub(str,i,i)) + end + return temp + end + function ToStr(t) + local dat="{" + for i,v in pairs(t) do + if type(i)=="number" then + i="["..i.."]=" + else + i=i.."=" + end + if type(v)=="string" then + dat=dat..i.."\""..v.."\"," + elseif type(v)=="number" then + dat=dat..i..v.."," + elseif type(v)=="boolean" then + dat=dat..i..tostring(v).."," + elseif type(v)=="table" and not(G==v) then + dat=dat..i..ToStr(v).."," + --elseif type(v)=="table" and G==v then + -- dat=dat..i.."assert(loadstring(\"return self\"))," + elseif type(v)=="function" then + dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," + end + end + return string.sub(dat,1,-2).."}" + end + return "return "..ToStr(G) +end +function Thread:Send(name,var) + arg3="4" + if type(var)=="table" then + var=Thread:packTable(var) + arg3="table" + end + self.ChannelMain:push({name,var,arg3}) +end +function Thread:UnPackChannel() + local c=self.ChannelThread:getCount() + for i=1,c do + local temp=self.ChannelThread:pop() + if temp[1] and temp[2] then + if temp[1]=="func" and type(temp[2])=="string" then + loadstring(temp[2])(temp[3]) + else + _G[temp[1]]=temp[2] + end + end + end + if #multi:getChildren()<2 then + os.sleep(.05) + end +end +function Thread:boost(func,name) + self:Send(name,string.dump(func)) +end +function Thread.mainloop() + Thread:UnPackChannel() +end +Thread.MainThread=false +multi:newLoop():OnLoop(Thread.mainloop) +multi:mainloop() diff --git a/Libs/ThreadManager.lua b/Libs/ThreadManager.lua new file mode 100644 index 0000000..de6434d --- /dev/null +++ b/Libs/ThreadManager.lua @@ -0,0 +1,158 @@ +Thread={} +Thread.ChannelT1 = love.thread.getChannel("Easy1") +Thread.ChannelT2 = love.thread.getChannel("Easy2") +Thread.ChannelT3 = love.thread.getChannel("Easy3") +Thread.ChannelT4 = love.thread.getChannel("Easy4") +Thread.ChannelMain = love.thread.getChannel("EasyMain") +Thread.Name = "Thread Main" +Thread.n=0 +Thread.count=1 +function Thread:packTable(G) + function escapeStr(str) + local temp="" + for i=1,#str do + temp=temp.."\\"..string.byte(string.sub(str,i,i)) + end + return temp + end + function ToStr(t) + local dat="{" + for i,v in pairs(t) do + if type(i)=="number" then + i="["..i.."]=" + else + i=i.."=" + end + if type(v)=="string" then + dat=dat..i.."\""..v.."\"," + elseif type(v)=="number" then + dat=dat..i..v.."," + elseif type(v)=="boolean" then + dat=dat..i..tostring(v).."," + elseif type(v)=="table" and not(G==v) then + dat=dat..i..bin.ToStr(v).."," + --elseif type(v)=="table" and G==v then + -- dat=dat..i.."assert(loadstring(\"return self\"))," + elseif type(v)=="function" then + dat=dat..i.."assert(loadstring(\""..escapeStr(string.dump(v)).."\"))," + end + end + return string.sub(dat,1,-2).."}" + end + return ToStr(G) +end +Thread.last={} +function Thread:GetStatus() + print(self.n.." Threads Exist!!!") + for i=1,self.n do + print("\tThread "..i.." Running: "..tostring(self["Thread"..i]:isRunning())) + if not(self["Thread"..i]:isRunning()) then + print("\t\t"..self["Thread"..i]:getError()) + end + end +end +function Thread:Start(n) + local x=love.system.getProcessorCount() + if x>1 then + x=x-1 + else + x=1 + end + n=n or x + if n<1 then + print("Must be atleast 1 thread running!!!") + return + end + if n>4 then + print("Must be no more than 4 threads running!!!") + return + end + for i=1,n do + self["Thread"..i]=love.thread.newThread("Libs/T"..i..".lua") + self["Thread"..i]:start() + end + Thread.n=n +end +function Thread:RestartBroken() + for i=1,self.n do + if self["Thread"..i]:isRunning()==false then + self["Thread"..i]:start() + end + Thread:Boost(Thread.last[1],Thread.last[2]) + end +end +function Thread:Send(name,var,arg3) + if self.n>0 then + if type(var)=="table" then + var=Thread:packTable(var) + arg3=name + name="table" + end + self["ChannelT"..((self.count-1)%self.n)+1]:push({name,var,arg3}) + self.count=self.count+1 + end +end +function Thread:SendAll(name,var,arg3) + if self.n>0 then + for i=1,self.n do + if type(var)=="table" then + var=Thread:packTable(var) + arg3=name + name="table" + end + self["ChannelT"..i]:push({name,var,arg3}) + end + end +end +function Thread:UnPackChannel() + local c=self.ChannelMain:getCount() + for i=1,c do + local temp=self.ChannelMain:pop() + if temp[3]=="table" then + _G[temp[1]]=assert(loadstring(temp[2]))() + else + if Thread.OnDataRecieved then + Thread.OnDataRecieved(temp[1],temp[2],temp[3]) + end + _G[temp[1]]=temp[2] + end + end +end +function Thread:Boost(func,name) + if Thread.last[1]==nil then + return + end + Thread.last={func,name} + name=name or "nil" + if self.n>0 then + self:Send("func",string.dump(func),name) + end +end +function Thread:SendLibs(func,name) + name=name or "nil" + if self.n>0 then + self:SendAll("func",string.dump(func),name) + end +end +function Thread.mainloop() + if Thread.n>0 then + Thread:UnPackChannel() + end +end +Thread.MainThread=true +local loop = multi:newLoop() +loop:OnLoop(Thread.mainloop) +OnThreadError=multi:newConnection() +function love.threaderror(thread, errorstr) + Thread:GetStatus() + Thread:RestartBroken() + Thread:GetStatus() + OnThreadError:Fire(thread,errorstr) +end +multi:newTask(function() + math.randomseed(math.floor(os.time()/2)) + for i=1,Thread.n do + Thread["ChannelT"..i]:push({"randseed",math.random(-1000000,1000000)}) + Thread["ChannelT"..i]:push({"func",string.dump(function() math.randomseed(randseed) end),"randomizing"}) + end +end) diff --git a/Libs/Utils.lua b/Libs/Utils.lua new file mode 100644 index 0000000..c80b4bc --- /dev/null +++ b/Libs/Utils.lua @@ -0,0 +1,797 @@ +-- os Additions +function os.getSystemBit() + if (os.getenv('PROCESSOR_ARCHITEW6432')=='AMD64' or os.getenv('PROCESSOR_ARCHITECTURE')=='AMD64') then + return 64 + else + return 32 + end +end +function os.sleep(n) + if not n then n=0 end + local t0 = os.clock() + while os.clock() - t0 <= n do end +end +function os.pause(msg) + if msg ~= nil then + print(msg) + end + io.read() +end +function os.batCmd(cmd) + io.mkFile('temp.bat',cmd) + local temp = os.execute([[temp.bat]]) + io.delFile('temp.bat') + return temp +end +function os._getOS() + if package.config:sub(1,1)=='\\' then + return 'windows' + else + return 'unix' + end +end +function os.getOS(t) + if not t then + return os._getOS() + end + if os._getOS()=='unix' then + fh,err = io.popen('uname -o 2>/dev/null','r') + if fh then + osname = fh:read() + end + if osname then return osname end + end + local winver='Unknown Version' + local a,b,c=os.capture('ver'):match('(%d+).(%d+).(%d+)') + local win=a..'.'..b..'.'..c + if type(t)=='string' then + win=t + end + if win=='4.00.950' then + winver='95' + elseif win=='4.00.1111' then + winver='95 OSR2' + elseif win=='4.00.1381' then + winver='NT 4.0' + elseif win=='4.10.1998' then + winver='98' + elseif win=='4.10.2222' then + winver='98 SE' + elseif win=='4.90.3000' then + winver='ME' + elseif win=='5.00.2195' then + winver='2000' + elseif win=='5.1.2600' then + winver='XP' + elseif win=='5.2.3790' then + winver='Server 2003' + elseif win=='6.0.6000' then + winver='Vista/Windows Server 2008' + elseif win=='6.0.6002' then + winver='Vista SP2' + elseif win=='6.1.7600' then + winver='7/Windows Server 2008 R2' + elseif win=='6.1.7601' then + winver='7 SP1/Windows Server 2008 R2 SP1' + elseif win=='6.2.9200' then + winver='8/Windows Server 2012' + elseif win=='6.3.9600' then + winver='8.1/Windows Server 2012' + elseif win=='6.4.9841' then + winver='10 Technical Preview 1' + elseif win=='6.4.9860' then + winver='10 Technical Preview 2' + elseif win=='6.4.9879' then + winver='10 Technical Preview 3' + elseif win=='10.0.9926' then + winver='10 Technical Preview 4' + end + return 'Windows '..winver +end +function os.getLuaArch() + return (#tostring({})-7)*4 +end +if os.getOS()=='windows' then + function os.sleep(n) + if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end + end +else + function os.sleep(n) + os.execute('sleep ' .. tonumber(n)) + end +end +function os.capture(cmd, raw) + local f = assert(io.popen(cmd, 'r')) + local s = assert(f:read('*a')) + f:close() + if raw then return s end + s = string.gsub(s, '^%s+', '') + s = string.gsub(s, '%s+$', '') + s = string.gsub(s, '[\n\r]+', ' ') + return s +end +function os.getCurrentUser() + return os.getenv('$USER') or os.getenv('USERNAME') +end +-- string Additions +function string.trim(s) + local from = s:match"^%s*()" + return from > #s and "" or s:match(".*%S", from) +end +function string.random(n) + local str = '' + strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} + for i=1,n do + h = math.random(1,#strings) + str = str..''..strings[h] + end + return str +end +function string.linesToTable(s) + local t = {} + local i = 0 + while true do + i = string.find(s, '\n', i+1) + if i == nil then return t end + table.insert(t, i) + end +end +function string.lines(str) + local t = {} + local function helper(line) table.insert(t, line) return '' end + helper((str:gsub('(.-)\r?\n', helper))) + return t +end +function string.split(str, pat) + local t = {} -- NOTE: use {n = 0} in Lua-5.0 + local fpat = '(.-)' .. pat + local last_end = 1 + local s, e, cap = str:find(fpat, 1) + while s do + if s ~= 1 or cap ~= '' then + table.insert(t,cap) + end + last_end = e+1 + s, e, cap = str:find(fpat, last_end) + end + if last_end <= #str then + cap = str:sub(last_end) + table.insert(t, cap) + end + return t +end +function string.shuffle(inputStr) + math.randomseed(os.time()); + local outputStr = ''; + local strLength = string.len(inputStr); + while (strLength ~=0) do + local pos = math.random(strLength); + outputStr = outputStr..string.sub(inputStr,pos,pos); + inputStr = inputStr:sub(1, pos-1) .. inputStr:sub(pos+1); + strLength = string.len(inputStr); + end + return outputStr; +end +function string.genKeys(chars,a,f,s,GG) + if GG then + chars=string.rep(chars,a) + end + if s then + chars=string.shuffle(chars) + end + b=#chars + if a==0 then return end + local taken = {} local slots = {} + for i=1,a do slots[i]=0 end + for i=1,b do taken[i]=false end + local index = 1 + local tab={} + for i=1,#chars do + table.insert(tab,chars:sub(i,i)) + end + while index > 0 do repeat + repeat slots[index] = slots[index] + 1 + until slots[index] > b or not taken[slots[index]] + if slots[index] > b then + slots[index] = 0 + index = index - 1 + if index > 0 then + taken[slots[index]] = false + end + break + else + taken[slots[index]] = true + end + if index == a then + local tt={} + for i=1,a do + table.insert(tt,tab[slots[i]]) + end + f(table.concat(tt)) + taken[slots[index]] = false + break + end + index = index + 1 + until true end +end +-- io Additions +function io.getInput(msg) + if msg ~= nil then + io.write(msg) + end + return io.read() +end +function io.scanDir(directory) + directory=directory or io.getDir() + local i, t, popen = 0, {}, io.popen + if os.getOS()=='unix' then + for filename in popen('ls -a \''..directory..'\''):lines() do + i = i + 1 + t[i] = filename + end + else + for filename in popen('dir \''..directory..'\' /b'):lines() do + i = i + 1 + t[i] = filename + end + end + return t +end +function io.buildFromTree(tbl, indent,folder) + if not indent then indent = 0 end + if not folder then folder = '' end + for k, v in pairs(tbl) do + formatting = string.rep(' ', indent) .. k .. ':' + if type(v) == 'table' then + if not(io.dirExists(folder..string.sub(formatting,1,-2))) then + io.mkDir(folder..string.sub(formatting,1,-2)) + end + io.buildFromTree(v,0,folder..string.sub(formatting,1,-2)..'\\') + else + a=string.find(tostring(v),':',1,true) + if a then + file=string.sub(tostring(v),1,a-1) + data=string.sub(tostring(v),a+1) + io.mkFile(folder..file,data,'wb') + else + io.mkFile(folder..v,'','wb') + end + end + end +end +function io.cpFile(path,topath) + if os.getOS()=='unix' then + os.execute('cp '..file1..' '..file2) + else + os.execute('Copy '..path..' '..topath) + end +end +function io.delDir(directoryname) + if os.getOS()=='unix' then + os.execute('rm -rf '..directoryname) + else + os.execute('rmdir '..directoryname..' /s /q') + end +end +function io.delFile(path) + os.remove(path) +end +function io.mkDir(dirname) + os.execute('mkdir "' .. dirname..'"') +end +function io.mkFile(filename,data,tp) + if not(tp) then tp='wb' end + if not(data) then data='' end + file = io.open(filename, tp) + if file==nil then return end + file:write(data) + file:close() +end +function io.movFile(path,topath) + io.cpFile(path,topath) + io.delFile(path) +end +function io.listFiles(dir) + if not(dir) then dir='' end + local f = io.popen('dir \''..dir..'\'') + if f then + return f:read('*a') + else + print('failed to read') + end +end +function io.getDir(dir) + if not dir then return io.getWorkingDir() end + if os.getOS()=='unix' then + return os.capture('cd '..dir..' ; cd') + else + return os.capture('cd '..dir..' & cd') + end +end +function io.getWorkingDir() + return io.popen'cd':read'*l' +end +function io.fileExists(path) + g=io.open(path or '','r') + if path =='' then + p='empty path' + return nil + end + if g~=nil and true or false then + p=(g~=nil and true or false) + end + if g~=nil then + io.close(g) + else + return false + end + return p +end +function io.fileCheck(file_name) + if not file_name then print('No path inputed') return false end + local file_found=io.open(file_name, 'r') + if file_found==nil then + file_found=false + else + file_found=true + end + return file_found +end +function io.dirExists(strFolderName) + strFolderName = strFolderName or io.getDir() + local fileHandle, strError = io.open(strFolderName..'\\*.*','r') + if fileHandle ~= nil then + io.close(fileHandle) + return true + else + if string.match(strError,'No such file or directory') then + return false + else + return true + end + end +end +function io.getAllItems(dir) + local t=os.capture("cd \""..dir.."\" & dir /a-d | find",true):lines() + return t +end +function io.listItems(dir) + if io.dirExists(dir) then + temp=io.listFiles(dir) -- current directory if blank + if io.getDir(dir)=='C:\\\n' then + a,b=string.find(temp,'C:\\',1,true) + a=a+2 + else + a,b=string.find(temp,'..',1,true) + end + temp=string.sub(temp,a+2) + list=string.linesToTable(temp) + temp=string.sub(temp,1,list[#list-2]) + slist=string.lines(temp) + table.remove(slist,1) + table.remove(slist,#slist) + temp={} + temp2={} + for i=1,#slist do + table.insert(temp,string.sub(slist[i],40,-1)) + end + return temp + else + return nil + end +end +function io.getDirectories(dir,l) + if dir then + dir=dir..'\\' + else + dir='' + end + local temp2=io.scanDir(dir) + for i=#temp2,1,-1 do + if io.fileExists(dir..temp2[i]) then + table.remove(temp2,i) + elseif l then + temp2[i]=dir..temp2[i] + end + end + return temp2 +end +function io.getFiles(dir,l) + if dir then + dir=dir..'\\' + else + dir='' + end + local temp2=io.scanDir(dir) + for i=#temp2,1,-1 do + if io.dirExists(dir..temp2[i]) then + table.remove(temp2,i) + elseif l then + temp2[i]=dir..temp2[i] + end + end + return temp2 +end +function io.getFullName(name) + local temp=name or arg[0] + if string.find(temp,'\\',1,true) or string.find(temp,'/',1,true) then + temp=string.reverse(temp) + a,b=string.find(temp,'\\',1,true) + if not(a) or not(b) then + a,b=string.find(temp,'/',1,true) + end + return string.reverse(string.sub(temp,1,b-1)) + end + return temp +end +function io.getName(file) + local name=io.getFullName(file) + name=string.reverse(name) + a,b=string.find(name,'.',1,true) + name=string.sub(name,a+1,-1) + return string.reverse(name) +end +function io.readFile(file) + local f = io.open(file, 'rb') + local content = f:read('*all') + f:close() + return content +end +function io.getExtension(file) + local file=io.getFullName(file) + file=string.reverse(file) + local a,b=string.find(file,'.',0,true) + local temp=string.sub(file,1,b) + return string.reverse(temp) +end +function io.pathToTable(path) + local p=io.splitPath(path) + local temp={} + temp[p[1]]={} + local last=temp[p[1]] + for i=2,#p do + snd=last + last[p[i]]={} + last=last[p[i]] + end + return temp,last,snd +end +function io.splitPath(str) + return string.split(str,'[\\/]+') +end + +function io.parseDir(dir,t) + io.tempFiles={} + function _p(dir) + local dirs=io.getDirectories(dir,true) + local files=io.getFiles(dir,true) + for i=1,#files do + p,l,s=io.pathToTable(files[i]) + if t then + s[io.getFullName(files[i])]=io.readFile(files[i]) + else + s[io.getFullName(files[i])]=io.open(files[i],'r+') + end + table.merge(io.tempFiles,p) + end + for i=1,#dirs do + table.merge(io.tempFiles,io.pathToTable(dirs[i])) + _p(dirs[i],t) + end + end + _p(dir) + return io.tempFiles +end +function io.parsedir(dir,f) + io.tempFiles={} + function _p(dir,f) + local dirs=io.getDirectories(dir,true) + local files=io.getFiles(dir,true) + for i=1,#files do + if not f then + table.insert(io.tempFiles,files[i]) + else + f(files[i]) + end + end + for i=1,#dirs do + _p(dirs[i],f) + end + end + _p(dir,f) + return io.tempFiles +end +function io.driveReady(drive) + drive=drive:upper() + if not(drive:find(':',1,true)) then + drive=drive..':' + end + drives=io.getDrives() + for i=1,#drives do + if drives[i]==drive then + return true + end + end + return false +end +function io.getDrives() + if os.getOS()=='windows' then + local temp={} + local t1=os.capture('wmic logicaldisk where drivetype=2 get deviceid, volumename',true) + local t2=os.capture('wmic logicaldisk where drivetype=3 get deviceid, volumename',true) + for drive,d2 in t1:gmatch('(.:)%s-(%w+)') do + if #d2>1 then + table.insert(temp,drive) + end + end + for drive in t2:gmatch('(.:)') do + table.insert(temp,drive) + end + return temp + end + error('Command is windows only!') +end +-- table Additions +function table.dump(t,indent) + local names = {} + if not indent then indent = '' end + for n,g in pairs(t) do + table.insert(names,n) + end + table.sort(names) + for i,n in pairs(names) do + local v = t[n] + if type(v) == 'table' then + if(v==t) then + print(indent..tostring(n)..': <-') + else + print(indent..tostring(n)..':') + table.dump(v,indent..' ') + end + else + if type(v) == 'function' then + print(indent..tostring(n)..'()') + else + print(indent..tostring(n)..': '..tostring(v)) + end + end + end +end +function table.alphanumsort(o) + local function padnum(d) local dec, n = string.match(d, '(%.?)0*(.+)') + return #dec > 0 and ('%.12f'):format(d) or ('%s%03d%s'):format(dec, #n, n) + end + table.sort(o, function(a,b) return tostring(a):gsub('%.?%d+',padnum)..('%3d'):format(#b)< tostring(b):gsub('%.?%d+',padnum)..('%3d'):format(#a) end) + return o +end +function table.foreach(t,f) + for i,v in pairs(t) do + f(v) + end +end +function table.merge(t1, t2) + for k,v in pairs(t2) do + if type(v) == 'table' then + if type(t1[k] or false) == 'table' then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 +end +function table.print(tbl, indent) + if not indent then indent = 0 end + for k, v in pairs(tbl) do + formatting = string.rep(' ', indent) .. k .. ': ' + if type(v) == 'table' then + print(formatting) + table.print(v, indent+1) + else + print(formatting .. tostring(v)) + end + end +end +function table.merge(t1, t2) + for k,v in pairs(t2) do + if type(v) == 'table' then + if type(t1[k] or false) == 'table' then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 +end +function table.clear(t) + for k in pairs (t) do + t[k] = nil + end +end +function table.copy(t) + function deepcopy(orig) + local orig_type = type(orig) + local copy + if orig_type == 'table' then + copy = {} + for orig_key, orig_value in next, orig, nil do + copy[deepcopy(orig_key)] = deepcopy(orig_value) + end + setmetatable(copy, deepcopy(getmetatable(orig))) + else -- number, string, boolean, etc + copy = orig + end + return copy + end + return deepcopy(t) +end +function table.swap(tab,i1,i2) + tab[i1],tab[i2]=tab[i2],tab[i1] +end +function table.append(t1, ...) + t1,t2= t1 or {},{...} + for k,v in pairs(t2) do + t1[#t1+1]=t2[k] + end + return t1 +end +function table.compare(t1, t2,d) + if d then + return table.deepCompare(t1,t2) + end + --if #t1 ~= #t2 then return false end + if #t2>#t1 then + for i=1,#t2 do + if t1[i] ~= t2[i] then + return false,t2[i] + end + end + else + for i=1,#t1 do + if t1[i] ~= t2[i] then + return false,t2[i] + end + end + end + return true +end +function table.deepCompare(t1,t2) + if t1==t2 then return true end + if (type(t1)~='table') then return false end + local mt1 = getmetatable(t1) + local mt2 = getmetatable(t2) + if( not table.deepCompare(mt1,mt2) ) then return false end + for k1,v1 in pairs(t1) do + local v2 = t2[k1] + if( not table.deepCompare(v1,v2) ) then return false end + end + for k2,v2 in pairs(t2) do + local v1 = t1[k2] + if( not table.deepCompare(v1,v2) ) then return false end + end + return true +end +function table.has(t,_v) + for i,v in pairs(t) do + if v==_v then + return true + end + end + return false +end +function table.reverse(tab) + local size = #tab + local newTable = {} + for i,v in ipairs (tab) do + newTable[size-i] = v + end + for i=1,#newTable do + tab[i]=newTable[i] + end +end +-- Math Additions +local Y = function(g) local a = function(f) return f(f) end return a(function(f) return g(function(x) local c=f(f) return c(x) end) end) end +local F = function(f) return function(n)if n == 0 then return 1 else return n*f(n-1) end end end +math.factorial = Y(F) +math.fib={} +math.fib.fibL={} +setmetatable(math.fib,{__call=function(self,n) + if n<=2 then + return 1 + else + if self.fibL[n] then + return self.fibL[n] + else + local t=math.fib(n-1)+math.fib(n-2) + self.fibL[n]=t + return t + end + end +end}) +local floor,insert = math.floor, table.insert +function math.basen(n,b) + n = floor(n) + if not b or b == 10 then return tostring(n) end + local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + local t = {} + local sign = '' + if n < 0 then + sign = '-' + n = -n + end + repeat + local d = (n % b) + 1 + n = floor(n / b) + insert(t, 1, digits:sub(d,d)) + until n == 0 + return sign .. table.concat(t,'') +end +function math.convbase(n,b,tb) + return math.basen(tonumber(tostring(n),b),tb) +end +if BigNum then + function BigNum.mod(a,b) + return a-((a/b)*b) + end + local floor,insert = math.floor, table.insert + function math.basen(n,b) + n = BigNum.new(n) + if not b or b == 10 then return tostring(n) end + local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + local t = {} + local sign = '' + if n < BigNum.new(0) then + sign = '-' + n = -n + end + repeat + local d = BigNum.mod(n , b) + 1 + n = n/b + d=tonumber(tostring(d)) + insert(t, 1, digits:sub(d,d)) + until tonumber(tostring(n)) == 0 + return sign .. table.concat(t,'') + end + function math.to10(n,b) + local num=tostring(n) + local sum=BigNum.new() + local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' + for i=1,#num do + local v=digits:find(num:sub(i,i),1,true) + sum=sum+BigNum.new(tonumber(v)-1)*BigNum.pow(BigNum.new(b),BigNum.new(#num-i)) + end + return sum + end + function math.convbase(n,b,tb) + return math.basen(math.to10(n,b),tb) + end +end +function math.numfix(n,x) + local str=tostring(n) + if #str olleh +nil = binobj:flipbits() -- flips the binary bits +nil** = binobj:segment(a,b) -- gets a segment of the binobj data works just like string.sub(a,b) without str +nil* = binobj:insert(a,i) -- inserts i (string or number(converts into string)) in position a +nil* = binobj:parseN(n) -- removes ever (nth) byte of data +nil = binobj:getlength() -- gets length or size of binary data +nil* = binobj:shift(n) -- shift the binary data by n positive --> negitive <-- +nil* = binobj:delete(a,b) -- deletes part of a binobj data Usage: binobj:delete(#) deletes at pos # binobj:delete(#1,#2) deletes from #1 to #2 binobj:delete('string') deletes all instances of 'byte' as a string Use string.char(#) or '\#' to get byte as a string +nil* = binobj:encrypt(seed) -- encrypts data using a seed, seed may be left blank +nil* = binobj:decrypt(seed) -- decrypts data encrypted with encrypt(seed) +nil* = binobj:shuffle() -- Shuffles the data randomly Note: there is no way to get it back!!! If original is needed clone beforehand +nil** = binobj:mutate(a,i) -- changes position a's value to i +nil = binobj:merge(o,t) -- o is the binobj you are merging if t is true it merges the new data to the left of the binobj EX: b:merge(o,true) b='yo' o='data' output: b='datayo' b:merge(o) b='yo' o='data' output: b='yodata' +nil* = binobj:parseA(n,a,t) -- n is every byte where you add, a is the data you are adding, t is true or false true before false after +nil = binobj:getHEX(a,b) -- returns the HEX of the bytes between a,b inclusive +nil = binobj:cryptM() -- a mirrorable encryptor/decryptor +nil = binobj:addBlock(d,n) -- adds a block of data to a binobj s is size d is data e is a bool if true then encrypts string values. if data is larger than 'n' then data is lost. n is the size of bytes the data is Note: n is no longer needed but you must use getBlock(type) to get it back +nil = binobj:getBlock(t,n) -- gets block of code by type +nil = binobj:seek(n) -- used with getBlock EX below with all 3 +nil* = binobj:morph(a,b,d) -- changes data between point a and b, inclusive, to d +nil = binobj:fill(n,d) -- fills binobj with data 'd' for n +nil = binobj:fillrandom(n) -- fills binobj with random data for n +nil = binobj:shiftbits(n) -- shifts all bits by n amount +nil = binobj:shiftbit(n,i) -- shifts a bit ai index i by n +nil# = binobj:streamwrite(d,n) -- writes to the streamable binobj d data n position +nil# = binobj:open() -- opens the streamable binobj +nil# = binobj:close() -- closes the streamable binobj +nil = binobj:wipe() -- erases all data in the file +nil* = binobj:tackB(d) -- adds data to the beginning of a file +nil = binobj:tackE(d) -- adds data to the end of a file +nil = binobj:parse(n,f) -- loops through each byte calling function 'f' with the args(i,binobj,data at i) +nil = binobj:flipbit(i) -- flips the binary bit at position i +nil* = binobj:gsub() -- just like string:gsub(), but mutates self +nil = blockWriter:addNamedBlock(name,value) -- writes a named block to the file with name 'name' and the value 'value' + +Note: numbers are written in Big-endian use bin.endianflop(d) to filp to Little-endian + +Note: binobj:tonumber() returns big,little endian so if printing do: b,l=binobj:tonumber() print(l) print(b) + +nil = bitobj:add(i) -- adds i to the bitobj i can be a number (base 10) or a bitobj +nil = bitobj:sub(i) -- subs i to the bitobj i can be a number (base 10) or a bitobj +nil = bitobj:multi(i) -- multiplys i to the bitobj i can be a number (base 10) or a bitobj +nil = bitobj:div(i) -- divides i to the bitobj i can be a number (base 10) or a bitobj +nil = bitobj:flipbits() -- filps the bits 1 --> 0, 0 --> 1 +string = bitobj:getBin() -- returns 1's & 0's of the bitobj + +# stream objects only +* not compatible with stream files +** works but do not use with large files or it works to some degree +*** in stream objects all changes are made directly to the file, so there is no need to do tofile() +]] + +bin.Changelog=[[ +Version.Major.Minor +------------------------- +1.0.0 : initial release load/new/tofile/clone/closeto/compare/sub/reverse/flip/segment/insert/insert/parseN/getlength/shift +1.0.1 : update Delete/tonumber/getbyte/ +1.0.2 : update Changed how delete works. Added encrypt/decrypt/shuffle +1.0.3 : update Added bits class, Added in bin: tobit/mutate/parseA Added in bits: add/sub/multi/div/isover/tobyte/tonumber/flip +1.0.4 : update Changed tobyte() to tobytes()/flipbit() to flipbits() and it now returns a binobj not str Added bin:merge +1.0.5 : update Changed bin.new() now hex data can be inserted EX: bin.new('0xFFC353D') Added in bin: getHEX/cryptM/addBlock/getBlock/seek +1.0.6 : update Added bin.NumtoHEX/bin:getHEX/bin.HEXtoBin/bin.HEXtoStr/bin.tohex/bin.fromhex +1.0.7 : update Added bin:morph/bin.endianflop/bin:scan/bin.ToStr +1.0.8 : update Added bin:fill/bin:fillrandom +1.1.0 : update Added bin.packLLIB/bin.unpackLLIB +1.2.0 : update Updated llib files +1.3.0 : Update Changed bin.unpackLLIB and bin.load() Added: bin.fileExist +1.4.0 : Update Changed bin.unpackLLIB bin.packLLIB Added: bin:shiftbits(n) bin:shiftbit(n,i) + +Woot!!! Version 2 +2.0.0 HUGE UPDATE Added Streamable files!!! lua 5.1, 5.2 and 5.3 compatable!!! +#binobj is the same as binobj:getlength() but only works in 5.2 and 5.3, in 5.1 just use getlength() or getSize() for compatibility +Now you can work with gigabyte sized data without memory crashes(streamable files[WIP]). + +Stream Compatible methods: + sub(a,b) + getlength() + tofile(filename) + flipbits() + tonumber(a,b) + getbyte(n) + segment(a,b) + parse(n,f) + tobits(i) + reverse() + flipbit(i) + cryptM() + getBlock(t,n) + addBlock(d,n) + shiftbits(n) + shiftbit(n,i) + getHEX(a,b) + +Added functions in this version: + binobj:streamwrite(d,n) + binobj:open() + binobj:close() + binobj:tackB(d) + binobj:tackE(d) + binobj:parse(n,f) + binobj:flipbit(i) + bin.stream(file) + binobj:streamData(a,b) + bin.getVersion() + bin.escapeStr(str) + binobj:streamread(a,b) + binobj:canStreamWrite() + binobj:wipe() + +Woot!!! Version 3 +3.0.0 HUGE UPDATE!!! + Added: bin.newVFS() bin.loadVFS() bin.textToBinary(txt) bin.decodeBits(bindata) bitobj:getBin() + Updated: bin.addBlock() <-- Fixed error with added features to the bits.new() function that allow for new functions to work + Notice: The bin library now requires the utils library!!! Put utils.lua in the lua/ directory +3.1.0 + Added: bin.newTempFile(data) binobj:setEndOfFile(n) bin.randomName(n,ext) + Updated: bin:tackE() bin:fill() bin:fillrandom() are now stream compatible! + Notice: bin:setEndOfFile() only works on streamable files! +3.1.1 + Added: bin.trimNul(s) bin:gsub() +3.1.2 + Added: log(data,name,fmt) + In secret something is brewing... + +3.1.3 + Added: bin:getHash(n) +3.2.1 + Added: bin.encryptA(data,seed), bin.decryptA(data,seed), bin.encryptB(data,seed), bin.decryptB(data,seed), bin:flush() + Updated: bin:encrypt(seed) and bin:decrypt(seed) + Fixed: bin:shiftbit() not working right with streamable files +3.2.2 + Fixed: bits.new() -- minor mistake huge error +3.2.3 + General bug fixes + Changed how bin.ToStr(t) -- functions are no longer valid data types +3.3.0 + Added: + bin:getSize() -- same as bin:getlength() just makes more sense. bin:getlength() is still valid and always will be. + bin.newLink() -- creates a link to a file object... Its like opening a file without opening it... Lua can only open a maximum of 200 files so use links if you will be going beyond that or make sure to close your files + bin.getHash2(h,n) -- 'h' hash size 8bit,16bit,32bit,64bit, 128bit, 100000bit whatever. is a number 'n' is the segmentation size defualt is 1024 greater numbers result in faster hashes but eaiser to forge hashes +3.4.1:(7/22/2016) NOTE: I started to add dates so I can see my work flow + Added: + binobj:getData() -- returns bin object as a string + bin:newDataBuffer(s) + Fixed: binobj:tonumber(a,b) +4.0.0:(7/23/2016) + Added: + bin.bufferToBin(b) + bin.binToBuffer(b) + bin.getLuaVersion() + bin.newNamedBlock(indexSize) + bin.newStreamedNamedBlock(indexSize,path) + bin.loadNamedBlock(path) + bin.getIndexSize(tab) + bits.numToBytes(num,occ) +4.1.0:(11/2/2016) NOTE: I took quite a long break due to college lol + Added: + bin.namedBlockManager(name) + Allows for a new way to use NamedBlocks + Example usage: + test=bin.namedBlockManager() + test["name"]="Ryan" -- My name lol + test["age"]=21 -- my age lol + test:tofile("test.dat") + --Now lets load the data we created + test2=bin.namedBlockManager("test.dat") + print(test2["name"]) + print(test2["age"]) + Changed: + bin.newNamedBlock(indexSize) + Now allows for indexSize to be nil and dynamacally adds to the size of the index + Fixed: + bin.loadNamedBlock(name) + Issue with indexing + TODO: + Allow streamed files to have expanding indexes +]] +bin.data='' +bin.t='bin' +bin.__index = bin +bin.__tostring=function(self) return self.data end +bin.__len=function(self) return self:getlength() end +bits={} +bits.data='' +bits.t='bits' +bits.__index = bits +bits.__tostring=function(self) return self.data end +bits.__len=function(self) return (#self.data)/8 end +bin.lastBlockSize=0 +--[[---------------------------------------- +Links +------------------------------------------]] +function bin.newLink(path) + if not path then + error("Must include a path when using a link!") + end + local c={} + c.path=path + c.tempfile={} + local mt={ + __tostring=function(self) + if self:getlength()>2048 then + -- + end + end, + __len=function(self) + return self:getlength() + end + } + function c:getlength() + -- + end +end + + +--[[---------------------------------------- +utils +------------------------------------------]] +function cleanName(name) + name=name:gsub("\\","") + name=name:gsub("/","") + name=name:gsub(":","") + name=name:gsub("*","") + name=name:gsub("%?","") + name=name:gsub("\"","''") + name=name:gsub("<","") + name=name:gsub(">","") + name=name:gsub("|","") + return name +end +function math.numfix(n,x) + local str=tostring(n) + if #str/dev/null','r') + if fh then + osname = fh:read() + end + if osname then return osname end + end + local winver='Unknown Version' + local a,b,c=os.capture('ver'):match('(%d+).(%d+).(%d+)') + local win=a..'.'..b..'.'..c + if type(t)=='string' then + win=t + end + if win=='4.00.950' then + winver='95' + elseif win=='4.00.1111' then + winver='95 OSR2' + elseif win=='4.00.1381' then + winver='NT 4.0' + elseif win=='4.10.1998' then + winver='98' + elseif win=='4.10.2222' then + winver='98 SE' + elseif win=='4.90.3000' then + winver='ME' + elseif win=='5.00.2195' then + winver='2000' + elseif win=='5.1.2600' then + winver='XP' + elseif win=='5.2.3790' then + winver='Server 2003' + elseif win=='6.0.6000' then + winver='Vista/Windows Server 2008' + elseif win=='6.0.6002' then + winver='Vista SP2' + elseif win=='6.1.7600' then + winver='7/Windows Server 2008 R2' + elseif win=='6.1.7601' then + winver='7 SP1/Windows Server 2008 R2 SP1' + elseif win=='6.2.9200' then + winver='8/Windows Server 2012' + elseif win=='6.3.9600' then + winver='8.1/Windows Server 2012' + elseif win=='6.4.9841' then + winver='10 Technical Preview 1' + elseif win=='6.4.9860' then + winver='10 Technical Preview 2' + elseif win=='6.4.9879' then + winver='10 Technical Preview 3' + elseif win=='10.0.9926' then + winver='10 Technical Preview 4' + end + return 'Windows '..winver +end +function os.capture(cmd, raw) + local f = assert(io.popen(cmd, 'r')) + local s = assert(f:read('*a')) + f:close() + if raw then return s end + s = string.gsub(s, '^%s+', '') + s = string.gsub(s, '%s+$', '') + s = string.gsub(s, '[\n\r]+', ' ') + return s +end +function io.scanDir(directory) + directory=directory or io.getDir() + local i, t, popen = 0, {}, io.popen + if os.getOS()=='unix' then + for filename in popen('ls -a "'..directory..'"'):lines() do + i = i + 1 + t[i] = filename + end + else + for filename in popen('dir "'..directory..'" /b'):lines() do + i = i + 1 + t[i] = filename + end + end + return t +end +function io.getDir(dir) + if not dir then return io.getWorkingDir() end + if os.getOS()=='unix' then + return os.capture('cd '..dir..' ; cd') + else + return os.capture('cd '..dir..' & cd') + end +end +function string.split(str, pat) + local t = {} -- NOTE: use {n = 0} in Lua-5.0 + local fpat = '(.-)' .. pat + local last_end = 1 + local s, e, cap = str:find(fpat, 1) + while s do + if s ~= 1 or cap ~= '' then + table.insert(t,cap) + end + last_end = e+1 + s, e, cap = str:find(fpat, last_end) + end + if last_end <= #str then + cap = str:sub(last_end) + table.insert(t, cap) + end + return t +end +function io.fileExists(path) + g=io.open(path or '','r') + if path =='' then + p='empty path' + return nil + end + if g~=nil and true or false then + p=(g~=nil and true or false) + end + if g~=nil then + io.close(g) + else + return false + end + return p +end +function io.getDirectories(dir,l) + if dir then + dir=dir..'\\' + else + dir='' + end + local temp2=io.scanDir(dir) + for i=#temp2,1,-1 do + if io.fileExists(dir..temp2[i]) then + table.remove(temp2,i) + elseif l then + temp2[i]=dir..temp2[i] + end + end + return temp2 +end +function io.getFiles(dir,l) + if dir then + dir=dir..'\\' + else + dir='' + end + local temp2=io.scanDir(dir) + for i=#temp2,1,-1 do + if io.dirExists(dir..temp2[i]) then + table.remove(temp2,i) + elseif l then + temp2[i]=dir..temp2[i] + end + end + return temp2 +end +function io.readFile(file) + local f = io.open(file, 'rb') + local content = f:read('*all') + f:close() + return content +end +function table.print(tbl, indent) + if not indent then indent = 0 end + for k, v in pairs(tbl) do + formatting = string.rep(' ', indent) .. k .. ': ' + if type(v) == 'table' then + print(formatting) + table.print(v, indent+1) + else + print(formatting .. tostring(v)) + end + end +end +function io.dirExists(strFolderName) + strFolderName = strFolderName or io.getDir() + local fileHandle, strError = io.open(strFolderName..'\\*.*','r') + if fileHandle ~= nil then + io.close(fileHandle) + return true + else + if string.match(strError,'No such file or directory') then + return false + else + return true + end + end +end +function io.getFullName(name) + local temp=name or arg[0] + if string.find(temp,'\\',1,true) or string.find(temp,'/',1,true) then + temp=string.reverse(temp) + a,b=string.find(temp,'\\',1,true) + if not(a) or not(b) then + a,b=string.find(temp,'/',1,true) + end + return string.reverse(string.sub(temp,1,b-1)) + end + return temp +end +function table.merge(t1, t2) + for k,v in pairs(t2) do + if type(v) == 'table' then + if type(t1[k] or false) == 'table' then + table.merge(t1[k] or {}, t2[k] or {}) + else + t1[k] = v + end + else + t1[k] = v + end + end + return t1 +end +function io.splitPath(str) + return string.split(str,'[\\/]+') +end +function io.pathToTable(path) + local p=io.splitPath(path) + local temp={} + temp[p[1]]={} + local last=temp[p[1]] + for i=2,#p do + snd=last + last[p[i]]={} + last=last[p[i]] + end + return temp,last,snd +end +function io.parseDir(dir,t) + io.tempFiles={} + function _p(dir) + local dirs=io.getDirectories(dir,true) + local files=io.getFiles(dir,true) + for i=1,#files do + p,l,s=io.pathToTable(files[i]) + if t then + s[io.getFullName(files[i])]=io.readFile(files[i]) + else + s[io.getFullName(files[i])]=io.open(files[i],'r+') + end + table.merge(io.tempFiles,p) + end + for i=1,#dirs do + table.merge(io.tempFiles,io.pathToTable(dirs[i])) + _p(dirs[i],t) + end + end + _p(dir) + return io.tempFiles +end +function io.parsedir(dir,f) + io.tempFiles={} + function _p(dir,f) + local dirs=io.getDirectories(dir,true) + local files=io.getFiles(dir,true) + for i=1,#files do + if not f then + table.insert(io.tempFiles,files[i]) + else + f(files[i]) + end + end + for i=1,#dirs do + _p(dirs[i],f) + end + end + _p(dir,f) + return io.tempFiles +end +--[[---------------------------------------- +Random +Not all of this is mine +------------------------------------------]] +--[[------------------------------------ +RandomLua v0.3.1 +Pure Lua Pseudo-Random Numbers Generator +Under the MIT license. +copyright(c) 2011 linux-man +--]]------------------------------------ + +local math_floor = math.floor + +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], math_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(math_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], math_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, math_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, math_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 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 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 = math_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 + return a + (y % (b - a + 1)) + 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 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 +-- Little bind for the methods: My code starts +randomGen={} +randomGen.__index=randomGen +function randomGen:new(s) + local temp={} + setmetatable(temp,randomGen) + temp[1]=twister() + temp[2]=lcg() + temp[3]=mwc() + temp.pos=1 + for i=1,3 do + temp[i]:randomseed(s) + end + return temp +end +function randomGen:randomseed(s) + self.pos=1 + self[1]:randomseed(s) + self[2]:randomseed(s) + self[3]:randomseed(s) +end +function randomGen:randomInt(a,b) + local t=self[self.pos]:random(a,b) + self.pos=self.pos+1 + if self.pos>3 then + self.pos=1 + end + return t +end +function randomGen:newND(a,b,s) + if not(a) or not(b) then error('You must include a range!') end + local temp=randomGen:new(s) + temp.a=a + temp.b=b + temp.range=b-a+1 + temp.dups={no=0} + function temp:nextInt() + local t=self:randomInt(self.a,self.b) + if self.dups[t]==nil then + self.dups[t]=true + self.dups.no=self.dups.no+1 + else + return self:nextInt() + end + if self.dups.no==self.range then + function self:nextInt() + return 1,true + end + return t + else + return t + end + end + function temp:nextIInt() + return function() return self:nextInt() end + end + return temp +end +--[[---------------------------------------- +BIN +------------------------------------------]] +function bin:getSize() + return self:getlength() +end +function bin.getVersion() + return bin.Version[1]..'.'..bin.Version[2]..'.'..bin.Version[3] +end +function bin:gsub(...) + self.data=self.data:gsub(...) +end +-- +function bin:trim() + self.data=self.data:match'^()%s*$' and '' or self.data:match'^%s*(.*%S)' +end +function bin._trim(str) + return str:match'^()%s*$' and '' or str:match'^%s*(.*%S)' +end +function bin:fullTrim(empty) + local t=self:lines() + for i=#t,1,-1 do + t[i]=bin._trim(t[i]) + if empty then + if t[i]=="" then + table.remove(t,i) + end + end + end + self.data = table.concat(t,"\n") +end +function bin:lines() + local t = {} + local function helper(line) table.insert(t, line) return '' end + helper((self.data:gsub('(.-)\r?\n', helper))) + return t +end +function bin._lines(str) + local t = {} + local function helper(line) table.insert(t, line) return '' end + helper((str:gsub('(.-)\r?\n', helper))) + return t +end +-- +function bin:find(...) + return self.data:find(...) +end +function bin.fromhex(str) + print(str) + return (str:gsub('..', function (cc) + return string.char(tonumber(cc, 16)) + end)) +end +if table.unpack==nil then + table.unpack=unpack +end +function bin.tohex(str) + return (str:gsub('.', function (c) + return string.format('%02X', string.byte(c)) + end)) +end +function bin:streamData(a,b) + if type(a)=='table' then + a,b,t=table.unpack(a) + end + if type(a)=='number' and type(b)=='string' then + return bin.load(self.file,a,b),bin.load(self.file,a,b).data + else + error('Invalid args!!! Is do you have a valid stream handle or is this a streamable object?') + end +end +function bin.new(data,hex) + data=data or "" + data=tostring(data) + local c = {} + setmetatable(c, bin) + if string.sub(data,1,2)=='0x' and hex==true then + data=string.sub(data,3) + data=bin.fromhex(data) + end + c.data=data + c.t='bin' + c.Stream=false + return c +end +function bin.stream(file,l) + local c=bin.new() + if bin.fileExist(file) then + c.file=file + c.lock = l + c.workingfile=io.open(file,'rb+') + else + c.file=file + c.lock = l + c.workingfile=io.open(file,'w') + io.close(c.workingfile) + c.workingfile=io.open(file,'rb+') + end + c.Stream=true + return c +end +function bin:streamwrite(d,n) + if self:canStreamWrite() then + if n then + self.workingfile:seek('set',n) + else + self.workingfile:seek('set',self.workingfile:seek('end')) + end + self.workingfile:write(d) + end +end +function bin:streamread(a,b) + a=tonumber(a) + b=tostring(b) + return bin.load(self.file,a,b).data +end +function bin:close() + if self:canStreamWrite() then + self.workingfile:close() + end +end +function bin:flush() + if self:canStreamWrite() then + self.workingfile:flush() + else + self:tofile(self.filepath) + end +end +function bin:open() + if self:canStreamWrite() then + self.workingfile=io.open(self.file,'r+') + end +end +function bin:canStreamWrite() + return (self.Stream==true and self.lock==false) +end +function bin.load(file,s,r) + if not(s) or not(r) then + local f = io.open(file, 'rb') + local content = f:read('*a') + f:close() + return bin.new(content) + end + s=s or 0 + r=r or -1 + if type(r)=='number' then + r=r+s-1 + elseif type(r)=='string' then + r=tonumber(r) or -1 + end + local f = io.open(file, 'rb') + f:seek('set',s) + local content = f:read((r+1)-s) + f:close() + local temp=bin.new(content) + temp.filepath=file + return temp +end +function bin:tofile(filename) + if not(filename) or self.Stream then return nil end + io.mkFile(filename,self.data) +end +function bin.trimNul(s) + for i=1,#s do + if s:sub(i,i)=='\0' then + return s:sub(1,i-1) + end + end + return s +end +function bin:match(pat) + return self.data:match(pat) +end +function bin:gmatch(pat) + return self.data:gmatch(pat) +end +function bin:getHash(n) + if self:getlength()==0 then + return "NaN" + end + n=(n or 32)/2 + local rand = randomGen:newND(1,self:getlength(),self:getlength()) + local h,g={},0 + for i=1,n do + g=rand:nextInt() + table.insert(h,bin.tohex(self:sub(g,g))) + end + return table.concat(h,'') +end +function bin:newDataBuffer(s) + local c={} + local mt={ + __index=function(t,k,v) + if k<=t.maxBuffer then + if t.dataS[k] then + return string.byte(t.dataS[k]) + else + return "NOINDEX" + end + else + return + end + end, + __newindex=function(t,k,v) + t.dataS[k]=string.char(v) + end, + __tostring=function(t) + return t:getBuffer() + end + } + c.dataS={} + if s then + if type(s)=="number" then + c.maxBuffer=s + s=string.rep("\0",s) + else + c.maxBuffer=math.huge + end + for i=1,#s do + c.dataS[i]=s:sub(i,i) + end + else + c.maxBuffer=math.huge + end + function c:getBuffer(a,b) + if a and b then + return table.concat(self.dataS,""):sub(a,b) + else + return table.concat(self.dataS,"") + end + end + function c:getBufferTable() + return self.dataS + end + function c:getBufferSize() + if self.maxBuffer~=math.huge then + return self.maxBuffer + end + return #self:getBuffer() + end + function c:getlength() + return #self:getBuffer(a,b) + end + c.getSize=c.getlength + function c:fillBuffer(s,a) + for i=0,#s-1 do + if i+a<=self.maxBuffer then + c.dataS[i+a]=s:sub(i+1,i+1) + else + return "Buffer Overflow!" + end + end + return a,a+#s-1 + end + setmetatable(c,mt) + return c +end +function bin:getHash2(h,n) + n=n or 1024 + h=(h or 32) + local temp=bin.new() + local len=self:getSize() + local seg=math.ceil(len/n) + temp:fill("\0",h) + for i=1,seg do + local s=bin.new(self:sub(n*(i-1)+1,n*i)):getHash(h) + for i=1,h do + temp:shiftbit(string.byte(s:sub(i,i)),i) + end + end + return temp:getHEX() +end +function bin.encryptA(data,seed) + seed=seed or 1 + local d=bin.new(data) + local r=randomGen:newND(1,#d.data,seed) + for i=1,#d.data do + d:shiftbit(r:nextInt(),i) + end + return bin.tohex(d.data) +end +function bin.decryptA(data,seed) + seed=seed or 1 + local d=bin.new('0x'..data) + local r=randomGen:newND(1,#d.data,seed) + for i=1,#d.data do + d:shiftbit(-r:nextInt(),i) + end + return d.data +end +function bin.encryptB(data,seed) + seed=seed or 'abcdefghijklmnopqrstuvwxyz' + seed=tostring(seed) + local d=bin.new(data) + local r,mr=1,#seed + for i=1,#d.data do + d:shiftbit(string.byte(seed:sub(r,r)),i) + r=r+1 + if r>mr then + r=1 + end + end + return bin.tohex(d.data) +end +function bin.decryptB(data,seed) + seed=seed or 'abcdefghijklmnopqrstuvwxyz' + seed=tostring(seed) + local d=bin.new('0x'..data) + local r,mr=1,#seed + for i=1,#d.data do + d:shiftbit(-string.byte(seed:sub(r,r)),i) + r=r+1 + if r>mr then + r=1 + end + end + return d.data +end +function bin:encrypt(seed) + seed=seed or 'abcdefghijklmnopqrstuvwxyz' + seed=tostring(seed) + local r,mr=1,#seed + for i=1,self:getlength() do + self:shiftbit(string.byte(seed:sub(r,r)),i) + r=r+1 + if r>mr then + r=1 + end + end +end +function bin:decrypt(seed) + seed=seed or 'abcdefghijklmnopqrstuvwxyz' + seed=tostring(seed) + local r,mr=1,#seed + for i=1,self:getlength() do + self:shiftbit(-string.byte(seed:sub(r,r)),i) + r=r+1 + if r>mr then + r=1 + end + end +end +function bin.randomName(n,ext) + n=n or math.random(7,15) + if ext then + a,b=ext:find('.',1,true) + if a and b then + ext=ext:sub(2) + end + end + local str,h = '',0 + strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'} + for i=1,n do + h = math.random(1,#strings) + str = str..''..strings[h] + end + return str..'.'..(ext or 'tmp') +end +function bin.newTempFile(data) + data=data or '' + local name=bin.randomName() + bin.new():tofile(name) + local tempfile=bin.stream(name,false) + tempfile:streamwrite(data,0) + tempfile:setEndOfFile(#data) + return tempfile +end +function bin:wipe() + if self:canStreamWrite() then + self:close() + os.remove(self.file) + self:open() + else + self.data='' + end +end +function bin:setEndOfFile(n) + if self:canStreamWrite() then + local name=bin.randomName() + local tempfile=bin.stream(name,false) + tempfile:streamwrite(self:sub(0,n-1)) + self:close() + os.remove(self.file) + tempfile:close() + os.rename(name,self.file) + self:open() + tempfile=nil + else + self.data=self.data:sub(1,n) + end +end +function bin:reverse() + if self:canStreamWrite() then + local x,f,b=self:getlength(),0,0 + for i=0,math.floor((x-1)/2) do + self:streamwrite(self:sub(i+1,i+1),x-i-1) + self:streamwrite(self:sub(x-i,x-i),i) + end + elseif self.Stream==false then + self.data=string.reverse(self.data) + end +end +function bin:flipbits() + if self:canStreamWrite() then + for i=0,self:getlength()-1 do + self:streamwrite(string.char(255-string.byte(self:streamread(i,i))),i) + end + elseif self.Stream==false then + local temp={} + for i=1,#self.data do + table.insert(temp,string.char(255-string.byte(string.sub(self.data,i,i)))) + end + self.data=table.concat(temp,'') + end +end +function bin:flipbit(i) + if self:canStreamWrite() then + self:streamwrite(string.char(255-string.byte(self:streamread(i-1,i-1))),i-1) + elseif self.Stream==false then + self:mutate(string.char(255-string.byte(string.sub(self.data,i,i))),i) + end +end +function bin:segment(a,b) -- needs to be updated!!! + if self:canStreamWrite() then + --[[local pos=1 + for i=a,b do + self:streamwrite(self:sub(i,i),b-a-i) + end]] + local temp=self:sub(a,b) + self:close() + local f=io.open(self.file,'w') + f:write(temp) + io.close(f) + self:open() + elseif self.Stream==false then + self.data=string.sub(self.data,a,b) + end +end +function bin:insert(i,a) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + if type(i)=='number' then i=string.char(i) end + self.data=string.sub(self.data,1,a)..i..string.sub(self.data,a+1) + end +end +function bin:parseN(n) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + local temp={} + for i=1,#self.data do + if i%n==0 then + table.insert(temp,string.sub(self.data,i,i)) + end + end + self.data=table.concat(temp,'') + end +end +function bin:parse(n,f) + local f = f + local n=n or 1 + if not(f) then return end + for i=1,self:getlength() do + if i%n==0 then + f(i,self,self:sub(i,i)) + end + end +end +function bin.copy(file,tofile,s) + if not(s) then + bin.load(file):tofile(tofile) + else + rf=bin.stream(file) + wf=bin.stream(tofile,false) + for i=1,rf:getlength(),s do + wf:streamwrite(rf:sub(i,i-1+s)) + end + end +end +function bin:getlength() + if self.Stream then + if self.workingfile==nil then print("Error getting size of file!") return 0 end + local current = self.workingfile:seek() -- get current position + local size = self.workingfile:seek('end') -- get file size + self.workingfile:seek('set', current) -- restore position + return size + elseif self.Stream==false then + return #self.data + end +end +function bin:sub(a,b) + if self.Stream then + return bin.load(self.file,a-1,tostring(b-1)).data + elseif self.Stream==false then + return string.sub(self.data,a,b) + end +end +function bin:tackB(d) + if self:canStreamWrite() then + -- do something don't know if possible + elseif self.Stream==false then + self.data=d..self.data + end +end +function bin:tackE(d) + if type(d)=='table' then + if d:canStreamWrite() then + d=d:sub(1,d:getlength()) + else + d=d.data + end + return + end + if self:canStreamWrite() then + self:streamwrite(d) + elseif self.Stream==false then + self.data=self.data..d + end +end +function bin:clone(filename) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + return bin.new(self.data) + end +end +function bin.closeto(a,b,v) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + if type(a)~=type(b) then + error('Attempt to compare unlike types') + elseif type(a)=='number' and type(b)=='number' then + return math.abs(a-b)<=v + elseif type(a)=='table' and type(b)=='table' then + if a.data and b.data then + return (math.abs(string.byte(a.data)-string.byte(b.data)))<=v + else + error('Attempt to compare non-bin data') + end + elseif type(a)=='string' and type(b)=='string' then + return math.abs(string.byte(a)-string.byte(b))<=v + else + error('Attempt to compare non-bin data') + end + end +end +function bin:compare(_bin,t) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + t=t or 1 + local tab={} + local a,b=self:getlength(),_bin:getlength() + if not(a==b) then + print('Unequal Lengths!!! Equalizing...') + if a>b then + _bin.data=_bin.data..string.rep(string.char(0),a-b) + else + self.data=self.data..string.rep(string.char(0),b-a) + end + end + if t==1 then + for i=1,self:getlength() do + table.insert(tab,self:sub(i,i)==_bin:sub(i,i)) + end + else + for i=1,self:getlength() do + table.insert(tab,bin.closeto(self:sub(i,i),_bin:sub(i,i),t)) + end + end + local temp=0 + for i=1,#tab do + if tab[i]==true then + temp=temp+1 + end + end + return (temp/#tab)*100 + end +end +function bin:shift(n) + if self:canStreamWrite() then + local a,b,x,p='','',self:getlength(),0 + for i=1,x do + if i+n>x then + p=(i+n)-(x) + else + p=i+n + end + end + elseif self.Stream==false then + n=n or 0 + local s=#self.data + if n>0 then + self.data = string.sub(self.data,s-n+1)..string.sub(self.data,1,s-n) + elseif n<0 then + n=math.abs(n) + self.data = string.sub(self.data,n+1)..string.sub(self.data,1,n*1) + end + end +end +function bin:delete(a,b) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + if type(a)=='string' then + local tab={} + for i=1,self:getlength() do + if self:getbyte(i)~=string.byte(a) then + table.insert(tab,self:sub(i,i)) + end + end + self.data=table.concat(tab) + elseif a and not(b) then + self.data=self:sub(1,a-1)..self:sub(a+1) + elseif a and b then + self.data=self:sub(1,a-1)..self:sub(b+1) + else + self.data='' + end + end +end +function bin:tonumber(a,b) + local temp={} + if a then + temp.data=self:sub(a,b) + else + temp=self + end + local l,r=0,0 + local g=#temp.data + for i=1,g do + r=r+(256^(g-i))*string.byte(string.sub(temp.data,i,i)) + l=l+(256^(i-1))*string.byte(string.sub(temp.data,i,i)) + end + return r,l +end +function bin:getbyte(n) + return string.byte(self:sub(n,n)) +end +function bin:shuffle(s) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + s=tonumber(s) or 4546 + math.randomseed(s) + local t={} + for i=1,self:getlength() do + table.insert(t,self:sub(i,i)) + end + local n = #t + while n >= 2 do + local k = math.random(n) + t[n], t[k] = t[k], t[n] + n = n - 1 + end + self.data=table.concat(t) + end +end +function bin:tobits(i) + return bits.new(self:getbyte(i)) +end +function bin:mutate(a,i) + if self:canStreamWrite() then + self:streamwrite(a,i-1) + elseif self.Stream==false then + self:delete(i) + self:insert(a,i-1) + end +end +function bin:parseA(n,a,t) + if self:canStreamWrite() then + -- do something + elseif self.Stream==false then + local temp={} + for i=1,#self.data do + if i%n==0 then + if t then + table.insert(temp,a) + table.insert(temp,string.sub(self.data,i,i)) + else + table.insert(temp,string.sub(self.data,i,i)) + table.insert(temp,a) + end + else + table.insert(temp,string.sub(self.data,i,i)) + end + end + self.data=table.concat(temp,'') + end +end +function bin:merge(o,t) + if self:canStreamWrite() then + self:close() + self.workingfile=io.open(self.file,'a+') + self.workingfile:write(o.data) + self:close() + self:open() + elseif self.Stream==false then + if not(t) then + self.data=self.data..o.data + else + seld.data=o.data..self.data + end + end +end +function bin:cryptM() + self:flipbits() + self:reverse() +end +function bin.escapeStr(str) + local temp='' + for i=1,#str do + temp=temp..'\\'..string.byte(string.sub(str,i,i)) + end + return temp +end + +function bin.ToStr(val, name, skipnewlines, depth) + skipnewlines = skipnewlines or false + depth = depth or 0 + local tmp = string.rep(" ", depth) + if name then + if type(name) == "string" then + tmp = tmp .. "[\""..name.."\"] = " + else + tmp = tmp .. "["..(name or "").."] = " + end + end + if type(val) == "table" then + tmp = tmp .. "{" .. (not skipnewlines and " " or "") + for k, v in pairs(val) do + tmp = tmp .. bin.ToStr(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and " " or "") + end + tmp = tmp .. string.rep(" ", depth) .. "}" + elseif type(val) == "number" then + tmp = tmp .. tostring(val) + elseif type(val) == "string" then + tmp = tmp .. string.format("%q", val) + elseif type(val) == "boolean" then + tmp = tmp .. (val and "true" or "false") + else + tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\"" + end + return tmp +end +function bin:addBlock(d,n,e) + local temp={} + if type(d)=='table' then + if d.t=='bin' then + temp=d + elseif d.t=='bit' then + temp=bin.new(d:tobytes()) + else + self:addBlock('return '..bin.ToStr(d)) + return + end + elseif type(d)=='string' then + temp=bin.new(d) + if e or not(n) then + temp.data=temp.data..'_EOF' + temp:flipbits() + end + elseif type(d)=='function' then + temp=bin.new(string.dump(d)) + if e or not(n) then + temp.data=temp.data..'_EOF' + temp:flipbits() + end + elseif type(d)=='number' then + local nn=tostring(d) + if nn:find('.',1,true) then + temp=bin.new(nn) + temp.data=temp.data..'_EOF' + temp:flipbits() + else + temp=bits.new(d):tobytes() + if not n then + temp.data=temp.data..'_EOF' + temp:flipbits() + end + end + elseif type(d)=='boolean' then + n=1 + if d then + temp=bits.new(math.random(0,127)):tobytes() + else + temp=bits.new(math.random(128,255)):tobytes() + end + end + if n then + if temp:getlength()n then + temp:segment(1,n) + end + end + self:merge(temp) +end +function bin:getBlock(t,n,se) + if not(self.Block) then + self.Block=1 + end + local x=self.Block + local temp=bin.new() + if n then + temp=bin.new(self:sub(x,x+n-1)) + self.Block=self.Block+n + end + if se then + self.Block=self.Block+se + end + if t=='stringe' or t=='stre' or t=='se' and n then + temp:flipbits() + bin.lastBlockSize=#temp + return temp.data + elseif t=='string' or t=='str' or t=='s' and n then + bin.lastBlockSize=#temp + return temp.data + elseif t=='number' or t=='num' or t=='n' and n then + bin.lastBlockSize=n + return self:tonumber(x,x+n-1) + elseif t=='boolean' or t=='bool' or t=='b' then + self.Block=self.Block+1 + bin.lastBlockSize=1 + return self:tonumber(x,x)<127 + elseif t=='stringe' or t=='stre' or t=='se' or t=='string' or t=='str' or t=='s' then + local a,b=self:scan('_EOF',self.Block,true) + if not(b) then return nil end + local t=bin.new(self:sub(self.Block,b-4)) + bin.lastBlockSize=t:getlength() + t:flipbits() + self.Block=self.Block+t:getlength()+4 + return tostring(t) + elseif t=='table' or t=='tab' or t=='t' then + temp=self:getBlock('s') + bin.lastBlockSize=#temp + return assert(loadstring(temp))() + elseif t=='function' or t=='func' or t=='f' then + local temp=self:getBlock('s') + bin.lastBlockSize=#temp + return assert(loadstring(temp)) + elseif t=='number' or t=='num' or t=='n' then + local num=bin.new(self:getBlock('s')) + bin.lastBlockSize=#num + if tonumber(num.data) then + return tonumber(num.data) + end + local a,b=num:tonumber() + return a + elseif n then + -- C data + else + print('Invalid Args!!!') + end +end +function bin:seek(n) + self.Block=self.Block+n +end +function bin.NumtoHEX(num) + local hexstr = '0123456789ABCDEF' + local s = '' + while num > 0 do + local mod = math.fmod(num, 16) + s = string.sub(hexstr, mod+1, mod+1) .. s + num = math.floor(num / 16) + end + if s == '' then + s = '0' + end + return s +end +function bin:getHEX(a,b,e) + a=a or 1 + local temp = self:sub(a,b) + if e then temp=string.reverse(temp) end + return bin.tohex(temp) +end +function bin.HEXtoBin(hex,e) + if e then + return bin.new(string.reverse(bin.fromhex(hex))) + else + return bin.new(bin.fromhex(hex)) + end +end +function bin.HEXtoStr(hex,e) + if e then + return string.reverse(bin.fromhex(hex)) + else + return bin.fromhex(hex) + end +end +function bin:morph(a,b,d) + if self:canStreamWrite() then + local len=self:getlength() + local temp=bin.newTempFile(self:sub(b+1,self:getlength())) + self:streamwrite(d,a-1) + print(temp:sub(1,temp:getlength())) + self:setEndOfFile(len+(b-a)+#d) + self:streamwrite(temp:sub(1,temp:getlength()),a-1) + temp:remove() + elseif self.Stream==false then + if a and b then + self.data=self:sub(1,a-1)..d..self:sub(b+1) + else + print('error both arguments must be numbers and the third a string') + end + end +end +function bin.endianflop(data) + return string.reverse(data) +end +function bin:scan(s,n,f) + n=n or 1 + if self.Stream then + for i=n,self:getlength() do + if f then + local temp=bin.new(self:sub(i,i+#s-1)) + temp:flipbits() + if temp.data==s then + return i,i+#s-1 + end + else + if self:sub(i,i+#s-1)==s then + return i,i+#s-1 + end + end + end + elseif self.Stream==false then + if f then + s=bin.new(s) + s:flipbits() + s=s.data + end + n=n or 1 + local a,b=string.find(self.data,s,n,true) + return a,b + end +end +function bin:fill(s,n) + if self:canStreamWrite() then + self:streamwrite(string.rep(s,n),0) + self:setEndOfFile(n*#s) + elseif self.Stream==false then + self.data=string.rep(s,n) + end +end +function bin:fillrandom(n) + if self:canStreamWrite() then + local t={} + for i=1,n do + table.insert(t,string.char(math.random(0,255))) + end + self:streamwrite(table.concat(t),0) + self:setEndOfFile(n) + elseif self.Stream==false then + local t={} + for i=1,n do + table.insert(t,string.char(math.random(0,255))) + end + self.data=table.concat(t) + end +end +function bin.packLLIB(name,tab,ext) + local temp=bin.new() + temp:addBlock('³Šž³–') + temp:addBlock(bin.getVersion()) + temp:addBlock(tab) + for i=1,#tab do + temp:addBlock(tab[i]) + temp:addBlock(bin.load(tab[i]).data) + end + temp:addBlock('Done') + temp:tofile(name.. ('.'..ext or '.llib')) +end +function bin.unpackLLIB(name,exe,todir,over,ext) + local temp=bin.load(name..('.'..ext or '.llib')) + local name='' + Head=temp:getBlock('s') + ver=temp:getBlock('s') + infiles=temp:getBlock('t') + if ver~=bin.getVersion() then + print('Incompatable llib file') + return nil + end + local tab={} + while name~='Done' do + name,data=temp:getBlock('s'),bin.new(temp:getBlock('s')) + if string.find(name,'.lua',1,true) then + table.insert(tab,data.data) + else + if not(bin.fileExist((todir or '')..name) and not(over)) then + data:tofile((todir or '')..name) + end + end + end + os.remove((todir or '')..'Done') + if exe then + for i=1,#tab do + assert(loadstring(tab[i]))() + end + end + return infiles +end +function bin.fileExist(path) + g=io.open(path or '','r') + if path =='' then + p='empty path' + return nil + end + if g~=nil and true or false then + p=(g~=nil and true or false) + end + if g~=nil then + io.close(g) + else + return false + end + return p +end +function bin:shiftbits(n) + if self:canStreamWrite() then + n=n or 0 + if n>=0 then + for i=0,self:getlength() do + print(string.byte(self:sub(i,i))+n%256) + self:streamwrite(string.char(string.byte(self:sub(i,i))+n%256),i-1) + end + else + n=math.abs(n) + for i=0,self:getlength() do + self:streamwrite(string.char((string.byte(self:sub(i,i))+(256-n%256))%256),i-1) + end + end + elseif self.Stream==false then + n=n or 0 + if n>=0 then + for i=1,self:getlength() do + self:morph(i,i,string.char(string.byte(self:sub(i,i))+n%256)) + end + else + n=math.abs(n) + for i=1,self:getlength() do + self:morph(i,i,string.char((string.byte(self:sub(i,i))+(256-n%256))%256)) + end + end + end +end +function bin:shiftbit(n,i) + if self:canStreamWrite() then + i=i-1 + n=n or 0 + if n>=0 then + print((string.byte(self:sub(i,i))+n)%256,n) + self:streamwrite(string.char((string.byte(self:sub(i,i))+n)%256),i-1) + else + n=math.abs(n) + print((string.byte(self:sub(i,i))+(256-n))%256,n) + self:streamwrite(string.char((string.byte(self:sub(i,i))+(256-n%256))%256),i-1) + end + elseif self.Stream==false then + n=n or 0 + if n>=0 then + self:morph(i,i,string.char((string.byte(self:sub(i,i))+n)%256)) + else + n=math.abs(n) + self:morph(i,i,string.char((string.byte(self:sub(i,i))+(256-n%256))%256)) + end + end +end +function bin.decodeBits(par) + if type(par)=='table' then + if par.t=='bit' then + return bin.new(par:toSbytes()) + end + else + if par:find(' ') then + par=par:gsub(' ','') + end + local temp=bits.new() + temp.data=par + return bin.new((temp:toSbytes()):reverse()) + end +end +function bin.textToBinary(txt) + return bin.new(bits.new(txt:reverse()):getBin()) +end +function bin:getData() + return self.data +end +function bin.getLuaVersion() + if type(jit)=="table" then + if jit.version then + return "JIT",jit.version + end + end + return "PUC",_VERSION:match("(%d-)%.(%d+)") +end +function bin.binToBuffer(b) + return bin:newDataBuffer(b.data) +end +function bin.bufferToBin(b) + return bin.new(b:getBuffer()) +end +function bin.newNamedBlock(indexSize) + local c={} + c.data=bin.new() + c.lastLoc=0 + if indexSize then + indexSize=indexSize+4 + end + c.index=bin:newDataBuffer(indexSize) + c.conv={ + ["n"]="\1", + ["b"]="\2", + ["s"]="\3", + ["t"]="\4", + ["f"]="\5" + } + if indexSize then + c.index:fillBuffer(bits.numToBytes(indexSize,4),1) + c.lastLoc=4 + else + --c.index:fillBuffer(bits.numToBytes(2048,4),1) + end + function c:tofile(path) + bin.new(self:tostring()):tofile(path) + end + function c:tostring() + c.index:fillBuffer(bits.numToBytes(c.index:getSize()-4,4),1) + return self.index:getBuffer()..self.data.data + end + function c:setPointer(name,data,t) + t=c.conv[t] + data=t..data + local dSize=#data + local index=bin:newDataBuffer() + local nLen=#name + local test="" + index:fillBuffer(bits.numToBytes(self.data:getSize()+1,4),1) + index:fillBuffer(name,5) + self.data:tackE(data) + test=self.index:fillBuffer(index:getBuffer().."\31",self.lastLoc+1) + self.lastLoc=self.lastLoc+1+index:getBufferSize() + if test=="Buffer Overflow!" then + error("Increase Index size!") + end + end + function c:addNamedBlock(name,value) + local bSize=#name + local ftype={} + if type(value)=="number" then + local dat=bits.numToBytes(value,8) -- makes 64 bit version of lua compatable + self:setPointer(name,dat,"n") + elseif type(value)=="boolean" then + if value then + self:setPointer(name,"1","b") + else + self:setPointer(name,"0","b") + end + elseif type(value)=="string" then + self:setPointer(name,value,"s") + elseif type(value)=="table" then + local str=bin.ToStr(value) + self:setPointer(name,str,"t") + elseif type(value)=="function" then + local ver,verM,verm=bin.getLuaVersion() + local data=string.dump(value) + if ver=="JIT" then + ftype=bin:newDataBuffer(bits.numToBytes(0,4)) -- luajit version + else + ftype=bin:newDataBuffer(bits.numToBytes(tonumber(verM..verm),4)) -- lua version with MajorMinor data + end + local fdata=bin.new() + fdata:tackE(ftype:getBuffer()..data) + self:setPointer(name,fdata.data,"f") + elseif type(value)=="userdata" then + error("Userdata cannot be put into a block!") + end + end + if not indexSize then + c:addNamedBlock("__UNBOUNDEDINDEX__",true) + end + return c +end +function bin.newStreamedNamedBlock(indexSize,path,update) + local c={} + c.data=bin.stream(path,false) + c.lastLoc=4 + c.conv={ + ["n"]="\1", + ["b"]="\2", + ["s"]="\3", + ["t"]="\4", + ["f"]="\5" + } + if not update then + c.data:tackE(bin:newDataBuffer(indexSize+4 or 2052):getBuffer()) + if indexSize then + c.data:mutate(bits.numToBytes(indexSize,4),1) + else + c.data:mutate(bits.numToBytes(2048,4),1) + end + c.indexSize=indexSize+4 or 2052 + else + c.indexSize=c.data:tonumber(1,4) + local i=bin.new(c.data:sub(5,c.indexSize+4)).data + local last=0 + for b=#i,1,-1 do + if i:sub(b,b)=="\31" then + last=b+4 + break + end + end + c.lastLoc=last + end + function c:tofile(path) + --No need when using a streamed block + end + function c:tostring() + return self.index:getBuffer()..self.data.data + end + function c:setPointer(name,data,t) + t=c.conv[t] + data=t..data + local dSize=#data + local index=bin:newDataBuffer() + local nLen=#name + local test="" + index:fillBuffer(bits.numToBytes((self.data:getSize()+1)-self.indexSize,4),1) + index:fillBuffer(name,5) + local test=self.data:mutate(index:getBuffer().."\31",self.lastLoc+1) + self.lastLoc=self.lastLoc+1+index:getBufferSize() + self.data:tackE(data) + if test=="Buffer Overflow!" then + error("Increase Index size!") + end + end + function c:addNamedBlock(name,value) + local bSize=#name + local ftype={} + if type(value)=="number" then + local dat=bits.numToBytes(value,8) -- makes 64 bit version of lua compatable + self:setPointer(name,dat,"n") + elseif type(value)=="boolean" then + if value then + self:setPointer(name,"1","b") + else + self:setPointer(name,"0","b") + end + elseif type(value)=="string" then + self:setPointer(name,value,"s") + elseif type(value)=="table" then + local str=bin.ToStr(value) + self:setPointer(name,str,"t") + elseif type(value)=="function" then + local ver,verM,verm=bin.getLuaVersion() + local data=string.dump(value) + if ver=="JIT" then + ftype=bin:newDataBuffer(bits.numToBytes(0,4)) -- luajit version + else + ftype=bin:newDataBuffer(bits.numToBytes(tonumber(verM..verm),4)) -- lua version with MajorMinor data + end + local fdata=bin.new() + fdata:tackE(ftype:getBuffer()..data) + self:setPointer(name,fdata.data,"f") + elseif type(value)=="userdata" then + error("Userdata cannot be put into a block!") + end + end + function c:close() + self:addNamedBlock("",false) + self.data:close() + end + return c +end +function bin.loadNamedBlock(path) + local c={} + c.data=bin.stream(path) + c.iSize=c.data:tonumber(1,4) + c.index=bin.new(c.data:sub(5,c.iSize+4)) + c.sData=bin.new(c.data:sub(c.iSize+5,-1)) + function c:CheckRestOfIndex(name) + local a,b=self.index:scan(name) + local d=self.index:tonumber(b+2,b+5) + if d==0 or b+5>self.iSize then + return -1 + end + return d + end + function c:getIndexes() + local tab={} + ind=5 + while ind do + local a=self.index:find("\31",ind) + if not a then break end + local b=self.index:sub(ind,a-1) + table.insert(tab,b) + ind=a+5 + end + return tab + end + function c:getBlock(name) + local a,b=self.index:scan(name) + if not a then return "index not found" end + local dloc=self.index:tonumber(a-4,a-1) + local dindex=bin:newDataBuffer(self.sData:sub(dloc,dloc)) + if dindex[1]==0x01 then -- type number + return self.sData:tonumber(dloc+1,dloc+8) + elseif dindex[1]==0x02 then -- type bool + return ({[1]=true,[0]=false})[tonumber(self.sData:sub(dloc+1,dloc+1))] + elseif dindex[1]==0x03 then -- type string + local dend=self:CheckRestOfIndex(name)--self.index:tonumber(b+2,b+5) + return self.sData:sub(dloc+1,dend-1) + elseif dindex[1]==0x04 then -- type table + local dend=self.index:tonumber(b+2,b+5) + return loadstring("return "..self.sData:sub(dloc+1,dend-1))() + elseif dindex[1]==0x05 then -- type function + local dend=self:CheckRestOfIndex(name)--self.index:tonumber(b+2,b+5) + local _ver=self.sData:tonumber(dloc+1,dloc+4) + local ver,verM,verm=bin.getLuaVersion() + if tonumber(verM..verm)==_ver then + return loadstring(self.sData:sub(dloc+5,dend-1)) + else + return function() error("This lua function is not compatible with the current version of lua!") end + end + end + end + return c +end +function bin.namedBlockManager(name) + if type(name)=="string" then + local i={} + local data=bin.loadNamedBlock(name) + local mt={ + __index=function(t,k) + return data:getBlock(k) + end, + } + setmetatable(i,mt) + return i + else + local i={} + local data=bin.newNamedBlock(name) + local mt={ + __newindex=function(t,k,v) + data:addNamedBlock(k,v) + end, + __index=data + } + setmetatable(i,mt) + return i + end +end +function bin.getIndexSize(tab) + size=0 + for i=1,#tab do + size=size+#tab[i]+5 + end + return size+5 +end +--[[---------------------------------------- +VFS +------------------------------------------]] +local _require = require +function require(path,vfs) + if bin.fileExist(path..'.lvfs') then + local data = bin.loadVFS(path..'.lvfs') + if data:fileExist(vsf) then + loadstring(data:readFile(vfs))() + end + else + return _require(path) + end +end +function bin.loadVFS(path) + local vfs=bin.newVFS() + local temp=bin.stream(path,false) + local files=temp:getBlock("t") + local size=0 + for i=1,#files do + local p,len=files[i]:match("(.-)|(.+)") + len=tonumber(len) + size=size+bin.lastBlockSize + local dat=temp:sub(size+5,size+len+4) + bin.lastBlockSize=len + vfs:mkfile(p:gsub("%./",""),dat) + end + return vfs +end +function bin.copyDir(dir,todir) + local vfs=bin.newVFS(dir,true) + vfs:toFS(todir) + vfs=nil +end +function bin.newVFS(t,l) + l=l or true + if type(t)=='string' then + t=io.parseDir(t,l) + end + local c={} + c.FS= t or {} + function c:merge(vfs) + bin.newVFS(table.merge(self.FS,vfs.FS)) + end + function c:mirror(file) + self:mkfile(file,file) + end + function c:mkdir(path) + table.merge(self.FS,io.pathToTable(path)) + end + function c:scanDir(path) + path=path or '' + local tab={} + if path=='' then + for i,v in pairs(self.FS) do + tab[#tab+1]=i + end + return tab + end + spath=io.splitPath(path) + local last=self.FS + for i=1,#spath-1 do + last=last[spath[i]] + end + return last[spath[#spath]] + end + function c:getFiles(path) + if not self:dirExist(path) then return end + path=path or '' + local tab={} + if path=='' then + for i,v in pairs(self.FS) do + if self:fileExist(i) then + tab[#tab+1]=i + end + end + return tab + end + spath=io.splitPath(path) + local last=self.FS + for i=1,#spath-1 do + last=last[spath[i]] + end + local t=last[spath[#spath]] + for i,v in pairs(t) do + if self:fileExist(path..'/'..i) then + tab[#tab+1]=path..'/'..i + end + end + return tab + end + function c:getDirectories(path) + if not self:dirExist(path) then return end + path=path or '' + local tab={} + if path=='' then + for i,v in pairs(self.FS) do + if self:dirExist(i) then + tab[#tab+1]=i + end + end + return tab + end + spath=io.splitPath(path) + local last=self.FS + for i=1,#spath-1 do + last=last[spath[i]] + end + local t=last[spath[#spath]] + for i,v in pairs(t) do + if self:dirExist(path..'/'..i) then + tab[#tab+1]=path..'/'..i + end + end + return tab + end + function c:mkfile(path,data) + local name=io.getFullName(path) + local temp=path:reverse() + local a,b=temp:find('/') + if not a then + a,b=temp:find('\\') + end + if a then + temp=temp:sub(a+1):reverse() + path=temp + local t,l=io.pathToTable(path) + l[name]=data + table.merge(self.FS,t) + else + self.FS[name]=data + end + end + function c:remove(path) + if path=='' or path==nil then return end + spath=io.splitPath(path) + local last=self.FS + for i=1,#spath-1 do + last=last[spath[i]] + end + last[spath[#spath]]=nil + end + function c:readFile(path) + spath=io.splitPath(path) + local last=self.FS + for i=1,#spath do + last=last[spath[i]] + end + if type(last)=='userdata' then + last=last:read('*all') + end + return last + end + function c:copyFile(p1,p2) + self:mkfile(p2,self:readFile(p1)) + end + function c:moveFile(p1,p2) + self:copyFile(p1,p2) + self:remove(p1) + end + function c:fileExist(path) + return type(self:readFile(path))=='string' + end + function c:dirExist(path) + if path=='' or path==nil then return end + spath=io.splitPath(path) + local last=self.FS + for i=1,#spath-1 do + last=last[spath[i]] + end + if last[spath[#spath]]~=nil then + if type(last[spath[#spath]])=='table' then + return true + end + end + return false + end + function c:_getHierarchy() + local ord={} + local datlink=bin.new() + local function toStr(val, name, skipnewlines, depth, path) + skipnewlines = skipnewlines or false + path=path or "." + depth = depth or 0 + local tmp = string.rep(" ", depth) + if name then + if type(name) == "string" then + tmp = tmp .. "[\""..name.."\"] = " + else + tmp = tmp .. "["..(name or "").."] = " + end + end + if type(val) == "table" then + tmp = tmp .. "{" .. (not skipnewlines and "\n" or "") + for k, v in pairs(val) do + tmp = tmp .. toStr(v, k, skipnewlines, depth + 1,path.."/"..k) .. "," .. (not skipnewlines and "\n" or "") + end + tmp = tmp .. string.rep(" ", depth) .. "}" + elseif type(val) == "string" then + tmp = tmp .. #val + datlink:tackE(val) + ord[#ord+1]=path.."|"..#val + end + return tmp + end + return toStr(self.FS),ord,datlink + end + function c:getHierarchy() + local ord={} + local function toStr(val, name, skipnewlines, depth, path) + skipnewlines = skipnewlines or false + path=path or "." + depth = depth or 0 + local tmp = string.rep(" ", depth) + if name then + if type(name) == "string" then + tmp = tmp .. "[\""..name.."\"] = " + else + tmp = tmp .. "["..(name or "").."] = " + end + end + if type(val) == "table" then + tmp = tmp .. "{" .. (not skipnewlines and "\n" or "") + for k, v in pairs(val) do + tmp = tmp .. toStr(v, k, skipnewlines, depth + 1,path.."/"..k) .. "," .. (not skipnewlines and "\n" or "") + end + tmp = tmp .. string.rep(" ", depth) .. "}" + elseif type(val) == "string" then + tmp = tmp .. ";" + ord[#ord+1]=path.."|"..#val + end + return tmp + end + return toStr(self.FS),ord + end + function c:tofile(path) + local temp=bin.new() + local h,o,link=self:_getHierarchy() + temp:addBlock(o) + temp:merge(link) + temp:tofile(path) + end + function c:toFS(path) + if path then + if path:sub(-1,-1)~='\\' then + path=path..'\\' + elseif path:find('/') then + path=path:gsub('/','\\') + end + io.mkDir(path) + else + path='' + end + function build(tbl, indent, folder) + if not indent then indent = 0 end + if not folder then folder = '' end + for k, v in pairs(tbl) do + formatting = string.rep(' ', indent) .. k .. ':' + if type(v) == 'table' then + if v.t~=nil then + io.mkFile(folder..k,tostring(v),'wb') + else + if not(io.dirExists(path..folder..string.sub(formatting,1,-2))) then + io.mkDir(folder..string.sub(formatting,1,-2)) + end + build(v,0,folder..string.sub(formatting,1,-2)..'\\') + end + elseif type(v)=='string' then + io.mkFile(folder..k,v,'wb') + elseif type(v)=='userdata' then + io.mkFile(folder..k,v:read('*all'),'wb') + end + end + end + build(self.FS,0,path) + end + function c:print() + table.print(self.FS) + end + return c +end +--[[---------------------------------------- +BITS +------------------------------------------]] +function bits.new(n) + if type(n)=='string' then + local t=tonumber(n,2) + if not t then + t={} + for i=#n,1,-1 do + table.insert(t,bits:conv(string.byte(n,i))) + end + n=table.concat(t) + else + n=t + end + end + local temp={} + temp.t='bit' + setmetatable(temp, bits) + if type(n)~='string' then + local tab={} + while n>=1 do + table.insert(tab,n%2) + n=math.floor(n/2) + end + local str=string.reverse(table.concat(tab)) + if #str%8~=0 then + str=string.rep('0',8-#str%8)..str + end + temp.data=str + else + temp.data=n + end + setmetatable({__tostring=function(self) return self.data end},temp) + return temp +end +function bits.numToBytes(n,fit) + local num=bits.new(n):toSbytes() + num=bin.endianflop(num) + if fit then + if fit<#num then + print("Warning: attempting to store a number that takes up more space than allotted!") + return num:sub(1,fit) + elseif fit==#num then + return num + else + return string.rep("\0",fit-#num)..num + end + else + return num + end +end +function bits:conv(n) + local tab={} + while n>=1 do + table.insert(tab,n%2) + n=math.floor(n/2) + end + local str=string.reverse(table.concat(tab)) + if #str%8~=0 then + str=string.rep('0',8-#str%8)..str + end + return str +end +function bits:add(i) + if type(i)=='number' then + i=bits.new(i) + end + self.data=self:conv(tonumber(self.data,2)+tonumber(i.data,2)) +end +function bits:sub(i) + if type(i)=='number' then + i=bits.new(i) + end + self.data=self:conv(tonumber(self.data,2)-tonumber(i.data,2)) +end +function bits:multi(i) + if type(i)=='number' then + i=bits.new(i) + end + self.data=self:conv(tonumber(self.data,2)*tonumber(i.data,2)) +end +function bits:div(i) + if type(i)=='number' then + i=bits.new(i) + end + self.data=self:conv(tonumber(self.data,2)/tonumber(i.data,2)) +end +function bits:tonumber(s) + if type(s)=='string' then + return tonumber(self.data,2) + end + s=s or 1 + return tonumber(string.sub(self.data,(8*(s-1))+1,8*s),2) or error('Bounds!') +end +function bits:isover() + return #self.data>8 +end +function bits:flipbits() + tab={} + for i=1,#self.data do + if string.sub(self.data,i,i)=='1' then + table.insert(tab,'0') + else + table.insert(tab,'1') + end + end + self.data=table.concat(tab) +end +function bits:tobytes() + local tab={} + for i=self:getbytes(),1,-1 do + table.insert(tab,string.char(self:tonumber(i))) + end + return bin.new(table.concat(tab)) +end +function bits:toSbytes() + local tab={} + for i=self:getbytes(),1,-1 do + table.insert(tab,string.char(self:tonumber(i))) + end + return table.concat(tab) +end +function bits:getBin() + return self.data +end +function bits:getbytes() + return #self.data/8 +end diff --git a/Libs/lovebind.lua b/Libs/lovebind.lua new file mode 100644 index 0000000..eca6618 --- /dev/null +++ b/Libs/lovebind.lua @@ -0,0 +1,103 @@ +os.sleep=love.timer.sleep +function bin.load(file,s,r) + content, size = love.filesystem.read(file) + local temp=bin.new(content) + temp.filepath=file + return temp +end +function bin:tofile(filename) + if not(filename) or self.Stream then return nil end + love.filesystem.write(filename,self.data) +end +function bin.stream(file,l) + error("Sorry streaming is not available when using love2d :(, I am looking for a solution though :)") +end +function love.run() + if love.math then + love.math.setRandomSeed(os.time()) + end + if love.event then + love.event.pump() + end + if love.load then love.load(arg) end + if love.timer then love.timer.step() end + local dt = 0 + while true do + -- Process events. + if love.event then + love.event.pump() + for e,a,b,c,d in love.event.poll() do + if e == "quit" then + if not love.quit or not love.quit() then + if love.audio then + love.audio.stop() + end + return + end + end + love.handlers[e](a,b,c,d) + end + end + if love.timer then + love.timer.step() + dt = love.timer.getDelta() + end + if love.update then love.update(dt) end + if multi.boost then + for i=1,multi.boost-1 do + multi:uManager(dt) + end + end + multi:uManager(dt) + if love.window and love.graphics and love.window.isCreated() then + love.graphics.clear() + love.graphics.origin() + if love.draw then love.draw() end + multi.dManager() + love.graphics.setColor(255,255,255,255) + if multi.draw then multi.draw() end + love.graphics.present() + end + end +end +multi.drawF={} +function multi:dManager() + for ii=1,#multi.drawF do + multi.drawF[ii]() + end +end +function multi:onDraw(func,i) + i=i or 1 + table.insert(self.drawF,i,func) +end +function multi:lManager() + if love.event then + love.event.pump() + for e,a,b,c,d in love.event.poll() do + if e == "quit" then + if not love.quit or not love.quit() then + if love.audio then + love.audio.stop() + end + return nil + end + end + love.handlers[e](a,b,c,d) + end + end + if love.timer then + love.timer.step() + dt = love.timer.getDelta() + end + if love.update then love.update(dt) end + multi:uManager(dt) + if love.window and love.graphics and love.window.isCreated() then + love.graphics.clear() + love.graphics.origin() + if love.draw then love.draw() end + multi.dManager() + love.graphics.setColor(255,255,255,255) + if multi.draw then multi.draw() end + love.graphics.present() + end +end diff --git a/Libs/test.dat b/Libs/test.dat new file mode 100644 index 0000000..8b9302a Binary files /dev/null and b/Libs/test.dat differ diff --git a/Libs/test.lua b/Libs/test.lua new file mode 100644 index 0000000..f551bde --- /dev/null +++ b/Libs/test.lua @@ -0,0 +1,18 @@ +require("Library") +local clock = os.clock +function sleep(n) -- seconds + local t0 = clock() + while clock() - t0 <= n do end +end +function tester(test) + sleep(1) + return test*10 +end +--~ require("bin") +--~ test=bin.namedBlockManager() +--~ test["name"]="Ryan" +--~ test["age"]=21 +--~ test:tofile("test.dat") +--~ test2=bin.namedBlockManager("test.dat") +--~ print(test2["name"]) +--~ print(test2["age"]) diff --git a/Tests.dmf b/Tests.dmf new file mode 100644 index 0000000..41fea47 --- /dev/null +++ b/Tests.dmf @@ -0,0 +1,38 @@ +USING AICM +USING EBIM +[ONCHAT:function(msg,speaker)]{ + p"(msg:cap1)What is (.+)?"< + "I don't know what $cap1$ is sorry..." GOTO(end) + "How would I know what cap1$ is?" GOTO(end) + "Funny that you asked about that, because I have no idea what $cap1$ is." GOTO(end) + > + ::end:: +} +[START]{ + msg="What is love?" + p(msg:cap1)What is (.+)? + "$cap1$";"hi!" + test=[1,144,3] + num=100 + a=num + "$a$" + --Comment Here + switch key: + case "A" + --[[ + long + comment + ]] + "Hello Whats up!" + "You are here now" + case "B" JUMP(BLOCKOTHER) + case "C" JUMP(BLOCKOTHER) + case "D" JUMP(BLOCKOTHER) + else JUMP(BLOCKOTHER) + endswitch + error("Test") + "Now we are here";"Teehee" +} +[ERROR]{ + error() +} \ No newline at end of file diff --git a/adventures/bedroom.dat b/adventures/bedroom.dat new file mode 100644 index 0000000..61aa953 --- /dev/null +++ b/adventures/bedroom.dat @@ -0,0 +1,135 @@ +-- When using seperate files to hold data you should have a convention for identification purposes +[BEDROOM]{ + cls() + SAVE() + wenttobedroom=setVar(true) + "You take a look around your room, and can't help but notice the amount of mess in it"< + "Examine Desk" JUMPPLAY(Bedroom_DESK,select) + "Examine Bed" JUMPPLAY(Bedroom_BED,select) + "Examine Closet" JUMPPLAY(Bedroom_CLOSET,select) + "Examine Clock" JUMPPLAY(Bedroom_CLOCK,select) + "Examine Trash" JUMPPLAY(Bedroom_TRASH,select) + "Examine Door" JUMPPLAY(Bedroom_DOOR,select) + > +} +[Bedroom_DESK]{ + COMPARE(=,bedroom_lookedatdesk,true,Bedroom_DESK2,Bedroom_DESK1) +} +[Bedroom_DESK1]{ + bedroom_lookedatdesk=setVar(true) + "My lovely desk, it has my homework and a pile of papers on it" + "I really should clean my desk up a bit" + playSong(paper) + "..." + "There we go, nice and clean now" + "I guess I'll hold on to these pieces of paper for now" + JUMP(BEDROOM) +} +[Bedroom_DESK2]{ + "MY desk sure looks a lot better without all of that paper scattered around it" + JUMP(BEDROOM) +} +[Bedroom_BED]{ + COMPARE(=,bedroom_lookedatbed,true,Bedroom_BED1,__STAY) + bedroom_lookedatbed=setVar(true) + COMPARE(=,bedroom_lookedatclock,true,Bedroom_BED2,__STAY) + "Ah my bed, if it weren't for mom I would be sleeping right now" + "I remember back when I was younger I used to jump on my bed" + playSong(bed) + "haha this is fun" + playSong(laugh) + "Okay, I think I am done for now" + JUMP(BEDROOM) +} +[Bedroom_BED1]{ + playSong(laugh) + "I had enough, let me look around the room more" + JUMP(BEDROOM) +} +[Bedroom_BED2]{ + "I remember back when I was younger I used to jump on my bed" + playSong(bed) + "haha this is fun" + playSong(laugh) + "Okay, I think I am done for now" + JUMP(BEDROOM) +} +[Bedroom_CLOSET]{ + COMPARE(=,bedroom_lookedatcloset,true,Bedroom_CLOSET1,__STAY) + bedroom_lookedatcloset=setVar(true) + "Look at all these clothes" + "Hmm..." + playSong(paper) + "Hey, what do you know 15 dollars!" + money=ADD(money,15) + "I now have $money$ dollars" + JUMP(BEDROOM) +} +[Bedroom_CLOSET1]{ + "Nothing interesting left in here" + JUMP(BEDROOM) +} +[Bedroom_CLOCK]{ + COMPARE(=,bedroom_lookedatclock,true,Bedroom_CLOCK1,__STAY) + bedroom_lookedatclock=setVar(true) + playSong(alarm) + playSong(laugh) + "Ahhh... my alarm wasn't expecting that!" + "Looks like it is 9AM I should start hurrying" + COMPARE(=,bedroom_lookedatbed,true,__STAY,BEDROOM) + playSong(laugh) + "I guess even though my mom called me, my alarm would have woken me up anyway" +} +[Bedroom_CLOCK1]{ + "It's still morning, but I should probably get going" + JUMP(BEDROOM) +} +[Bedroom_TRASH]{ + COMPARE(=,bedroom_lookedattrash,true,Bedroom_TRASH2,Bedroom_TRASH1) +} +[Bedroom_TRASH1]{ + "An empty garbage can..." + "I kinda want to put something in it..." + COMPARE(=,bedroom_lookedatdesk,true,__STAY,BEDROOM_REDIRECT_TRASH) + bedroom_lookedattrash=setVar(true) + bedroom_trashcounter=setVar(1,"n") + "Alright, I'll throw away some of these pieces of paper I found on my desk" + playSong(paper) + playSong(laugh) + "I feel like an all-star" + JUMP(BEDROOM) +} +[BEDROOM_REDIRECT_TRASH]{ + playSong(sigh) + "All well, I don't have anything I can put into it" + JUMP(BEDROOM) +} +[Bedroom_TRASH2]{ + "Another shot for the all-star" + playSong(paper) + playSong(laugh) + bedroom_trashcounter=ADD(bedroom_trashcounter,1) + "I think I threw in $bedroom_trashcounter$ pieces already, and I didn't even miss a shot, a new record!" + JUMP(BEDROOM) +} +[Bedroom_DOOR]{ + COMPARE(=,bedroom_lookedatdoor,true,Bedroom_DOOR2,Bedroom_DOOR1) +} +[Bedroom_DOOR1]{ + bedroom_lookedatdoor=setVar(true) + "This is like the nicest wooden door I have ever seen!" + "The wood is so sturdy and it has that solid feel" + "You know that feel when you knock on it and it doesn't feel like it will break from your knock" + playSong(laugh) + "Okay, I should stop rambling..." + "Am I ready to go down stairs?"< + "Yeah, I looked around enough" JUMPPLAY(LIVINGROOM,select) + "Hmm... Maybe I should take a second look around..." JUMPPLAY(BEDROOM,select) + > +} +[Bedroom_DOOR2]{ + "Am I ready to go down stairs?"< + "Yeah, I looked around enough" JUMPPLAY(LIVINGROOM,select) + "Hmm... Maybe I should take a second look around..." JUMPPLAY(BEDROOM,select) + > +} diff --git a/adventures/home.dat b/adventures/home.dat new file mode 100644 index 0000000..68ed33d --- /dev/null +++ b/adventures/home.dat @@ -0,0 +1,3 @@ +[HOME]{ + "This is getting too much to make lol" +} \ No newline at end of file diff --git a/adventures/livingroom.dat b/adventures/livingroom.dat new file mode 100644 index 0000000..a503127 --- /dev/null +++ b/adventures/livingroom.dat @@ -0,0 +1,75 @@ +LOAD adventures/store.dat +[LIVINGROOM]{ + cls() + SAVE() + playSong(stairs) + "$name$: I am coming down right now" + cmd=setVar("Hey") + COMPARE(=,wenttobedroom,true,__STAY,Livingroom_Chat) + cmd=setVar("Anyway") + "Mom: What took you so long?"< + "I was upstairs looking around my room" JUMPPLAY(Livingroom_Truth,select) + "Tell her a lie" JUMPPLAY(Livingroom_Lie,select) + > +} +[Livingroom_Truth]{ + "$name$: I was upstairs looking around my room a bit, I was cleaning a bit and found some cash too" + "Mom: Okay... next time when I call you come right away" + playSong(laugh) + "$name$ Okay mom I promise" + momcantrust=setVar(true) + SAVE() + JUMP(Livingroom_Chat) +} +[Livingroom_Lie]{ + "$name$: As I was going down stairs I heard my clock ring so I went to turn it off" + COMPARE(=,bedroom_lookedatclock,true,__STAY,Livingroom_CoughtInLieClock) + "Mom: I heard your alarm $name$, thats true" + COMPARE(=,bedroom_lookedatbed,true,Livingroom_CoughtInLieBed,__STAY) + COMPARE(=,bedroom_lookedatdesk,true,__STAY,Livingroom_Okay) + COMPARE(=,bedroom_lookedattrash,true,__STAY,Livingroom_Okay) + "Mom: but, what was all that 'All-Star' stuff about huh?" + "$name$: Hey I can explain, ok so I wa..." + "Mom: I don't want to hear it!" + "$name$: but..." + playSong(sigh) + "Mom: No buts!" + JUMP(Livingroom_CoughtInLie) +} +[Livingroom_CoughtInLieBed]{ + "Mom: But what was all that jumping around on your bed for?" + "$name$: ..." + "Mom: Sometimes I wonder about you, you know that" + "$name$: ..." + JUMP(Livingroom_CoughtInLie) +} +[Livingroom_CoughtInLieClock]{ + "Mom: I didn't hear a clock mister!" + "$name$: Oh... um..." + JUMP(Livingroom_CoughtInLie) +} +[Livingroom_CoughtInLie]{ + "Mom: how many times have I told you not to lie to me $name$! I can never trust you to tell me the truth" + JUMP(Livingroom_Chat) +} +[Livingroom_Okay]{ + momcantrust=setVar(true) + isElusive=setVar(true) + "Mom: Alright then got it, no problem" + SAVE() + JUMP(Livingroom_Chat) +} +[Livingroom_Chat]{ + "Mom: $cmd$, I need you to get some stuff from the store, I am making breakfast and we are out of some stuff." + playSong(pots) + "Mom: I have a list of things you need to get over there, go get it and bring the stuff back" + playSong(paper) + "$name$: Alright, I'll get the stuff..." + playSong(sigh) + "$name$: There is so many things I need to get" + "Mom: Well make sure you get them all, or else" + "$name$: Alright, I got it.." + playSong(footsteps) + fadeSong(maintheme) + JUMP(STORE) +} diff --git a/adventures/resources.dat b/adventures/resources.dat new file mode 100644 index 0000000..8343cc4 --- /dev/null +++ b/adventures/resources.dat @@ -0,0 +1,40 @@ +[CONFIG]{ + cls() + --setLeaderboard("Money: $money$ Day: $day$") + dat=LOAD() -- call this only once!!! + maintheme=loadSong("Audio/Collapse.ogg") + laugh=loadSong("Audio/Laugh.ogg") + yawn=loadSong("Audio/Yawn.ogg") + sigh=loadSong("Audio/sigh.ogg") + stairs=loadSong("Audio/Creaky.ogg") + paper=loadSong("Audio/paper.ogg") + select=loadSong("Audio/select.ogg") + bed=loadSong("Audio/bed.ogg") + alarm=loadSong("Audio/alarm.ogg") + stairs=loadSong("Audio/stairs.ogg") + footsteps=loadSong("Audio/footsteps.ogg") + pots=loadSong("Audio/pots.ogg") + hmm=loadSong("Audio/hmm.ogg") + knife=loadSong("Audio/knife.ogg") + boyknife=loadSong("Audio/boyknife.ogg") + over=loadSong("Audio/over.ogg") + playSongLooped(maintheme,.4) + COMPARE(=,dat,1,HASDATA,NODATA) +} +[HASDATA]{ + RESTORE() +} +[NODATA]{ + "Welcome to my, Choose your own Adventure Game: The Story of Wonder" + money=10 + day=1 + name=getInput("Enter Your Name: ") + "Name: $name$ is this corect?"< + "Yes" JUMPPLAY("SAVEINIT",select) + "No" JUMPPLAY("NODATA",select) + > +} +[SAVEINIT]{ + SAVE() + JUMP("START") +} \ No newline at end of file diff --git a/adventures/store.dat b/adventures/store.dat new file mode 100644 index 0000000..c07c8a8 --- /dev/null +++ b/adventures/store.dat @@ -0,0 +1,221 @@ +LOAD adventures/home.dat +[STORE]{ + cls() + playSong(footsteps) + COMPARE(=,Store_StartedMenu,true,__SKIP+7,__STAY) + grab=setVar("first") + SAVE() + Store_StartedMenu=setVar(true) + store=loadSong("Audio/store.ogg") + stopSong() + playSongLooped(store) + "Alright, I am at the store..." + "Let's take a look at this list" + playSong(paper) + "What should I grab $grab$?"< + "Milk" JUMPPLAY(Store_Milk,footsteps) + "Eggs" JUMPPLAY(Store_Eggs,footsteps) + "Bread" JUMPPLAY(Store_Bread,footsteps) + "Butter" JUMPPLAY(Store_Butter,footsteps) + "Orange and Apple Juice" JUMPPLAY(Store_OJAJ,footsteps) + "Frozen Pizzas" JUMPPLAY(Store_Frozen,footsteps) + "Sussages" JUMPPLAY(Store_Sussages,footsteps) + "Go to checkout" JUMPPLAY(Store_CheckOut,footsteps) + > +} +[Store_CheckOut]{ + Store_cost=setVar(0,"n") + COMPARE(=,Store_GotMilk,true,__STAY,__SKIP+2) + Store_cost=ADD(Store_cost,1.75) + "Ok $Store_cost$ for the Milk" + COMPARE(=,Store_GotEggs,true,__STAY,__SKIP+2) + Store_cost=ADD(Store_cost,4.50) + "$Store_cost$ with the Eggs" + COMPARE(=,Store_GotBread,true,__STAY,__SKIP+2) + Store_cost=ADD(Store_cost,2.75) + "$Store_cost$ with the Bread" + COMPARE(=,Store_GotButter,true,__STAY,__SKIP+2) + Store_cost=ADD(Store_cost,2.99) + "$Store_cost$ with the Butter" + COMPARE(=,Store_GotOJAJ,true,__STAY,__SKIP+2) + Store_cost=ADD(Store_cost,5.50) + "$Store_cost$ with the Juices" + COMPARE(=,Store_GotSussages,true,__STAY,__SKIP+2) + Store_cost=ADD(Store_cost,2.00) + "$Store_cost$ with the sussages" + COMPARE(=,Store_GotPizzas,true,__STAY,__SKIP+16) + Store_cost=ADD(Store_cost,1.75) + "$Store_cost$ with the frozen pizzas" + COMPARE(=,metRick,true,__STAY,__SKIP+13) + "Rick: Look who's at the checkout line..." + playSong(hmm) + "Rick: And what do we have here? Are those frozen pizzas?" + "$name$: ..." + playSong(hmm) + "Rick: What happened to I didn't know?" + "$name$: At the time I had no idea where they were..." + ricksaw=setVar(true) + "Rick: I see how it is..." + playSong(footsteps) + "$name$: I don't know why, but I get a really bad feeling from him..." + playSong(sigh) + "$name$: Well, I'll worry about that later" + COMPARE(=,Store_cost,0,Store_NoItems,__STAY) + "Store Clerk: Alright, looks like you owe me $Store_cost$ dollars for your items" + COMPARE(>,money,Store_cost,__STAY,__SKIP+5) + couldpay=setVar(true) + "$name$: Here you go..." + "Store Clerk: Thanks, have a good day" + money=SUB(money,Store_cost) + JUMP(HOME) + "$name$: Crap, I don't have the money on me..." + "Store Clerk: Well I guess you won't be leaving with any items then" + JUMP(HOME) +} +[Store_NoItems]{ + playSong(hmm) + "What am I doing?" + "I didn't even buy anything" + "Should I really leave the store without buying anything?"< + "Yes" JUMPPLAY(__STAY,footsteps) + "No" JUMPPLAY(STORE,select) + > + Store_BoughtNone=true + JUMP(HOME) +} +[STOREROUTER]{ + grab=setVar("next") + JUMP(STORE) +} +[Store_Milk]{ + COMPARE(=,Store_GotMilk,true,__SKIP+8,__STAY) + Store_GotMilk=setVar(true) + "Hmm.. Where is the milk?" + playSong("footsteps") + "Maybe it's over here..." + playSong(laugh) + "Ah here it is, I wonder why it took so long..." + "On to the next item" + JUMP(STOREROUTER) + "I already grabbed the milk!" + JUMP(STOREROUTER) +} +[Store_Eggs]{ + COMPARE(=,Store_GotEggs,true,__SKIP+14,__STAY) + Store_GotEggs=setVar(true) + COMPARE(=,Store_GotMilk,true,__STAY,__SKIP+3) + "Now... I think the eggs should be close to the milk" + playSong(footsteps) + "Weird, I don't see them" + COMPARE(=,Store_GotButter,true,__STAY,__SKIP+3) + "Wait! I think I saw them near the butter" + playSong(laugh) + "I feel dumb now" + playSong(footsteps) + "Here the eggs are!" + playSong(sigh) + "I walked over the entire store looking for these" + JUMP(STOREROUTER) + "I already grabbed the Eggs" + JUMP(STOREROUTER) +} +[Store_Bread]{ + COMPARE(=,Store_GotBread,true,__SKIP+31,__STAY) + Store_GotBread=setVar(true) + scared=loadSong("Audio/twisted.ogg") + "Now for the bread..." + playSong(footsteps) + "Here we g..." + playSongLooped(scared,.4) + playSong(hmm) + metRick=setVar(true) + "Who's that?" + "Unknown Man: Hello there little boy!?" + "$name$: Umm... hi... Who are you?" + "Rick: You can call me Rick!" + "$name$: So... Rick what do you want?" + "Rick: Oh, I want to ask you if you knew where the Frozen Pizzas are?" + COMPARE(=,Store_GotPizzas,true,__STAY,Store_Idk) + "$name$: Yeah, I know where they are..." + playSong(footsteps) + "Rick: Thanks a lot sonny..." + "$name$: Yeah don't mention it" + "Rick: Can you do me one more favor?" + playSong(sigh) + "$name$: Sure what is it?" + "Rick: DIE!" + playSong(boyknife) + sleep(1.5) + fadeSong(scared) + stopSong() + playSong(over) + UNSAVE() + sleep(3) + JUMP(CONFIG) + "I already got the bread! I meet a creepy man named Rick over here... I should get out of here!" + JUMP(STOREROUTER) +} +[Store_Idk]{ + "$name$: I am sorry, but I don't know..." + playSong(sigh) + "Rick: Alright then, I guess I will have to find them myself..." + playSong(footsteps) + fadeSong(scared) + stopSong() + stopSong(store) + playSongLooped(store,1) + sleep(.5) + playSong(laugh) + "That was weird... Well at least I got the bread" + "That was one strange man though..." + JUMP(STOREROUTER) +} +[Store_Butter]{ + COMPARE(=,Store_GotButter,true,__SKIP+5,__STAY) + Store_GotButter=setVar(true) + "Great I found the butter" + "This is going smoother than I thought" + "This is great, I'll be home in no time" + JUMP(STOREROUTER) + "I already grabbed the Butter!" + JUMP(STOREROUTER) +} +[Store_OJAJ]{ + COMPARE(=,Store_GotOJAJ,true,__SKIP+5,__STAY) + Store_GotOJAJ=setVar(true) + "Here they are..." + "The orange and apple juice, right next to each other" + "This makes it all the better" + JUMP(STOREROUTER) + "I already grabbed the Juices!" + JUMP(STOREROUTER) +} +[Store_Frozen]{ + COMPARE(=,Store_GotPizzas,true,__SKIP+14,__STAY) + Store_GotPizzas=setVar(true) + "Ok looks like I found the pizzas" + "They are right by the Sussages" + COMPARE(=,Store_GotSussages,true,__SKIP+5,__STAY) + Store_GotSussages=setVar(true) + "Might as well pick them up while I am at it" + playSong(footsteps) + "Now that we got these lets see if I forgot anything else" + JUMP(STOREROUTER) + playSong(laugh) + "I picked up the Sussages already" + playSong(sigh) + "If I were paying attention before I would have grabbed the pizzas as well" + JUMP(STOREROUTER) + "I already got the Frozen Pizzas!" + JUMP(STOREROUTER) +} +[Store_Sussages]{ + COMPARE(=,Store_GotSussages,true,__SKIP+5,__STAY) + Store_GotSussages=setVar(true) + "Oooh the Sussages are right here in the Freezer aisle" + playSong(laugh) + "Well that makes sense" + JUMP(STOREROUTER) + "I already grabbed the Sussages!" + JUMP(STOREROUTER) +} diff --git a/arrow.png b/arrow.png new file mode 100644 index 0000000..78ad96d Binary files /dev/null and b/arrow.png differ diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..80d26f1 --- /dev/null +++ b/conf.lua @@ -0,0 +1,39 @@ +function love.conf(t) + t.identity = nil -- The name of the save directory (string) + t.version = "0.10.1" -- The LOVE version this game was made for (string) + t.console = true -- Attach a console (boolean, Windows only) + + t.window.title = "game" -- The window title (string) + t.window.icon = nil -- Filepath to an image to use as the window's icon (string) + t.window.width = 1200 -- The window width (number) + t.window.height = 738 -- The window height (number) + t.window.borderless = false -- Remove all border visuals from the window (boolean) + t.window.resizable = false -- Let the window be user-resizable (boolean) + t.window.minwidth = 1 -- Minimum window width if the window is resizable (number) + t.window.minheight = 1 -- Minimum window height if the window is resizable (number) + t.window.fullscreen = false -- Enable fullscreen (boolean) + t.window.fullscreentype = "desktop" -- Standard fullscreen or desktop fullscreen mode (string) + t.window.vsync = false -- Enable vertical sync (boolean) + t.window.fsaa = 0 -- The number of samples to use with multi-sampled antialiasing (number) + t.window.display = 1 -- Index of the monitor to show the window in (number) + t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean) + t.window.srgb = false -- Enable sRGB gamma correction when drawing to the screen (boolean) + t.window.x = nil -- The x-coordinate of the window's position in the specified display (number) + t.window.y = nil -- The y-coordinate of the window's position in the specified display (number) + + t.modules.audio = true -- Enable the audio module (boolean) + t.modules.event = true -- Enable the event module (boolean) + t.modules.graphics = true -- Enable the graphics module (boolean) + t.modules.image = true -- Enable the image module (boolean) + t.modules.joystick = true -- Enable the joystick module (boolean) + t.modules.keyboard = true -- Enable the keyboard module (boolean) + t.modules.math = true -- Enable the math module (boolean) + t.modules.mouse = true -- Enable the mouse module (boolean) + t.modules.physics = true -- Enable the physics module (boolean) + t.modules.sound = true -- Enable the sound module (boolean) + t.modules.system = true -- Enable the system module (boolean) + t.modules.timer = true -- Enable the timer module (boolean) + t.modules.window = true -- Enable the window module (boolean) + t.modules.thread = true -- Enable the thread module (boolean) +end +--1440 x 2560 diff --git a/config.txt b/config.txt new file mode 100644 index 0000000..e23d85d --- /dev/null +++ b/config.txt @@ -0,0 +1,5 @@ +ENABLE leaking +ENABLE debugging +ENABLE music +ENABLE forseeLabels +-- Leave this comment alone \ No newline at end of file diff --git a/fire.jpg b/fire.jpg new file mode 100644 index 0000000..529c437 Binary files /dev/null and b/fire.jpg differ diff --git a/init.dat b/init.dat new file mode 100644 index 0000000..e5c4c53 --- /dev/null +++ b/init.dat @@ -0,0 +1,19 @@ +LOAD config.txt -- loads the congig file into memory +LOAD adventures/resources.dat +LOAD adventures/bedroom.dat +LOAD adventures/livingroom.dat +[START]{ + cls() + "Mom: $name$" + "$name$: ..." + "Mom: $name$!" + playSong(yawn,.4) + "$name$: yeah?" + "Mom: Come down here, I need you to do something." + "$name$: Alright, i'll be down in a second!" + "What do you want to do?"< + "Search around the room first" JUMPPLAY(BEDROOM,select) -- bedroom.dat + "Go down to see what mom wants" JUMPPLAY(LIVINGROOM,select) -- livingroom.dat + > +} +-- Well thats it in this file, this keeps everything clean and nice \ No newline at end of file diff --git a/loading/Thumbs.db b/loading/Thumbs.db new file mode 100644 index 0000000..70ba3c0 Binary files /dev/null and b/loading/Thumbs.db differ diff --git a/loading/image-0000001.png b/loading/image-0000001.png new file mode 100644 index 0000000..15dc437 Binary files /dev/null and b/loading/image-0000001.png differ diff --git a/loading/image-0000002.png b/loading/image-0000002.png new file mode 100644 index 0000000..5a35f62 Binary files /dev/null and b/loading/image-0000002.png differ diff --git a/loading/image-0000003.png b/loading/image-0000003.png new file mode 100644 index 0000000..e32309f Binary files /dev/null and b/loading/image-0000003.png differ diff --git a/loading/image-0000004.png b/loading/image-0000004.png new file mode 100644 index 0000000..62eef36 Binary files /dev/null and b/loading/image-0000004.png differ diff --git a/loading/image-0000005.png b/loading/image-0000005.png new file mode 100644 index 0000000..e0eaea1 Binary files /dev/null and b/loading/image-0000005.png differ diff --git a/loading/image-0000006.png b/loading/image-0000006.png new file mode 100644 index 0000000..500db7b Binary files /dev/null and b/loading/image-0000006.png differ diff --git a/loading/image-0000007.png b/loading/image-0000007.png new file mode 100644 index 0000000..b9238b3 Binary files /dev/null and b/loading/image-0000007.png differ diff --git a/loading/image-0000008.png b/loading/image-0000008.png new file mode 100644 index 0000000..d87356f Binary files /dev/null and b/loading/image-0000008.png differ diff --git a/loading/image-0000009.png b/loading/image-0000009.png new file mode 100644 index 0000000..054d32d Binary files /dev/null and b/loading/image-0000009.png differ diff --git a/loading/image-0000010.png b/loading/image-0000010.png new file mode 100644 index 0000000..72750cd Binary files /dev/null and b/loading/image-0000010.png differ diff --git a/loading/image-0000011.png b/loading/image-0000011.png new file mode 100644 index 0000000..40362ae Binary files /dev/null and b/loading/image-0000011.png differ diff --git a/loading/image-0000012.png b/loading/image-0000012.png new file mode 100644 index 0000000..ddf4cae Binary files /dev/null and b/loading/image-0000012.png differ diff --git a/loading/image-0000013.png b/loading/image-0000013.png new file mode 100644 index 0000000..d80c93e Binary files /dev/null and b/loading/image-0000013.png differ diff --git a/loading/image-0000014.png b/loading/image-0000014.png new file mode 100644 index 0000000..e458aa6 Binary files /dev/null and b/loading/image-0000014.png differ diff --git a/loading/image-0000015.png b/loading/image-0000015.png new file mode 100644 index 0000000..a7d34b0 Binary files /dev/null and b/loading/image-0000015.png differ diff --git a/loading/image-0000016.png b/loading/image-0000016.png new file mode 100644 index 0000000..14c4979 Binary files /dev/null and b/loading/image-0000016.png differ diff --git a/loading/image-0000017.png b/loading/image-0000017.png new file mode 100644 index 0000000..d22c69c Binary files /dev/null and b/loading/image-0000017.png differ diff --git a/loading/image-0000018.png b/loading/image-0000018.png new file mode 100644 index 0000000..2efdbc0 Binary files /dev/null and b/loading/image-0000018.png differ diff --git a/loading/image-0000019.png b/loading/image-0000019.png new file mode 100644 index 0000000..3572b5e Binary files /dev/null and b/loading/image-0000019.png differ diff --git a/loading/image-0000020.png b/loading/image-0000020.png new file mode 100644 index 0000000..4a60bc6 Binary files /dev/null and b/loading/image-0000020.png differ diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..c49e61a --- /dev/null +++ b/main.lua @@ -0,0 +1,380 @@ +--package.path="/?/init.lua;"..package.path +require("Libs/Library") +require("Libs/Utils") +require("Libs/bin") +require("Libs/MultiManager") +require("parseManager") +require("Libs/lovebind") +require("GuiManager") +gui.LoadAll("Interface") +function form(link,x,y,w,h,sx,sy,sw,sh) + local x,y,w,h,sx,sy,sw,sh=(link:varExists(x) or tonumber(x)),(link:varExists(y) or tonumber(y)),(link:varExists(w) or tonumber(w)),(link:varExists(h) or tonumber(h)),(link:varExists(sx) or tonumber(sx)),(link:varExists(sy) or tonumber(sy)),(link:varExists(sw) or tonumber(sw)),(link:varExists(sh) or tonumber(sh)) + return x,y,w,h,sx,sy,sw,sh +end +parseManager.internalcount=0 +parseManager.funcType=function(link,name,t,data,filename) + if parseManager.loaded then print("Thread loaded not going to re-init!") return end + local ft,args=t:match("(function)(%b())") + if ft~="function" then return false end + local _args=parseManager.split(args) + local phantomChunk=link._chunks[name][1] + local func=function(self,...) + if type(self)~="table" then + thread=link._methods.newThread(link,name) + print("THREAD:",self,thread.test,link) + local args_={self,...} + for i=1,#args_ do + if _args[i] then + thread.test._variables[(_args[i]:gsub("%)",""):gsub("%(",""))]=args_[i] + end + end + print("!!Diff Thread Method") + else + print("MAINTHREAD:",self,link,test) + print("!!Same Thread Method") + parseManager.internalcount=parseManager.internalcount+1 + test._chunks[name][1]=phantomChunk.."\nGOTO(__TEMPGOTO"..parseManager.internalcount.."__)" + test._labels["__TEMPGOTO"..parseManager.internalcount.."__"]={self._cblockname,test.pos} + test._methods.JUMP(test,name) + end + end + link._variables[name]=func + link._methods[name]=func +end +parseManager.OnExtendedBlock(parseManager.funcType) +function parseManager:pushError(err) + print(err) -- print to the console + local file=self._chunks[self._cblockname].file + local d={} + if love then + print(file) + d=bin.new((love.filesystem.read(file))) + else + d=bin.load(file) + end + local t=d:lines() + local pos=0 + --Sigh... comments are still a pain to deal with... + local cc=d:match("%["..self._cblockname.."[:.-]?%].-({.-})") + cc=cc:gsub("{.-\n","") + cc=cc:gsub((self._cblock[self.pos]:gsub("%%","%%%%"):gsub("%(","%%%("):gsub("%)","%%%)"):gsub("%[","%%%["):gsub("%]","%%%]"):gsub("%+","%%%+"):gsub("%-","%%%-"):gsub("%*","%%%*"):gsub("%.","%%%."):gsub("%$","%%%$"):gsub("%^","%%%^")).."(.+)","NOPE LOL") + --mlc,a=cc:gsub("%-%-%[%[.-%]%]","\n") + --print(mlc) + --d=#bin._lines(mlc or "") + _,b=cc:gsub("(%-%-.-)\n","\n") + _,c=cc:gsub("%-:.-:%-","\n") + e=b+c + print(a,b,c) + for i=1,#t do + if t[i]:find("["..self._cblockname,1,true) then + pos=i+self.pos + break + end + end + error("In Block '"..self._cblockname.."' LIQ: '"..self._cblock[self.pos].."' Filename: "..file.." On line: "..pos+e..": "..err) +end +actornum=0 +animnum=0 +rand=randomGen:new(0) +parseManager:define{ + getInput=multi:newFunction(function(mulitobj,self,msg) + inputBox.message.text=msg + inputBox.Visible=true + go.Visible=false + self.handle:Pause() + while _inputvar==nil do + multi:lManager() + end + self.handle:Resume() + local i=_inputvar + _inputvar=nil + inputBox.Visible=false + go.Visible=true + return i + end), + loadAudio=function(self,path) + return love.audio.newSource(path) + end, + loadSong=function(self,path) + print(path) + return love.audio.newSource(path) + end, + playSongLooped=function(self,item) + item:setLooping(true) + item:play() + end, + playAudio=function(self,item) + item:play() + end, + playSong=function(self,item) + item:play() + end, + sleep=function(self,n) + local num=n + self.handle:hold(num) + end, + fadeSong=function(self,item) + self.handle:Pause() + local handle=self:varExists(item) + local step=multi:newTStep(100,0,-1,.05) + step:OnStep(function(pos,self) + handle:setVolume(pos/100) + end) + while handle:getVolume()~=0 do + multi:lManager() + end + self.handle:Resume() + end, + stopAudio=function(self,item) + item:stop() + end, + stopSong=function(self,item) + if self:varExists(item)==nil then + love.audio.stop() + return + end + item:stop() + end, + pauseAudio=function(self,item) + item:pause() + end, + cls=function(self) + core.chatFrame.textHolder.text="" + end, + BG=function(self,path) + core:SetImage(path) + end, + SHOW=function(self,item) + self:varExists(item).Visible=true + end, + HIDE=function(self,item) + self:varExists(item).Visible=false + end, + createObject=function(self,x,y,w,h,sx,sy,sw,sh) + actornum=actornum+1 + local x,y,w,h,sx,sy,sw,sh=form(self,x,y,w,h,sx,sy,sw,sh) + local obj=workspace:newItem("",nil,"Actor "..actornum, x, y, w, h, sx ,sy ,sw ,sh) + if obj.DPI>=2 then + obj.DPI=obj.DPI-1 + end + print("OBJECT: "..tostring(obj)) + return obj + end, + makeObject=function(self,link,x,y,w,h,sx,sy,sw,sh) + actornum=actornum+1 + local x,y,w,h,sx,sy,sw,sh=form(self,x,y,w,h,sx,sy,sw,sh) + local obj= link:newItem("",nil,"Actor "..actornum, x, y, w, h, sx ,sy ,sw ,sh) + if obj.DPI>=2 then + obj.DPI=obj.DPI-1 + end + return obj + end, + createAnimation=function(self,file,delay,x,y,w,h,sx,sy,sw,sh) + local file,delay=(self:varExists(file) or file),(tonumber(self:varExists(delay)) or tonumber(delay)) + animnum=animnum+1 + local x,y,w,h,sx,sy,sw,sh=form(self,x,y,w,h,sx,sy,sw,sh) + local anim = workspace:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) + anim:OnAnimEnd(function(link) + link:Reset() + link:Resume() + end) + if anim.DPI>=2 then + anim.DPI=anim.DPI-1 + end + return anim + end, + stopAnimation=function(self,item) + item:Pause() + end, + resumeAnimation=function(self,item) + item:Resume() + end, + resetAnimation=function(self,item) + item:Reset() + end, + setImage=function(self,item,path) + smartPrint(item) + item:SetImage(path) + end, + setText=function(self,item,text) + if type(item)=="string" then + print(actor) + self:pushError("item must be a gui object!") + end + item.text=text + end, + JUMPPLAY=function(self,to,handle) + self._methods.playSong(self,handle) + self._methods.JUMP(self,to) + end, + setPosition=function(self,item,x,y,w,h,sx,sy,sw,sh) + local x,y,w,h,sx,sy,sw,sh=form(self,x,y,w,h,sx,sy,sw,sh) + item:SetDualDim(x,y,w,h,sx,sy,sw,sh) + end, + makeDraggable=function(self,item,db) + item.Draggable=true + if db then + item.dragbut=db + end + end, + centerX=function(self,item) + item:centerX() + end, + centerY=function(self,item) + item:centerY() + end, + centerXY=function(self,item) + item:centerX() + item:centerY() + end, + setVar=function(self,v,t) if t=="n" then return tonumber(v) else return v end end, + destroy=function(self,item) + item:Destroy() + end, + newThread=function(blocklink,block) + local loop=multi:newLoop(function(ti,self) + if self.t.Type=="text" then + print(self.t.text) + self.t=self.test:next() + elseif self.t.Type=="condition" then + self.t=self.test:next() + elseif self.t.Type=="assignment" then + self.t=self.test:next() + elseif self.t.Type=="label" then + self.t=self.test:next() + elseif self.t.Type=="method" then + self.t=self.test:next() + elseif self.t.Type=="choice" then + self.t=self.test:next(self.t,math.random(1,#self.t.choices)) + elseif self.t.Type=="end" then + self:Destroy() + elseif self.t.Type=="error" then + print(self.t.text) + else + self.t=self.test:next() + end + end) + loop.test=parseManager:load(blocklink._chunks[blocklink._cblockname].file) + loop.test._variables=blocklink._variables + loop.test.handle=loop + loop.t=loop.test:start(block) + return loop + end, +} +gui.enableAutoWindowScaling(true) +core=gui:newImageLabel(nil,0,0,0,0,0,0,1,1)--gui:newFullImageLabel("fire.jpg","BG") +workspace=core:newFullFrame() +top=gui:newFrame("",0,0,0,0,0,0,1,1) +workspace.Visibility=0 +top.Visibility=0 +core.chatFrame=core:newFrame("chatFrame",20,-100,-40,80,0,1,1) +core.chatFrame:setRoundness(10,10,360) +core.chatFrame.BorderSize=4 +core.chatFrame.textHolder=core.chatFrame:newTextLabel("","",5,5,-10,-10,0,0,1,1) +core.chatFrame.textHolder.Visibility=0 +core.chatFrame.textHolder.text="" +core.chatFrame.textHolder.TextFormat="left" +parseManager:setVariable("gui",workspace) +parseManager:setVariable("__workspace",workspace) +parseManager:setVariable("__top",top) +parseManager:setVariable("__menu",top) +test=parseManager:load("structure.dat") +t=test:start("CONDITIONS") +go=core.chatFrame.textHolder:newImageButton("arrow.png",-25,-25,20,20,1,1) +go:OnReleased(function(b,self) + dialogeHandler:Resume() +end) +dialogeHandler=multi:newLoop(function(ti,self) + if t.Type=="text" then + core.chatFrame.textHolder.text=t.text + self:Pause() + t=test:next() + elseif t.Type=="condition" then + t=test:next() + elseif t.Type=="assignment" then + t=test:next() + elseif t.Type=="label" then + t=test:next() + elseif t.Type=="method" then + t=test:next() + elseif t.Type=="choice" then + go.Visible=false + local choiceframe=gui:newFrame("",0,0,300,(#t.choices+1)*40-10) + choiceframe:newTextLabel(t.text,0,0,0,40,0,0,1).Color=Color.light_blue + for i=1,#t.choices do + local choice=choiceframe:newTextButton(t.choices[i],0,i*40,0,40,0,0,1) + choice.Color=Color.Darken(Color.saddle_brown,.15) + choice.index=i + choice:OnReleased(function(b,self) + choicemade=self.index + end) + end + choiceframe:centerX() + choiceframe:centerY() + self:Pause() + while choicemade==nil do + multi:lManager() + end + self:Resume() + go.Visible=true + choiceframe:Destroy() + local cm=choicemade + choicemade=nil + t=test:next(nil,cm,nil,t) + elseif t.Type=="end" then + if t.text=="leaking" then -- go directly to the block right under the current block if it exists + t=test:next() + else + --os.exit() + end + elseif t.Type=="error" then + error(t.text) + else + test:next() + end +end) +test.handle=dialogeHandler +inputBox=gui:newFrame(0,0,500,160) +inputBox.Visibility=0 +inputBox.header=inputBox:newFrame(0,0,8,28,0,0,1) +inputBox.header.Visibility=0 +inputBox.header.ClipDescendants=true +inputBox.header.helper=inputBox.header:newFrame("",4,4,-8,40,0,0,1) +inputBox.header.helper.BorderSize=4 +inputBox.header.helper:setRoundness(10,20,360) +inputBox.header.helper:ApplyGradient{Color.Brown,Color.Lighten(Color.Brown,.15)} +inputBox.body=inputBox:newFrame("",4,28,0,150,0,0,1) +inputBox.body.BorderSize=4 +inputBox.body:ApplyGradient{Color.tan,Color.Lighten(Color.tan,.3)} +inputBox.X=inputBox.header.helper:newTextButton("X","X",-23,4,15,15,1) +inputBox.X:setRoundness(5,5,360) +inputBox.X:ApplyGradient{Color.red,Color.Lighten(Color.red,.2)} +inputBox.X.Tween=-6 +inputBox.X.XTween=-2 +inputBox.message=inputBox.body:newTextLabel("","Prompt",0,0,0,0,.05,.1,.9,.5) +inputBox.input2=inputBox.body:newTextLabel("","",0,0,0,30,.05,.65,.7) +inputBox.input=inputBox.body:newTextBox("","Enter Text",0,0,0,30,.05,.65,.7) +inputBox.enter=inputBox.body:newTextButton("","GO",0,0,0,30,.8,.65,.15) +inputBox.message.BorderSize=4 +inputBox.input2.BorderSize=4 +inputBox.enter.BorderSize=4 +inputBox.message:setRoundness(5,5,360) +inputBox.input2:setRoundness(5,5,360) +inputBox.input2:ApplyGradient{Color.tan,Color.Lighten(Color.tan,.2)} +inputBox.enter:ApplyGradient{Color.Darken(Color.green,.2),Color.green} +inputBox.enter:setRoundness(5,5,360) +inputBox.enter:OnReleased(function(b,self) + _inputvar=inputBox.input.text + inputBox.Visible=false +end) +inputBox.input:OnEnter(function(self,text) + _inputvar=inputBox.input.text + inputBox.Visible=false +end) +inputBox.input.TextFormat="left" +inputBox.input.XTween=3 +inputBox.input.Visibility=0 +inputBox.input.ClipDescendants=true +inputBox:centerX() +inputBox:centerY() +inputBox.Visible=false diff --git a/net/chatting.lua b/net/chatting.lua new file mode 100644 index 0000000..fe2cb70 --- /dev/null +++ b/net/chatting.lua @@ -0,0 +1,51 @@ +require("net") +--General Stuff +--[[ What this module does! +Adds +net.chatting:init() +server:OnChatRecieved(function({user,msg}) end) +client:OnChatRecieved(function(user,msg) end) +client:sendChat(user,msg) +]] +net:registerModule("chatting",{1,0,0}) +function net.chatting:init() -- calling this initilizes the library and binds it to the servers and clients created + --Server Stuff + net.OnServerCreated:connect(function(s) + print("The Chatting Module has been loaded onto the server!") + s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered + --First Lets make sure we are getting chatting data + local user,msg = data:match("!chatting! (%S-) '(.+)'") + if user and msg then + local struct={ -- pack the info up as a table so the server can do filtering and whatnot to the chat + user=user, + msg=msg + } + self.OnChatRecieved:Fire(struct) -- trigger the chat event + self:sendAll("!chatting! "..struct.user.." '"..struct.msg.."'") + end + end) + s.rooms={} + function s:regesterRoom(roomname) + self.rooms[roomname]={} + end + s.OnChatRecieved=multi:newConnection() -- create a chat event + end) + --Client Stuff + net.OnClientCreated:connect(function(c) + c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered + --First Lets make sure we are getting chatting data + local user,msg = data:match("!chatting! (%S-) '(.+)'") + if user and msg then + --This is the client so our job here is done + self.OnChatRecieved:Fire(user,msg) -- trigger the chat event + end + end) + function c:sendChat(user,msg) + self:send("!chatting! "..user.." '"..msg.."'") + end + c.OnChatRecieved=multi:newConnection() -- create a chat event + end) +end +if net.autoInit then + net.chatting:init() +end diff --git a/net/email.lua b/net/email.lua new file mode 100644 index 0000000..dbea43a --- /dev/null +++ b/net/email.lua @@ -0,0 +1,53 @@ +require("net.identity") +net:registerModule("email",{1,0,0}) +smtp = require 'socket.smtp' +ssl = require 'ssl' + +function net.email.init(from,user,pass) + net.OnServerCreated:connect(function(s) + s.from=from + s.user=user + s.pass=pass + function s:sendMessage(subject, body, dTable) + local msg = { + headers = { + from = '<'..dTable.email..'>' + to = dTable.nick..' <'..dTable.email..'>', + subject = subject + }, + body = body + } + local ok, err = smtp.send { + from = '<'..self.from..'>', + rcpt = '<'..dTable.email..'>', + source = smtp.message(msg), + user = self.user, + password = self.pass, + server = 'smtp.gmail.com', + port = 465, + create = net.sslCreate + } + if not ok then + print("Mail send failed", err) -- better error handling required + end + end + end) +end +function net.sslCreate() + local sock = socket.tcp() + return setmetatable({ + connect = function(_, host, port) + local r, e = sock:connect(host, port) + if not r then return r, e end + sock = ssl.wrap(sock, {mode='client', protocol='tlsv1'}) + return sock:dohandshake() + end + }, { + __index = function(t,n) + return function(_, ...) + return sock[n](sock, ...) + end + end + }) +end + diff --git a/net/identity.lua b/net/identity.lua new file mode 100644 index 0000000..21c7e5e --- /dev/null +++ b/net/identity.lua @@ -0,0 +1,192 @@ +require("net") +--General Stuff +--[[ What this module does! +Adds +net.identity:init() + +]] +net:registerModule("identity",{1,0,0}) +function net.hash(text,n) + n=n or 16 + return bin.new(text.."jgmhktyf"):getHash(n) +end +function net.identity:init() -- calling this initilizes the library and binds it to the servers and clients created + --Server Stuff + net.OnServerCreated:connect(function(s) + s.userFolder="./" + print("The identity Module has been loaded onto the server!") + function s:_isRegistered(user) + return io.fileExists(self.userFolder..net.hash(user)..".dat") + end + function s:getUserData(user) + local userdata=bin.load(self.userFolder..net.hash(user)..".dat") + local nick,dTable=userdata:match("%S-|%S-|(%S-)|(.+)") + return nick,loadstring("return "..(dTable or "{}"))() + end + function s:getUserCred(user) + local userdata=bin.load(self.userFolder..net.hash(user)..".dat") + return userdata:match("%S-|(%S-)|") + end + function s:userLoggedIn(cid) + for i,v in pairs(self.loggedIn) do + if v.cid==cid then + return i + end + end + return false + end + function s:setDataLocation(loc) + self.userFolder=loc + end + function s:loginUserOut(user) + self.loggedIn[user]=nil + end + function s:loginUserIn(user,cid) + local nick,dTable=self:getUserData(user) + self.loggedIn[user]={} + table.merge(self.loggedIn[user],dTable or {}) + self.loggedIn[user].cid=cid + self.loggedIn[user].nick=nick + return self:getUserDataHandle(user) + end + function s:getUserDataHandle(user) + return self.loggedIn[user] + end + function s:syncUserData(user,ip,port) + local handle=self:getUserDataHandle(user) + self:send(ip,"!identity! SYNC <-|"..bin.ToStr(handle).."|->",port) + end + s.loggedIn={} + s.OnUserRegistered=multi:newConnection() + s.OnUserLoggedIn=multi:newConnection() + s.OnUserLoggerOut=multi:newConnection() + s.OnAlreadyLoggedIn=multi:newConnection() + s.OnPasswordForgotten=multi:newConnection() + s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered + local cmd,arg1,arg2,arg3,arg4 = data:match("!identity! (%S-) '(.-)' '(.-)' '(.-)' <%-|(.+)|%->") + if cmd=="register" then + local user,pass,nick,dTable = arg1,arg2,arg3,arg4 + if self:_isRegistered(user) then + self:send(ip,"!identity! REGISTERED <-|"..user.."|->",port) + else + if not(self.userFolder:sub(-1,-1)=="/" or self.userFolder:sub(-1,-1)=="\\") then + self.userFolder=self.userFolder.."/" + end + local rets=self.OnUserRegistered:Fire(user,pass,nick,loadstring("return "..(dTable or "{}"))()) + for i=1,#rets do + if rets[i][1]==false then + print("Server refused to accept registration request!") + self:send(ip,"!identity! REGISTERREFUSED <-|NIL|->",port) + return + end + end + bin.new(string.format("%s|%s|%s|%s\n",user,pass,nick,dTable)):tofile(self.userFolder..net.hash(user)..".dat") + self:send(ip,"!identity! REGISTEREDGOOD <-|"..user.."|->",port) + end + return + elseif cmd=="login" then + local user,pass = arg1,arg2 + local _pass=s:getUserCred(user) + if not(self:_isRegistered(user)) then + self:send(ip,"!identity! LOGINBAD <-|nil|->",port) + return + end + print(pass,_pass) + if pass==_pass then + if self:userLoggedIn(cid) then + self.OnAlreadyLoggedIn:Fire(self,user,cid,ip,port) + self:send(ip,"!identity! ALREADYLOGGEDIN <-|nil|->",port) + return + end + local handle=self:loginUserIn(user,cid) -- binds the cid to username + self:send(ip,"!identity! LOGINGOOD <-|"..bin.ToStr(handle).."|->",port) + self.OnUserLoggedIn:Fire(user,cid,ip,port) + return + else + self:send(ip,"!identity! LOGINBAD <-|nil|->",port) + return + end + elseif cmd=="logout" then + self:loginUserOut(user) + self.OnClientClosed:Fire(self,"User logged out!",cid,ip,port) + elseif cmd=="sync" then + local dTable = loadstring("return "..(arg4 or "{}"))() + local handle = self:getUserDataHandle(self:userLoggedIn(cid)) + table.merge(handle,dTable) + elseif cmd=="pass" then + local user=arg1 + if self:_isRegistered(user) then + self.OnPasswordForgotten:Fire(arg1,cid) + self:send(ip,"!identity! PASSREQUESTHANDLED <-|NONE|->",port) + else + self:send(ip,"!identity! NOUSER <-|"..user.."|->",port) + end + end + end) + s.OnClientClosed:connect(function(self,reason,cid,ip,port) + self.OnUserLoggerOut:Fire(self,self:userLoggedIn(cid),cid,reason) + end) + end) + --Client Stuff + net.OnClientCreated:connect(function(c) + c.userdata={} + c.OnUserLoggedIn=multi:newConnection() + c.OnBadLogin=multi:newConnection() + c.OnUserAlreadyRegistered=multi:newConnection() + c.OnUserAlreadyLoggedIn=multi:newConnection() + c.OnUserRegistered=multi:newConnection() + c.OnNoUserWithName=multi:newConnection() + c.OnPasswordRequest=multi:newConnection() + c.OnUserRegisterRefused=multi:newConnection() + function c:logout() + self:send("!identity! logout 'NONE' 'NONE' 'NONE' <-|nil|->") + end + c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered + local cmd,arg1 = data:match("!identity! (%S-) <%-|(.+)|%->") + if cmd=="REGISTERED" then + self.OnUserAlreadyRegistered:Fire(self,arg1) + elseif cmd=="REGISTEREDGOOD" then + self.OnUserRegistered:Fire(self,arg1) + elseif cmd=="REGISTERREFUSED" then + self.OnUserRegisterRefused:Fire(self,arg1) + elseif cmd=="ALREADYLOGGEDIN" then + self.OnUserAlreadyLoggedIn:Fire(self,arg1) + elseif cmd=="LOGINBAD" then + self.OnBadLogin:Fire(self) + elseif cmd=="LOGINGOOD" then + local dTable=loadstring("return "..(arg1 or "{}"))() + table.merge(self.userdata,dTable) + self.OnUserLoggedIn:Fire(self,self.userdata) + elseif cmd=="SYNC" then + local dTable=loadstring("return "..(arg1 or "{}"))() + table.merge(self.userdata,dTable) + elseif cmd=="NOUSER" then + self.OnNoUserWithName:Fire(self,arg1) + elseif cmd=="PASSREQUESTHANDLED" then + self.OnPasswordRequest:Fire(self) + end + end) + function c:syncUserData() + self:send(string.format("!identity! sync 'NONE' 'NONE' 'NONE' <-|%s|->",bin.ToStr(dTable))) + end + function c:forgotPass(user) + self:send(string.format("!identity! pass '%s' 'NONE' 'NONE' <-|nil|->",user)) + end + function c:getUserDataHandle() + return self.userdata + end + function c:logIn(user,pass) + self:send(string.format("!identity! login '%s' '%s' 'NONE' <-|nil|->",user,net.hash(pass))) + end + function c:register(user,pass,nick,dTable) + if dTable then + self:send(string.format("!identity! register '%s' '%s' '%s' <-|%s|->",user,net.hash(pass),nick,bin.ToStr(dTable))) + else + self:send(string.format("!identity! register '%s' '%s' '%s' <-|nil|->",user,net.hash(pass),nick)) + end + end + end) +end +if net.autoInit then + net.identity:init() +end diff --git a/net/init.lua b/net/init.lua new file mode 100644 index 0000000..cd4ef7a --- /dev/null +++ b/net/init.lua @@ -0,0 +1,483 @@ +function string.trim(s) + local from = s:match"^%s*()" + return from > #s and "" or s:match(".*%S", from) +end +socket=require("socket") +net={} +net.Version={1,0,0} +net.OnServerCreated=multi:newConnection() +net.OnClientCreated=multi:newConnection() +net.loadedModules={} +net.autoInit=true +function net:registerModule(mod,version) + table.insert(self.loadedModules,mod) + net[mod]={} + if version then + net[mod].Version=version + else + net[mod].Version={1,0,0} + end +end +function net.getModuleVersion(ext) + if not ext then + return string.format("%d.%d.%d",net.Version[1],net.Version[2],net.Version[3]) + end + return string.format("%d.%d.%d",net[ext].Version[1],net[ext].Version[2],net[ext].Version[3]) +end +function net.resolveID(obj) + local num=math.random(10000000,99999999) + if obj[tostring(num)] then + return net.resolveID(obj) + end + obj.ids[tostring(num)]=true + return tostring(num) +end +function net.inList(list,dat) + for i,v in pairs(list) do + if v==dat then + return true + end + end + return false +end +function net.setTrigger(funcW,funcE) + multi:newTrigger(func) +end +-- UDP Stuff +function net:newServer(port,servercode) + local c={} + c.udp=assert(socket.udp()) + c.udp:settimeout(0) + c.udp:setsockname("*", port) + c.ips={} + c.Type="udp" + c.port=port + c.ids={} + c.servercode=servercode + c.bannedIPs={} + c.bannedCIDs={} + function c:setUpdateRate(n) + print("Not needed in a udp server!") + end + function c:banCID(cid) + table.insert(self.bannedCIDs,cid) + end + function c:banIP(ip) + table.insert(self.bannedIPs,cid) + end + function c:send(ip,data,port,cid) + if self.servercode then + cid=cid or self:CIDFrom(ip,port) + if not self.ips[cid] then + print("Can't determine cid from client... sending the client a new one!") + local cid=net.resolveID(self) + print("Sending unique cid to client: "..cid) + self.ips[cid]={ip,port,0,self.servercode==nil} + print(ip) + self.udp:sendto("I!"..cid,ip,port) + if self.servercode then + self.udp:sendto("S!",ip,port) + end + return + end + if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then + self.udp:sendto("BANNED CLIENT", ip, port or self.port) + elseif self.ips[cid][4] then + self.udp:sendto(data, ip, port or self.port) + elseif self.ips[cid][4]==false then + self.udp:sendto("Make sure your server code is correct!", ip, port) + end + else + self.udp:sendto(data, ip, port or self.port) + end + end + function c:pollClientModules(ip,port) + self:send(ip,"L!",port) + end + function c:CIDFrom(ip,port) + for i,v in pairs(self.ips) do + if(ip==v[1] and v[2]==port) then + return i + end + end + end + function c:sendAll(data) + for i,v in pairs(self.ips) do + self:send(v[1],data,v[2],i) + end + end + function c:sendAllBut(data,cid) + for i,v in pairs(self.ips) do + if i~=cid then + self:send(v[1],data,v[2],i) + end + end + end + function c:clientRegistered(cid) + return self.ips[cid] + end + function c:clientLoggedIn(cid) + if not self.clientRegistered(cid) then + return nil + end + return self.ips[cid][4] + end + function c:update() + local data,ip,port=self.udp:receivefrom() + if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then + print("We will ingore data from a banned client!") + return + end + if data then + if data:sub(1,4)=="pong" then + print("Recieved pong from: "..data:sub(5,-1)) + self.ips[data:sub(5,-1)][3]=os.clock() + elseif data:sub(1,2)=="S!" then + local cid=self:CIDFrom(ip,port) + if data:sub(3,-1)==self.servercode then + print("Servercode Accepted: "..self.servercode) + if self.ips[cid] then + self.ips[cid][4]=true + else + print("Server can't keep up! CID: "..cid.." has been skipped! Sending new CID to the client!") + local cid=net.resolveID(self) + print("Sending unique cid to client: "..cid) + self.ips[cid]={ip,port,0,self.servercode==nil} + print(ip) + self.udp:sendto("I!"..cid,ip,port) + if self.servercode then + self.udp:sendto("S!",ip,port) + end + end + else + self.udp:sendto("Make sure your server code is correct!", ip, port) + end + elseif data:sub(1,2)=="C!" then + self.OnDataRecieved:Fire(self,data:sub(11,-1),data:sub(3,10),ip,port) + elseif data:sub(1,2)=="E!" then + self.ips[data:sub(3,10)]=nil + obj.ids[data:sub(3,10)]=false + self.OnClientClosed:Fire(self,"Client Closed Connection!",data:sub(3,10),ip,port) + elseif data=="I!" then + local cid=net.resolveID(self) + print("Sending unique cid to client: "..cid) + self.ips[cid]={ip,port,os.clock(),self.servercode==nil} + print(ip) + self.udp:sendto("I!"..cid,ip,port) + if self.servercode then + self.udp:sendto("S!",ip,port) + end + elseif data:sub(1,2)=="L!" then + cid,cList=data:sub(3,10),data:sub(11,-1) + local list={} + for m,v in cList:gmatch("(%S-):(%S-)|") do + list[m]=v + end + self.OnClientsModulesList:Fire(list,cid,ip,port) + end + end + for cid,dat in pairs(self.ips) do + if not((os.clock()-dat[3])<65) then + self.ips[cid]=nil + self.OnClientClosed:Fire(self,"Client lost Connection: ping timeout",cid,ip,port) + end + end + end + c.OnClientsModulesList=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + c.OnPongRecieved=multi:newConnection() + c.OnClientClosed=multi:newConnection() + c.connectiontest=multi:newAlarm(30) + c.connectiontest.link=c + c.connectiontest:OnRing(function(alarm) + print("pinging clients!") + alarm.link:sendAll("ping") + alarm:Reset() + end) + multi:newLoop(function() + c:update() + end) + net.OnServerCreated:Fire(c) + return c +end + +function net:newClient(host,port,servercode,nonluaServer) + local c={} + c.ip=assert(socket.dns.toip(host)) + c.udp=assert(socket.udp()) + c.udp:setpeername(c.ip, port) + c.udp:settimeout(0) + c.cid="NIL" + c.lastPing=0 + c.Type="udp" + c.servercode=servercode + c.autoReconnect=true + function c:pollPing(n) + return not((os.clock()-self.lastPing)<(n or 60)) + end + function c:send(data) + self.udp:send("C!"..self.cid..data) + end + function c:sendRaw(data) + self.udp:send(data) + end + function c:getCID() + if self:IDAssigned() then + return self.cid + end + end + function c:close() + self:send("E!") + end + function c:IDAssigned() + return self.cid~="NIL" + end + function c:update() + local data=self.udp:receive() + if data then + if data:sub(1,2)=="I!" then + self.cid=data:sub(3,-1) + self.OnClientReady:Fire(self) + elseif data=="S!" then + self.udp:send("S!"..(self.servercode or "")) + elseif data=="L!" then + local mods="" + local m="" + for i=1,#net.loadedModules do + m=net.loadedModules[i] + mods=mods..m..":"..net.getModuleVersion(m).."|" + end + self.udp:send("L!"..self.cid..mods) + elseif data=="ping" then + self.lastPing=os.clock() + self.OnPingRecieved:Fire(self) + self.udp:send("pong"..self.cid) + else + self.OnDataRecieved:Fire(self,data) + end + end + end + function c:reconnect() + if not nonluaServer then + self.cid="NIL" + c.udp:send("I!") + end + end + c.pingEvent=multi:newEvent(function(self) return self.link:pollPing() end) + c.pingEvent:OnEvent(function(self) + if self.link.autoReconnect then + self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout! Attempting to reconnect...") + self.link:reconnect() + else + self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout!") + end + end) + c.pingEvent.link=c + c.OnPingRecieved=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + c.OnServerNotAvailable=multi:newConnection() + c.OnClientReady=multi:newConnection() + c.notConnected=multi:newFunction(function(self) + self:hold(3) + if self.link:IDAssigned()==false then + self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server") + end + end) + c.notConnected.link=c + if not nonluaServer then + c.udp:send("I!") + end + multi:newLoop(function() + c:update() + end) + multi:newJob(function() c.notConnected() end) + net.OnClientCreated:Fire(c) + return c +end +--TCP Stuff +function net:newTCPServer(port) + local c={} + c.tcp=assert(socket.bind("*", port)) + c.tcp:settimeout(0) + c.ip,c.port=c.tcp:getsockname() + c.ips={} + c.port=port + c.ids={} + c.bannedIPs={} + c.Type="tcp" + c.rMode="*l" + c.sMode="*l" + c.updaterRate=1 + function c:setUpdateRate(n) + self.updaterRate=n + end + function c:setReceiveMode(mode) + self.rMode=mode + end + function c:setSendMode(mode) + self.rMode=mode + end + function c:banCID(cid) + print("Function not supported on a tcp server!") + end + function c:banIP(ip) + table.insert(self.bannedIPs,cid) + end + function c:send(handle,data) + if self.sMode=="*l" then + handle:send(data.."\n") + else + handle:send(data) + end + end + function c:pollClientModules(ip,port) + self:send(ip,"L!",port) + end + function c:CIDFrom(ip,port) + print("Method not supported when using a TCP Server!") + return "CIDs in TCP work differently!" + end + function c:sendAll(data) + for i,v in pairs(self.ips) do + self:send(v,data) + end + end + function c:sendAllBut(data,cid) + for i,v in pairs(self.ips) do + if not(cid==i) then + self:send(v,data) + end + end + end + function c:clientRegistered(cid) + return self.ips[cid] + end + function c:clientLoggedIn(cid) + return self.ips[cid] + end + function c:update() + local client = self.tcp:accept(self.rMode) + if not client then return end + table.insert(self.ips,client) + client:settimeout(0) + --client:setoption('tcp-nodelay', true) + client:setoption('keepalive', true) + ip,port=client:getpeername() + if ip and port then + print("Got connection from: ",ip,port) + local updater=multi:newUpdater(skip) + updater:OnUpdate(function(self) + local data, err = self.client:receive(self.Link.rMode) + if err=="closed" then + for i=1,#self.Link.ips do + if self.Link.ips[i]==self.client then + table.remove(self.Link.ips,i) + end + end + self.Link.OnClientClosed:Fire(self.Link,"Client Closed Connection!",self.client,self.client,ip) + self:Destroy() + end + if data then + if net.inList(self.Link.bannedIPs,ip) then + print("We will ingore data from a banned client!") + return + end + self.Link.OnDataRecieved:Fire(self.Link,data,self.client,self.client,ip) + if data:sub(1,2)=="L!" then + cList=data + local list={} + for m,v in cList:gmatch("(%S-):(%S-)|") do + list[m]=v + end + self.Link.OnClientsModulesList:Fire(list,self.client,self.client,ip) + end + end + end) + updater:setSkip(self.updaterRate) + updater.client=client + updater.Link=self + end + end + c.OnClientsModulesList=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + c.OnClientClosed=multi:newConnection() + multi:newLoop(function() + c:update() + end) + net.OnServerCreated:Fire(c) + return c +end + +function net:newTCPClient(host,port) + local c={} + c.ip=assert(socket.dns.toip(host)) + c.port=post + c.tcp=socket.connect(c.ip,port) + if not c.tcp then + print("Can't connect to the server: no response from server") + return false + end + c.tcp:settimeout(0) + c.tcp:setoption('tcp-nodelay', true) + c.tcp:setoption('keepalive', true) + c.Type="tcp" + c.autoReconnect=true + c.rMode="*l" + c.sMode="*l" + function c:setReceiveMode(mode) + self.rMode=mode + end + function c:setSendMode(mode) + self.sMode=mode + end + function c:send(data) + if self.sMode=="*l" then + self.tcp:send(data.."\n") + else + self.tcp:send(data) + end + end + function c:sendRaw(data) + self.tcp:send(data) + end + function c:getCID() + return "No Cid on a tcp client!" + end + function c:close() + self.tcp:close() + end + function c:IDAssigned() + return true + end + function c:update() + local data=self.tcp:receive() + if data then + self.OnDataRecieved:Fire(self,data) + end + end + function c:reconnect() + self.ip=assert(socket.dns.toip(host)) + self.tcp=socket.connect(self.ip,self.port) + if not self.tcp then + print("Can't connect to the server: no response from server") + return + end + self.tcp:settimeout(0) + self.tcp:setoption('tcp-nodelay', true) + self.tcp:setoption('keepalive', true) + end + c.event=multi:newEvent(function(event) + return event.link:IDAssigned() + end) + c.event:OnEvent(function(event) + event.link.OnClientReady:Fire(event.link) + end) + c.event.link=c + c.OnClientReady=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + multi:newLoop(function() + c:update() + end) + net.OnClientCreated:Fire(c) + return c +end diff --git a/net/sft.lua b/net/sft.lua new file mode 100644 index 0000000..d1a2018 --- /dev/null +++ b/net/sft.lua @@ -0,0 +1,179 @@ +require("net") +--General Stuff +--[[ What this module does! +Adds + +]] +function io.fileExists(path) + g=io.open(path or '','r') + if path =='' then + p='empty path' + return nil + end + if g~=nil and true or false then + p=(g~=nil and true or false) + end + if g~=nil then + io.close(g) + else + return false + end + return p +end +net:registerModule("sft",{1,0,0}) +function net.sft:init() -- calling this initilizes the library and binds it to the servers and clients created + --Server Stuff + net.OnServerCreated:connect(function(s) + print("The sft(Simple File Transfer) Module has been loaded onto the server!") + if s.Type~="tcp" then + print("It is recomended that you use tcp to transfer files!") + end + s.transfers={} + s.OnUploadRequest=multi:newConnection() -- create a sft event + s.OnFileUploaded=multi:newConnection() -- create a sft event + s.OnDownloadRequest=multi:newConnection() + s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered + --First Lets make sure we are getting sft data + --filename,dat=data:match("!sft! (%S-) (%S+)") + local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)") + if cmd=="tstart" then + local rets=self.OnUploadRequest:Fire(self,cid,ip,port) + for i=1,#rets do + if rets[i][1]==false then + print("Server refused to accept upload request!") + self:send(ip,"!sft! CANTUPLOAD NIL NIL",port) + return + end + end + local ID,streamable=arg1:match("(.+)|(.+)") + local file,hash=arg2:match("(.+)|(.+)") + if streamable~="NIL" then + self.transfers[ID]={bin.stream(streamable,false),hash,file} + else + self.transfers[ID]={bin.new(""),hash,file} + end + return + elseif cmd=="transfer" then + if self.transfers[arg1]~=nil then + self.transfers[arg1][1]:tackE(bin.fromhex(arg2)) + --print(self.transfers[arg1][1]:getSize()) + end + return + elseif cmd=="tend" then + if self.transfers[arg1]~=nil then + if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then + self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!") + else + print("Hash Error!") + self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!") + end + self.transfers[arg1]=nil + end + return + end + local filename=cmd + local dat=arg1 + if filename==nil then return end + local rets=self.OnDownloadRequest:Fire(self,cid,ip,port) + for i=1,#rets do + if rets[i][1]==false then + print("Server refused to accept download request!") + self:send(ip,"!sft! CANTREQUEST NIL NIL",port) + return + end + end + if io.fileExists(filename) then + --Lets first load the file + local file=bin.stream(filename,false) + local size=file:getSize() + local pieceSize=512 + local pieces=math.ceil(size/pieceSize) + local step=multi:newStep(1,pieces) + step.TransferID=tostring(math.random(1000,9999)) + step.sender=self + step.ip=ip + step.port=port + step.pieceSize=pieceSize + step:OnStart(function(self) + self.sender:send(self.ip,"!sft! TSTART "..self.TransferID.."|"..dat.." "..filename.."|"..file:getHash(32),self.port) + end) + step:OnStep(function(pos,self) + self:hold(.01) + self.sender:send(self.ip,"!sft! TRANSFER "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos)),self.port) + end) + step:OnEnd(function(self) + self.sender:send(self.ip,"!sft! TEND "..self.TransferID.." NIL",self.port) + end) + else + self:send(ip,"!sft! CANTREQUEST NIL NIL",port) + end + end) + end) + --Client Stuff + net.OnClientCreated:connect(function(c) + c.transfers={} + c.OnTransferStarted=multi:newConnection() -- create a sft event + c.OnTransferFinished=multi:newConnection() -- create a sft event + c.OnFileRequestFailed=multi:newConnection() -- create a sft event + c.OnFileUploadFailed=multi:newConnection() -- create a sft event + c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered + --First Lets make sure we are getting sft data + local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)") + if cmd=="TSTART" then + local ID,streamable=arg1:match("(.+)|(.+)") + local file,hash=arg2:match("(.+)|(.+)") + if streamable~="NIL" then + self.transfers[ID]={bin.stream(streamable,false),hash,file} + else + self.transfers[ID]={bin.new(""),hash,file} + end + self.OnTransferStarted:Fire(self) + elseif cmd=="TRANSFER" then + self.transfers[arg1][1]:tackE(bin.fromhex(arg2)) + elseif cmd=="TEND" then + if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then + self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!") + else + print("Hash Error!") + self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!") + end + self.transfers[arg1]=nil + elseif cmd=="CANTREQUEST" then + self.OnFileRequestFailed:Fire(self,"Could not request the file for some reason!") + elseif cmd=="CANTUPLOAD" then + self.OnFileUploadFailed:Fire(self,"Could not upload the file for some reason!") + end + end) + function c:uploadFile(filename) + if io.fileExists(filename) then + local file=bin.stream(filename,false) + local size=file:getSize() + local pieceSize=512 + local pieces=math.ceil(size/pieceSize) + local step=multi:newStep(1,pieces) + step.TransferID=tostring(math.random(1000,9999)) + step.sender=self + step.pieceSize=pieceSize + step:OnStart(function(self) + self.sender:send("!sft! tstart "..self.TransferID.."|NIL "..filename.."|"..file:getHash(32)) + end) + step:OnStep(function(pos,self) + self:hold(.01) + self.sender:send("!sft! transfer "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos))) + end) + step:OnEnd(function(self) + print("Request done!") + self.sender:send("!sft! tend "..self.TransferID.." NIL") + end) + else + self.OnFileUploadFailed:Fire(self,filename,"File does not exist!") + end + end + function c:requestFile(filename) + self:send("!sft! "..filename.." NIL NIL NIL") + end + end) +end +if net.autoInit then + net.sft.init() +end diff --git a/parseManager/AICM.lua b/parseManager/AICM.lua new file mode 100644 index 0000000..23496fa --- /dev/null +++ b/parseManager/AICM.lua @@ -0,0 +1,37 @@ +AICM={} +AICM.functions={ + getAICMVersion=function(self) + return "1.0.0" + end, +} +function AICM:InitSyntax(obj,name) + obj:debug("Now using the Artificial Intelligence Communication module!") + obj.OnExtendedBlock(self.blockModule) + obj.OnCustomSyntax(self.syntaxModule) + obj:define(self.functions) +end +AICM.syntaxModule=function(self,line) + pVars,mStr=line:match("p%((.-)%)(.+)") + if pVars then + local vRef,vars=pVars:match("(.-):(.+)") + if vars:find(",") then + vars={unpack(vars:split(","))} + else + vars={vars} + end + tab={self:varExists(vRef):match(mStr)} -- self:varExists allows for all internal structures to just work + for i=1,#tab do + if vars[i] then + self._variables[vars[i]]=tab[i] + end + end + self:p() -- requried to progress the script + return { + text=line, + Type="AICMModule" + } + end +end +AICM.blockModule=function(obj,name,t,chunk,filename) + -- +end diff --git a/parseManager/EBIM.lua b/parseManager/EBIM.lua new file mode 100644 index 0000000..08ac193 --- /dev/null +++ b/parseManager/EBIM.lua @@ -0,0 +1,71 @@ +EBIM={} +EBIM.functions={ + getEBIMVersion=function(self) + return "1.0.0" + end, +} +EBIM.registry={} +function EBIM:registerEBlock(name,func) + self.registry[name]=func +end +function EBIM:InitSyntax(obj,name) + obj:debug("Now using the Extended Block Interface module!") + obj.OnExtendedBlock(self.blockModule) + obj.OnCustomSyntax(self.syntaxModule) + obj:define(self.functions) +end +EBIM.syntaxModule=function(self,line) + local cmd,args=line:match("(.-) (.+):") + if cmd then + local goal=nil + local _tab={} + for i=self.pos+1,#self._cblock do + if self._cblock[i]=="end"..cmd then + goal=i + break + else + table.insert(_tab,self._cblock[i]) + end + end + if goal==nil then + self:pushError("'end"..cmd.."' Expected to close '"..cmd.."'") + end + if EBIM.registry[cmd] then + EBIM.registry[cmd](self,args,_tab) + self.pos=goal+1 + else + self:pushError("Unknown command: "..cmd) + end + return { + Type="EBIM-Data", + text=cmd.." Block" + } + else + return + end +end +EBIM.blockModule=function(obj,name,t,chunk,filename) + --print(">: ",obj,name,t,chunk,filename) +end +EBIM:registerEBlock("string",function(self,args,tab) + local str={} + for i=1,#tab do + table.insert(str,tab[i]) + end + self:setVariable(args,table.concat(str,"\n")) +end) +EBIM:registerEBlock("list",function(self,args,tab) + local str={} + for i=1,#tab do + table.insert(str,self:varExists(tab[i])) + end + self:setVariable(args,str) +end) +EBIM:registerEBlock("dict",function(self,args,tab) + local str={} + for i=1,#tab do + local a,b=tab[i]:match("(.-):%s*(.+)") + str[a]=self:varExists(b) + end + self:setVariable(args,str) +end) diff --git a/parseManager/bytecode.lua b/parseManager/bytecode.lua new file mode 100644 index 0000000..26fb46f --- /dev/null +++ b/parseManager/bytecode.lua @@ -0,0 +1,44 @@ +-- In an attempt to speed up my library I will use a virtual machine that runs bytecode +compiler={} +compiler.cmds={ -- list of all of the commands + EVAL="\01", -- evaluate + SPLT="\02", -- split + TRIM="\03", -- trim + VEXT="\04", -- variable exists + ILST="\05", -- is a list + LSTR="\06", -- load string + FCAL="\07", -- Function call + SVAR="\08", -- set variable + LOAD="\09", -- load file + LAOD="\10", -- _load file + DEFN="\11", -- define external functions + HCBK="\12", -- Has c Block + CMBT="\13", -- combine truths + SETB="\14", -- set block + STRT="\15", -- start + PERR="\16", -- push error + PROG="\17", -- progress + PHED="\18", -- parse header + SSLT="\19", -- split string + NEXT="\20", -- next + -- Needs refining... One step at a time right! +} +function compiler:compile(filename) -- compiles the code into bytecode + -- First we load the code but don't run it + local engine=parseManager:load(filename) + -- This captures all of the methods and important info. This also ensures that the compiler and interperter stay in sync! + local bytecodeheader=bin.new() -- header will contain the order of blocks and important flags + local bytecode=bin.newDataBuffer() -- lets leave it at unlimited size because we don't know how long it will need to be + local functions={} -- will be populated with the important methods that must be preloaded + local prebytecode={} -- this contains bytecode that has yet to be sterilized + for blockname,blockdata in pairs(engine._chunks) do + -- lets get some variables ready + local code,_type,nextblock,filename=blockdata[1],blockdata[2],blockdata.next,blockdata.file + -- note nextblock may be nil on 2 condidions. The first is when the leaking flag is disabled and the other is when the block in question was the last block defined + local lines=bin._lines(code) + print("\n["..blockname.."]\n") + for i=1,#lines do + print(lines[i]) + end + end +end diff --git a/parseManager/init.lua b/parseManager/init.lua new file mode 100644 index 0000000..af90212 --- /dev/null +++ b/parseManager/init.lua @@ -0,0 +1,1277 @@ +function trim(s) + return s:match'^()%s*$' and '' or s:match'^%s*(.*%S)' +end +parseManager={} +parseManager._VERSION={1,0,0} +dialogueManager=parseManager -- for backwards purposes +parseManager.OnExtendedBlock=multi:newConnection(true) -- true protects the module from crashes +parseManager.OnCustomSyntax=multi:newConnection(true) -- true protects the module from crashes +function string:split( inSplitPattern, outResults ) + if not outResults then + outResults = {} + end + local theStart = 1 + local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) + while theSplitStart do + table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) ) + theStart = theSplitEnd + 1 + theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) + end + table.insert( outResults, string.sub( self, theStart ) ) + return outResults +end +function parseManager:debug(txt) + if self.stats.debugging then + self._methods:debug(txt) + end +end +function parseManager.split(s,pat) + local pat=pat or "," + local res = {} + local start = 1 + local state = 0 + local c = '.' + local elem = '' + for i = 1, #s do + c = s:sub(i, i) + if state == 0 or state == 3 then -- start state or space after comma + if state == 3 and c == ' ' then + state = 0 -- skipped the space after the comma + else + state = 0 + if c == '"' or c=="'" then + state = 1 + elem = elem .. '"' + elseif c=="[" then + state = 1 + elem = elem .. '[' + elseif c == pat then + res[#res + 1] = elem + elem = '' + state = 3 -- skip over the next space if present + else + elem = elem .. c + end + end + elseif state == 1 then -- inside quotes + if c == '"' or c=="'" then --quote detection could be done here + state = 0 + elem = elem .. '"' + elseif c=="]" then + state = 0 + elem = elem .. ']' + elseif c == '\\' then + state = 2 + else + elem = elem .. c + end + elseif state == 2 then -- after \ in string + elem = elem .. c + state = 1 + end + end + res[#res + 1] = elem + return res +end +parseManager._chunks={} +parseManager._cblock={} +parseManager._cblockname="" +parseManager._pos=1 +parseManager._labels={ + -- {chunkname,pos} +} +parseManager.stats={ + leaking=false, + debugging=false, + topdown=true, + forseelabels=true, +} +parseManager._types={} +parseManager.__index=parseManager +parseManager._variables={__TYPE="ENV"} +parseManager.defualtENV=parseManager._variables +function parseManager:varExists(var) + if var==nil or var=="nil" then return end + if type(var)=="userdata" then return var end + if tonumber(var) then + return tonumber(var) + end + local aa,bb=var:match("(.-)%[\"(.-)\"%]") + if aa and bb then + return self.defualtENV[aa][bb] + end + if var:find('"') then + return self:parseHeader(var:sub(2,-2),self.defualtENV) + end + if var:find("%[%]") then + return {} + end + if var:sub(1,1)=="[" and var:sub(-1,-1)=="]" then + local list=var:match("[(.+)]") + if not list then + self:pushError("Invalid List assignment!") + end + local t=list:split(",") + local nlist={} + local a=":)" + for i=1,#t do + a=self:varExists(t[i]) + if a then + table.insert(nlist,a) + end + end + return nlist + end + if var=="true" then + return true + elseif var=="false" then + return false + end + local a,b=var:match("(.-)%[(.-)%]") + if a and b then + if type(self.defualtENV[a])=="table" then + if b=="-1" then + return self.defualtENV[a][#self.defualtENV[a]] + elseif b=="#" then + return self.defualtENV[a][math.random(1,#self.defualtENV[a])] + else + return self.defualtENV[a][tonumber(b) or self:varExists(b)] + end + end + if type(self.defualtENV[var])=="table" then + return self.defualtENV[var] + end + end + return self.defualtENV[var] or var -- if all tests fail, just pass on the data for the function to manage +end +function parseManager:isList(var) + local a,b=var:match("(.-)%[(.-)%]") + if not a or b then return end + if type(self.defualtENV[a])=="table" then + if b=="-1" then + return self.defualtENV[a][#self.defualtENV[a]] + else + return self.defualtENV[a][tonumber(b)] + end + end + return +end +function parseManager:loadString(data) + self:_load(bin.new(data),self) +end +parseManager.loadeddata={} +parseManager.envs={} +parseManager._methods={ + getLength=function(self,list) + return #(self:varExists(list) or {}) + end, + emptyList=function(self) + return {} + end, + DEBUG=function(self,text) + print(text) + end, + DIS=function(self,var) + print(var) + end, + SEED=function(self,n) + math.randomseed(tonumber(self:varExists(n) or n) or os.time()) + end, + delElem=function(self,l,i) + table.remove(l,i) + end, + addElem=function(self,l,d,i) + table.insert(l,(i or -1),d) + return l + end, + RANDOM=function(self,v1,v2) + if v1 then + return math.random(1,v1) + elseif v1 or v2 then + return math.random(tonumber(v1),tonumber(v2)) + else + return math.random() + end + end, + CALC=function(self,eq) + return self:evaluate(eq) + end, + GOTOV=function(self,label) + print(self:varExists(label)) + self._methods.GOTO(self,self:varExists(label)) + end, + GOTO=function(self,label) + label=label:gsub("-","") + if label=="__LASTGOTO" then + self:setBlock(self._labels.__LASTGOTO[1]) + self.pos=self._labels[label][2] + return true + end + --search current block for a label + if self.pos==nil then + error("Attempt to load a non existing block from the host script!") + end + for i=self.pos,#self._cblock do + local line=self._cblock[i] + local labeltest=line:match("::(.-)::") + if labeltest==label then + self._labels["__LASTGOTO"]={self._cblockname,self.pos} + self.pos=i + return true + end + end + --search for saved labels + if self._labels[label] then + self._labels["__LASTGOTO"]={self._cblockname,self.pos} + self:setBlock(self._labels[label][1]) + self.pos=self._labels[label][2] + return true + end + --search other blocks if enabled for labels + if self.stats.forseelabels then + for i,v in pairs(self._chunks) do + local chunks=bin._lines(v[1]) + for p=1,#chunks do + local line=chunks[p] + local labeltest=line:match("::(.-)::") + if labeltest==label then + self._labels["__LASTGOTO"]={self._cblockname,self.pos} + self:setBlock(i) + self.pos=p-1 + return true + end + end + end + end + if self.stats.forseelabels then + if self._methods.GOTOV(self,label) then return end + end + self:pushError("Attempt to goto a non existing label! You can only access labels in the current scope! Or labels that the code has seen thus far! "..label.." does not exist as a label!") + end, + QUIT=function() + os.exit() + end, + EXIT=function(self) + self.pos=math.huge + end, + TYPE=function(self,val) + return type(val) + end, + SAVE=function(self,filename) + if trim(filename)=="" then filename="saveData.sav" end + local t=bin.new() + t:addBlock(self.defualtENV) + t:addBlock(self._cblockname) + t:addBlock(self.pos) + t:addBlock(self._labels) + t:tofile(filename) + end, + UNSAVE=function(self,filename) + if trim(filename)=="" then filename="saveData.sav" end + self.defualtENV={} + os.remove(filename) + end, + RESTORE=function(self) + if not(self.loadeddata.load) then self:pushError("A call to RESTORE without calling LOAD") end + self.defualtENV=self.loadeddata:getBlock("t") + self:setBlock(self.loadeddata:getBlock("s")) + self.pos=self.loadeddata:getBlock("n") + self._labels=self.loadeddata:getBlock("t") + end, + LOAD=function(self,filename) + print(filename) + if not filename then filename="saveData.sav" end + if io.fileExists(filename) then + self.loadeddata=bin.load(filename) + return 1 + end + return 0 + end, + JUMP=function(self,to) + self:setBlock(to) + end, + SKIP=function(self,n) + self.pos=self.pos+tonumber(n) + end, + PRINT=function(self,text) print(text) end, + TRIGGER=function(self,to) + self:setBlock(to) + end, + COMPARE=function(self,t,v1,v2,trueto,falseto) -- if a blockname is __STAY then it will continue on + if t=="=" or t=="==" then + if v1==v2 then + self:setBlock(trueto) + else + self:setBlock(falseto) + end + elseif t==">=" then + if v1>=v2 then + self:setBlock(trueto) + else + self:setBlock(falseto) + end + elseif t=="<=" then + if v1<=v2 then + self:setBlock(trueto) + else + self:setBlock(falseto) + end + elseif t==">" then + if v1>v2 then + self:setBlock(trueto) + else + self:setBlock(falseto) + end + elseif t=="<" then + if v1"..a + end) + local choicetest=line:find("<$") or line:find("^<") + local lasttest=line:match("^\"(.+)\"$") + local labeltest=line:match("::(.-)::") + local var,list=line:match("([%w_]-)=%[(.+)%]") + local assignA,assignB=line:match("(.-)=(.+)") + local cond,f1,f2=line:match("^if%s*(.-)%s*then%s*([%w-%(%)]-)%s*|%s*([%w-%(%)]*)") + if choicetest then + local c=self._chunks[self._cblockname][1] + local test=bin.new(c:match("\"<(.-)>")) + test:fullTrim(true) + local header=line:match("\"(.-)\"<") + local stuff=test:lines() + local cho,met={},{} + for i=1,#stuff do + local a1,a2=stuff[i]:match("\"(.-)\" (.+)") + a1=tostring(self:parseHeader(a1,env)) + table.insert(cho,a1) + table.insert(met,a2) + end + return { + Type="choice", + text=tostring(self:parseHeader(header,env)), + choices=cho, + methods=met, + blocktype=self._chunks[self._cblockname][2] + } + elseif cond and f1 and f2 then + conds={["andors"]={}} + mtc="" + for a,b in cond:gmatch("(.-)([and ]+[or ]+)") do + b=b:gsub(" ","") + mtc=mtc..".-"..b + v1,c,v2=a:match("(.-)%s*([<>!~=]+)%s*(.+)") + table.insert(conds,{v1,c,v2}) + table.insert(conds.andors,b) + end + a=cond:match(mtc.."%s*(.+)") + v1,c,v2=a:match("(.-)%s*([<>!~=]+)%s*(.+)") + table.insert(conds,{v1,c,v2}) + truths={} + for i=1,#conds do + conds[i][1]=conds[i][1]:gsub("\"","") + conds[i][3]=conds[i][3]:gsub("\"","") + if conds[i][2]=="==" then + table.insert(truths,tostring((self:varExists(conds[i][1]) or conds[i][1]))==tostring((self:varExists(conds[i][3]) or conds[i][3]))) + elseif conds[i][2]=="!=" or conds[i][2]=="~=" then + table.insert(truths,tostring((self:varExists(conds[i][1]) or conds[i][1]))~=tostring((self:varExists(conds[i][3]) or conds[i][3]))) + elseif conds[i][2]==">=" then + table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))>=tonumber((self:varExists(conds[i][3]) or conds[i][3]))) + elseif conds[i][2]=="<=" then + table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))<=tonumber((self:varExists(conds[i][3]) or conds[i][3]))) + elseif conds[i][2]==">" then + table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))>tonumber((self:varExists(conds[i][3]) or conds[i][3]))) + elseif conds[i][2]=="<" then + table.insert(truths,tonumber((self:varExists(conds[i][1]) or conds[i][1]))])(.+)") + if d then + if d=="<-" then + self:setVariable(assignA,self.defualtENV[_env][vv]) + self:p() + return { + Type="assignment", + var=assignA, + value=assignB, + env=true, + text=assignA.."="..assignB + } + elseif d=="->" then + self.defualtENV[_env][assignA]=self:varExists(vv) + self:p() + return { + Type="assignment", + var=assignA, + value=assignB, + env=true, + text=assignA.."="..assignB + } + end + end + local a1,a2=parseManager.split(assignA),parseManager.split(assignB) + for i=1,#a1 do + local a=self._methods.CALC(self,a2[i]) + if a then + a2[i]=a + end + local t=tonumber(a2[i]) + if not t then + t=a2[i] + end + env[a1[i]]=t + end + self:p() + return { + Type="assignment", + var=assignA, + value=assignB, + text=assignA.."="..assignB + } + else + local rets=self.OnCustomSyntax:Fire(self,line) + for i=1,#rets do + if type(rets[i][1])=="table" then + return rets[i][1] + else + return { + Type="unknown", + text=line + } + end + end + self:p() + return { + Type="unknown", + text=line + } + end +end +function parseManager:RunCode(code,entry,sel,env) -- returns an env or selectVarName + local file = bin.new("ENTRY "..(entry or "START").."\n"..code) + local run=parseManager:load(file) + run._methods = self._methods + run.defualtENV=self.defualtENV + run.defualtENV=self.defualtENV + for i,v in pairs(env or {}) do + run.defualtENV[i]=v + end + local t=run:start() + while true do + if t.Type=="text" then + print(t.text) + t=run:next() + elseif t.Type=="condition" then + t=run:next() + elseif t.Type=="assignment" then + t=run:next() + elseif t.Type=="label" then + t=run:next() + elseif t.Type=="method" then + t=run:next() + elseif t.Type=="choice" then + t=run:next(nil,math.random(1,#t.choices),nil,t) + elseif t.Type=="end" then + if t.text=="leaking" then -- go directly to the block right under the current block if it exists + t=run:next() + else + return (run.defualtENV[sel] or run.defualtENV) + end + elseif t.Type=="error" then + error(t.text) + else + t=run:next() + end + end +end +parseManager.symbols={} -- {sym,code} +function parseManager:registerSymbol(sym,code) + self.symbols[#self.symbols+1]={sym,code} +end +function parseManager:populateSymbolList(o) + local str="" + for i=1,#self.symbols do + str=self.symbols[i][1]..str + end + return str +end +function parseManager:isRegisteredSymbol(o,r,v) + for i=1,#self.symbols do + if self.symbols[i][1]==o then + return parseManager:RunCode(self.symbols[i][2],"CODE","ret-urn",{["l"]=r,["r"]=v,["mainenv"]=self.defualtENV}) + end + end + return false --self:pushError("Invalid Symbol "..o.."!") +end +function parseManager:evaluate(cmd,v) + v=v or 0 + local loop + local count=0 + local function helper(o,v,r) + if type(v)=="string" then + if v:find("%D") then + v=self:varExists(v) + end + end + if type(r)=="string" then + if r:find("%D") then + r=self:varExists(r) + end + end + local r=tonumber(r) or 0 + local gg=self:isRegisteredSymbol(o,r,v) + if gg then + return gg + elseif o=="+" then + return r+v + elseif o=="-" then + return r-v + elseif o=="/" then + return r/v + elseif o=="*" then + return r*v + elseif o=="^" then + return r^v + end + end + for i,v in pairs(math) do + cmd=cmd:gsub(i.."(%b())",function(a) + a=a:sub(2,-2) + if a:sub(1,1)=="-" then + a="0"..a + end + return v(self:evaluate(a)) + end) + end + cmd=cmd:gsub("%b()",function(a) + return self:evaluate(a:sub(2,-2)) + end) + for l,o,r in cmd:gmatch("(.*)([%+%^%-%*/"..self:populateSymbolList().."])(.*)") do + loop=true + count=count+1 + if l:find("[%+%^%-%*/]") then + v=self:evaluate(l,v) + v=helper(o,r,v) + else + if count==1 then + v=helper(o,r,l) + end + end + end + if not loop then return self:varExists(cmd) end + return v +end +parseManager.constructType=function(self,name,t,data,filename) + if t~="construct" then return end + --print(name,t,"[CODE]{"..data.."}") + self:registerSymbol(name,"[CODE]{"..data.."}") +end +-- Let's add function +Stack = {} +function Stack:Create() + local t = {} + t._et = {} + function t:push(...) + if ... then + local targs = {...} + for _,v in ipairs(targs) do + table.insert(self._et, v) + end + end + end + function t:pop(num) + local num = num or 1 + local entries = {} + for i = 1, num do + if #self._et ~= 0 then + table.insert(entries, self._et[#self._et]) + table.remove(self._et) + else + break + end + end + return unpack(entries) + end + function t:getn() + return #self._et + end + function t:list() + for i,v in pairs(self._et) do + print(i, v) + end + end + return t +end +parseManager.funcstack=Stack:Create() +parseManager:define{ + __TRACEBACK=function(self) -- internal function to handle function calls + local t=self.funcstack:pop() + self:setBlock(t[1]) + self.pos=t[2] + -- We finished the function great. Lets restore the old env + self._methods.setENV(self,t[3]) + end +} +parseManager.funcType=function(link,name,t,data,filename) + local test,args=t:match("(function)%(*([%w,]*)%)*") + if not test then return false end + local vars={} + if args~="" then + for k, v in ipairs(parseManager.split(args)) do + table.insert(vars,v) + end + -- Time to collect local vars to populate we will use these below + end + link._chunks[name][1]=link._chunks[name][1].."\n__TRACEBACK()" + local func=function(self,...) + -- Here we will use the vars. First lets capture the args from the other side + local args={...} + -- Here we will play a matching game assigning vars to values. This cannot be done yet... + -- Now we have to change the enviroment so function vars are local to the function. + -- Also we need functions to be able to access the globals too + -- Now we invoke the createnv method + local env=self._methods.createENV(self) + -- A little messy compared to how its done within the interpreted language + -- Now we need a copy of the previous Env + -- We then invoke getEnv method + local lastEnv=self._methods.getENV(self) + -- Great now we have a new enviroment to play with and the current one + -- Next we need to store the current one somewhere + self.funcstack:push({self._cblockname,self.pos,lastEnv}) + -- We use a stack to keep track of function calls. Before I tried something else and it was a horrible mess + -- Stacks make it real nice and easy to use. We store a bit of data into the stack to use later + if self.funcstack:getn()>1024 then self:pushError("Stack Overflow!") end + -- Throw an error if the stack reaches 1024 elements. We don't want it to go forever and odds are neither does the user + -- Lets set that new env and prepare for the jump. To do this we invoke setEnv + self._methods.setENV(self,env) + -- Now lets play match making + for i=1,#vars do + self:setVariable(vars[i],args[i]) -- this method defualts to the current env + end + -- We are ready to make the jump with our stored data + self._methods.JUMP(self,name) + -- we need to be able to catch returns... This is where things get tricky. + -- We need a way to run the other code while also waiting here so we can return data + -- What we can do is return a reference to the enviroment and from there you can take what you want from the function + -- This is a really strange way to do things, but whats wrong with different + return env + end + link._methods[name]=func +end +parseManager.OnExtendedBlock(parseManager.funcType) +parseManager.constructType=function(link,name,t,data,filename) + local test,args=t:match("(construct)%(*([%w,]*)%)*") + if not test then return false end + local vars={} + if args~="" then + for k, v in ipairs(parseManager.split(args)) do + table.insert(vars,v) + end + end + link._chunks[name][1]=link._chunks[name][1].."\n__TRACEBACK()" + local func=function(self,...) + local args={...} + local env=self._methods.createENV(self) + local lastEnv=self._methods.getENV(self) + self.funcstack:push({self._cblockname,self.pos,lastEnv}) + if self.funcstack:getn()>1024 then self:pushError("Stack Overflow!") end + self._methods.setENV(self,env) + for i=1,#vars do + self:setVariable(vars[i],args[i]) + end + self._methods.JUMP(self,name) + return env + end + link._methods[name]=func +end +parseManager.OnExtendedBlock(parseManager.constructType) diff --git a/parseManager/interpreter.lua b/parseManager/interpreter.lua new file mode 100644 index 0000000..e4a5b84 --- /dev/null +++ b/parseManager/interpreter.lua @@ -0,0 +1,10 @@ +engine={} +function engine:init(bytecodeFile) + self.code=bin.load(bytecodeFile).data +end +--[[OP-CODES + +]] +function engine:run(assessors) + -- +end diff --git a/structure.dat b/structure.dat new file mode 100644 index 0000000..f19efec --- /dev/null +++ b/structure.dat @@ -0,0 +1,233 @@ +ENABLE forseeLabels -- allows you to jump to labels in other blocks if omitted what i am doing right now is impossible +[Functions]{--Allows choices to continue where they left off + ::FUNCTION:: + "We are now in the function" + "We can run tests using the relitiave __SKIP# handle set variables and do some things" + COMPARE(=,name,Ryan,__STAY,__SKIP+2) + "Name already set" + GOTO(__LASTGOTO) + name="Ryan" -- new update allows for setting variables like this + "Name is now set" + GOTO(__LASTGOTO) +} +[START_]{ + "Lets call a method that proccesses stuff for us than returns to the position we want" + "Look at variable name: $name$" + GOTO(FUNCTION) -- __LASTGOTO that the goto in the other block refers to + "Now out of the function" + "Look at variable name now: $name$" + "Now the next line will call the method again" + GOTO(FUNCTION) -- the new __LASTGOTO + "Here" + "Note when doing GOTO(__LASTGOTO) the previous __LASTGOTO is not changed!!!" + -- Note: Labels are saved when using the save method as well!!! + "Which means a loop can be made by doing GOTO(__LASTGOTO)" + GOTO(__LASTGOTO) +} +[CONFIG]{ + SAVE("tests.sav") + money=10 + num=math.sqrt(100)+15 + "$num$" + "$a$" + EXIT() -- forces an exit out of the code + COMPARE(=,num,30,-here-,__STAY) -- __LASTGOTO also applies to here as well when using + "$num$ not equal 30" + "test2" +} +[UNNAMEDBLOCK]{ + ::here:: + "It is equal" + GOTO(__LASTGOTO) +} +[LOOP]{ + count=0 + ::loop:: + count=count+1 + "Loop# $count$ | $list$" -- Note if JUMP(-end-) of GOTO(end) is called here, then it will goto the ::end:: closest. + --[[ The search order is as follows + 1. Check if label is __LASTGOTO + 2. Check if label is within current block + 3. Check for labels that were already seen + 4. Search other blocks for labels]] + GOTO(-loop-) + ::end:: + "You wont reach me lol" +} +[THREAD]{ + --vals=vals+1 + --"Value of vals: $vals$" + setText(disp,vals) + sleep(1) + "1"< + "2" JUMP(T1) + "3" JUMP(T2) + "4" JUMP(T3) + > +} +[T1]{ + vals="test1" + JUMP(THREAD) +} +[T2]{ + vals="test2" + JUMP(THREAD) +} +[T3]{ + vals="test3" + JUMP(THREAD) +} + +[FORLOOP]{ + count=0 -- you got to initlize variables before use + ::forloop::-- this can eaisly be adapted into a while loop by messing with the COMPARE method + COMPARE(>=,count,10,-end-,__STAY) + count=count+1 + "Loop# $count$" + GOTO(forloop) + ::end:: + "Out of for loop" + "Note if JUMP cannot find a block it will look for a label! if a block and label have the same name then do JUMP(-labelname-) instead of JUMP(labelname)" + "Choice Test"< + "test1 (inf loop)" JUMP(-loop-) -- label and block in this case have different names, so no need to do -labelname- I did it any way lol + "test 2 (forloop)" JUMP(FORLOOP) -- block + "test 3 (new syntax)" JUMP(SYNTAX) + > +} +[SYNTAX]{ + -- lets try doing lists! + num=0 -- set num to 0 + ind=2 + ind1=1 + list=["Ryan","Mary","Amy","Bob","Billy",num] -- a list :) NOTE: list's indexces start at 1 not 0!!! + --lets play with these a bit + SEED() + "Element 1 in list is: $list[1]$" -- display the first element in the list + "Random name1: $list$" -- if the object is a list and you want a random element do the same as normal varables + "Random name2: $list$" -- if the object is a list and you want a random element do the same as normal varables + "Random name3: $list$" -- if the object is a list and you want a random element do the same as normal varables + "Last element in list is $list[-1]$" -- the last element on the list + --using lists outside of text streams + elem1=list[ind1] -- varables can be used here as well + "$elem1$" + lastelem=list[-1] + "$lastelem$" + "Elem2: $list[ind]$" -- variables can also be used here as well, ind is equal to 2 + delElem(list,2)-- deletes the first element of the list, list + "Elem2: $list[2]$" + addElem(list,"CANDY!!!",2) -- adds an element to list at position i. i is optional! + "Elem2: $list[2]$" + count=0 + test=RANDOM() + len=getLength(list) + "Length: $len$" + "Choice Test"< + "test 1 (loop test)" JUMP(-loop-) -- label and block in this case have different names, so no need to do -labelname- I did it any way lol + "test 2 ($test$)" JUMP(FORLOOP) -- block + "test 3 (new syntax)" JUMP(SYNTAX) + > +} +[TRUE]{ + "true" + "Choice Test"< + "test 1 (loop test)" JUMP(SAYHI) -- label and block in this case have different names, so no need to do -labelname- I did it any way lol + "test 2 ($test$)" JUMP(SAYBYE) -- block + "test 3 (new syntax)" JUMP(SYNTAX) + > +} +[FALSE]{ + "false" + "Choice Test"< + "test 1 (loop test)" JUMP(-loop-) -- label and block in this case have different names, so no need to do -labelname- I did it any way lol + "test 2 ($test$)" JUMP(FORLOOP) -- block + "test 3 (new syntax)" JUMP(SYNTAX) + > +} +[SAYHI]{ + "HI!!!" + JUMP(SAYBYE) +} +[SAYBYE]{ + "BYE!!!" + EXIT() +} +[CONDITIONS]{ + "Lets play with BG" + "Lets Go!" + BG("fire.jpg") + "Great that works, now for Objects!" + test=__workspace:newItem("","fire.jpg","",0,0,300,200) + "Now lets play around with the actor a bit" + test:setText("Hello!") + "Now lets make it have an image too" + "Lets make it draggable" + makeDraggable(test,"l") + "Lets play with animations!" + "First we create an animation object..." + "Boom!" + anim=createAnimation("loading",.05,0,0,300,300) + "Lets Center the object!" + centerXY(anim) + "Now for audio!" + test=loadAudio("test.mp3") + "It's loaded! Lets play it!" + playAudio(test) + "Testing direct method calling... (We are pausing the animation dont worry it did not freeze :P)" + anim:Pause() -- added interface to directly call methods on objects Woot!!! + "Did it pause?" + "Now we may want to stop the audio..." + "Done" + stopAudio(test) + "lets Resume the anim" + anim:Resume() + "Lets experiment with conditions: if var1==var2 and var3!=var4 or 4<5 then MethodTrue|MethodFalse" + "Lets set name to Ryan" + name="Ryan" + "name is now $name$" + if name=="Ryan" and name!="bob" then JUMP(TRUE)|JUMP(FALSE) +} +[CODE:function()]{ + "Within a method" + test=15 -- lets set a variable here + "Does this block" + "Now time to nest" + TESTFunc() + "Then when we are done" + "We go back to where we were called :)" +} +[TESTFunc:function()]{ + "testing nested function calls" +} +[CODE2:function(button,self)]{ + "Called in a thread" + "$button$ mouse button pressed!" +} +[COLORThread]{ + r=RANDOM(255) + b=RANDOM(255) + g=RANDOM(255) + item:setColor(r,b,g) + sleep(1) + JUMP(COLORThread) +} +[DIRECT]{ -- this is a test of direct method calling of objects + BG("fire.jpg") + test=loadAudio("test.mp3") + playAudio(test) + "steps?" + item=__workspace:newTextLabel("Hello",0,0,100,30) + "Is there an item?" + "Lets change the text" + item:setText("Hello2") + "Lets change colors" + item:setColor(23,56,132) + "Lets test inhretance" + newThread(COLORThread) + item2=item:newTextButton("X",0,0,20,20) + item2:OnReleased(CODE2) + "Did it work?" + "Lets call a custom method!" + --CODE() -- the block CODE can now be called as a method + "What happened: $test$" + "And with that it works" +} \ No newline at end of file diff --git a/test.aac b/test.aac new file mode 100644 index 0000000..18836ce Binary files /dev/null and b/test.aac differ diff --git a/test.jpg b/test.jpg new file mode 100644 index 0000000..6951cc4 Binary files /dev/null and b/test.jpg differ diff --git a/test.lua b/test.lua new file mode 100644 index 0000000..8f760f8 --- /dev/null +++ b/test.lua @@ -0,0 +1,58 @@ +package.path=package.path..";?/init.lua" +require("Libs/bin") +require("Libs/Multimanager") +require("dialogueManager") +test=dialogueManager:load("Tests.dmf") +t=test:start()-- start the reading +while true do-- working on saving and loading of data + if t.Type=="text" then + if test.stats.reading then + local a=t.text:find(":") + if a then + if t.text=="..." then + speak(t.text:sub(1,a-1).." Didn't say a word!") + else + speak(t.text:sub(1,a-1).." says: "..t.text:sub(a+1,-1)) + end + else + speak(t.text) + end + else + io.write(t.text) + io.read() + end + t=test:next() + elseif t.Type=="condition" then + t=test:next() + elseif t.Type=="assignment" then + t=test:next() + elseif t.Type=="label" then + t=test:next() + elseif t.Type=="method" then + t=test:next() + elseif t.Type=="choice" then + if test.stats.reading then + speak(t.text) + else + print(t.text) + end + for i=1,#t.choices do + io.write(i..": "..t.choices[i].."\n") + end + io.write("Enter choice#: ") + local n=tonumber(io.read()) + t=test:next(t,n) + elseif t.Type=="end" then + if t.text=="leaking" then-- go directly to the block right under the current block if it exists + t=test:next() + else + print(t.text) + os.exit()-- if you have more than one dialogue objects you are using, you may want to change this from exiting the code to escaping your loop or changing the reference to t. Remember seperate block objects cannot access variables from each other! + end + elseif t.Type=="error" then + print(t.text) + io.read() + else + t=test:next() + end +end diff --git a/test.mp3 b/test.mp3 new file mode 100644 index 0000000..6b6f022 Binary files /dev/null and b/test.mp3 differ