diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index eba1110..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto \ No newline at end of file diff --git a/Audio/Collapse.ogg b/Audio/Collapse.ogg deleted file mode 100644 index 2041364..0000000 Binary files a/Audio/Collapse.ogg and /dev/null differ diff --git a/Audio/Creaky.ogg b/Audio/Creaky.ogg deleted file mode 100644 index 5c96307..0000000 Binary files a/Audio/Creaky.ogg and /dev/null differ diff --git a/Audio/Deadly Sorrow.ogg b/Audio/Deadly Sorrow.ogg deleted file mode 100644 index 818f791..0000000 Binary files a/Audio/Deadly Sorrow.ogg and /dev/null differ diff --git a/Audio/Don't Die on Me.ogg b/Audio/Don't Die on Me.ogg deleted file mode 100644 index b1b1a76..0000000 Binary files a/Audio/Don't Die on Me.ogg and /dev/null differ diff --git a/Audio/Laugh.ogg b/Audio/Laugh.ogg deleted file mode 100644 index e3daee4..0000000 Binary files a/Audio/Laugh.ogg and /dev/null differ diff --git a/Audio/Lost World - myuu.ogg b/Audio/Lost World - myuu.ogg deleted file mode 100644 index 3e95504..0000000 Binary files a/Audio/Lost World - myuu.ogg and /dev/null differ diff --git a/Audio/The End Is Always Near.ogg b/Audio/The End Is Always Near.ogg deleted file mode 100644 index 8905381..0000000 Binary files a/Audio/The End Is Always Near.ogg and /dev/null differ diff --git a/Audio/What Could Have Been.ogg b/Audio/What Could Have Been.ogg deleted file mode 100644 index 072857d..0000000 Binary files a/Audio/What Could Have Been.ogg and /dev/null differ diff --git a/Audio/Yawn.ogg b/Audio/Yawn.ogg deleted file mode 100644 index f952bce..0000000 Binary files a/Audio/Yawn.ogg and /dev/null differ diff --git a/Audio/alarm.ogg b/Audio/alarm.ogg deleted file mode 100644 index d4bdaa3..0000000 Binary files a/Audio/alarm.ogg and /dev/null differ diff --git a/Audio/bed.ogg b/Audio/bed.ogg deleted file mode 100644 index 51ac852..0000000 Binary files a/Audio/bed.ogg and /dev/null differ diff --git a/Audio/boyknife.ogg b/Audio/boyknife.ogg deleted file mode 100644 index 5f8ee76..0000000 Binary files a/Audio/boyknife.ogg and /dev/null differ diff --git a/Audio/footsteps.ogg b/Audio/footsteps.ogg deleted file mode 100644 index 8e53815..0000000 Binary files a/Audio/footsteps.ogg and /dev/null differ diff --git a/Audio/hmm.ogg b/Audio/hmm.ogg deleted file mode 100644 index 02ded82..0000000 Binary files a/Audio/hmm.ogg and /dev/null differ diff --git a/Audio/knife.ogg b/Audio/knife.ogg deleted file mode 100644 index b98fa18..0000000 Binary files a/Audio/knife.ogg and /dev/null differ diff --git a/Audio/over.ogg b/Audio/over.ogg deleted file mode 100644 index d9635c0..0000000 Binary files a/Audio/over.ogg and /dev/null differ diff --git a/Audio/paper.ogg b/Audio/paper.ogg deleted file mode 100644 index 12d34c7..0000000 Binary files a/Audio/paper.ogg and /dev/null differ diff --git a/Audio/pots.ogg b/Audio/pots.ogg deleted file mode 100644 index f8341f0..0000000 Binary files a/Audio/pots.ogg and /dev/null differ diff --git a/Audio/select.ogg b/Audio/select.ogg deleted file mode 100644 index 4e8fb46..0000000 Binary files a/Audio/select.ogg and /dev/null differ diff --git a/Audio/sigh.ogg b/Audio/sigh.ogg deleted file mode 100644 index b5650ec..0000000 Binary files a/Audio/sigh.ogg and /dev/null differ diff --git a/Audio/stairs.ogg b/Audio/stairs.ogg deleted file mode 100644 index b512df1..0000000 Binary files a/Audio/stairs.ogg and /dev/null differ diff --git a/Audio/store.ogg b/Audio/store.ogg deleted file mode 100644 index ad45b54..0000000 Binary files a/Audio/store.ogg and /dev/null differ diff --git a/Audio/twisted.ogg b/Audio/twisted.ogg deleted file mode 100644 index b0b09dd..0000000 Binary files a/Audio/twisted.ogg and /dev/null differ diff --git a/GuiManager/Core/Clickable.int b/GuiManager/Core/Clickable.int deleted file mode 100644 index f192d8e..0000000 --- a/GuiManager/Core/Clickable.int +++ /dev/null @@ -1,15 +0,0 @@ -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 my 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/Image-Animation/SetImage.int b/GuiManager/Image-Animation/SetImage.int deleted file mode 100644 index d0d5f78..0000000 --- a/GuiManager/Image-Animation/SetImage.int +++ /dev/null @@ -1,13 +0,0 @@ -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/newImageLabel.int b/GuiManager/Image-Animation/newImageLabel.int deleted file mode 100644 index 47323e1..0000000 --- a/GuiManager/Image-Animation/newImageLabel.int +++ /dev/null @@ -1,18 +0,0 @@ -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/Misc/Center.int b/GuiManager/Misc/Center.int deleted file mode 100644 index 0089c93..0000000 --- a/GuiManager/Misc/Center.int +++ /dev/null @@ -1,4 +0,0 @@ -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/addDominance.int b/GuiManager/Misc/addDominance.int deleted file mode 100644 index 5a55975..0000000 --- a/GuiManager/Misc/addDominance.int +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 0ec05e0..0000000 --- a/GuiManager/Misc/addHotKey.int +++ /dev/null @@ -1,6 +0,0 @@ -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/getFullSize.int b/GuiManager/Misc/getFullSize.int deleted file mode 100644 index 294667a..0000000 --- a/GuiManager/Misc/getFullSize.int +++ /dev/null @@ -1,12 +0,0 @@ -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/newScrollMenu.int b/GuiManager/Misc/newScrollMenu.int deleted file mode 100644 index 3dbfdaf..0000000 --- a/GuiManager/Misc/newScrollMenu.int +++ /dev/null @@ -1,98 +0,0 @@ -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/setHotKey.int b/GuiManager/Misc/setHotKey.int deleted file mode 100644 index 5866cfc..0000000 --- a/GuiManager/Misc/setHotKey.int +++ /dev/null @@ -1,24 +0,0 @@ -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 deleted file mode 100644 index 93d95c5..0000000 --- a/GuiManager/Misc/setNewFont.int +++ /dev/null @@ -1,3 +0,0 @@ -function gui:setNewFont(FontSize) - self.Font=love.graphics.setNewFont(tonumber(FontSize)) -end \ No newline at end of file diff --git a/GuiManager/Text/newTextBox.int b/GuiManager/Text/newTextBox.int deleted file mode 100644 index c98b847..0000000 --- a/GuiManager/Text/newTextBox.int +++ /dev/null @@ -1,178 +0,0 @@ -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 deleted file mode 100644 index da2f3f6..0000000 --- a/GuiManager/Text/newTextButton.int +++ /dev/null @@ -1,22 +0,0 @@ -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/Interface/colorpicker.int b/Interface/colorpicker.int deleted file mode 100644 index 2c58170..0000000 --- a/Interface/colorpicker.int +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index b05bba4..0000000 --- a/Interface/console.int +++ /dev/null @@ -1,40 +0,0 @@ -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 deleted file mode 100644 index 3d6f2be..0000000 --- a/Interface/header.int +++ /dev/null @@ -1,81 +0,0 @@ -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 deleted file mode 100644 index 91fa354..0000000 --- a/Interface/player.int +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index e0fc435..0000000 --- a/Interface/system.int +++ /dev/null @@ -1,77 +0,0 @@ -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/MultiManager.lua b/Libs/MultiManager.lua deleted file mode 100644 index d3a2dd2..0000000 --- a/Libs/MultiManager.lua +++ /dev/null @@ -1,1391 +0,0 @@ -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 deleted file mode 100644 index 02b5fb6..0000000 --- a/Libs/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -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 deleted file mode 100644 index f861efa..0000000 --- a/Libs/T1.lua +++ /dev/null @@ -1,598 +0,0 @@ -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 deleted file mode 100644 index 44e2fbf..0000000 --- a/Libs/T2.lua +++ /dev/null @@ -1,598 +0,0 @@ -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 deleted file mode 100644 index 171eff0..0000000 --- a/Libs/T3.lua +++ /dev/null @@ -1,596 +0,0 @@ -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 deleted file mode 100644 index a8d3203..0000000 --- a/Libs/T4.lua +++ /dev/null @@ -1,596 +0,0 @@ -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 deleted file mode 100644 index de6434d..0000000 --- a/Libs/ThreadManager.lua +++ /dev/null @@ -1,158 +0,0 @@ -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/bin.lua b/Libs/bin.lua deleted file mode 100644 index 3c0a143..0000000 --- a/Libs/bin.lua +++ /dev/null @@ -1,2675 +0,0 @@ ---[[TODO - +Better compatiblity with streamables - +Add Data Compression - +Add Encryption(better) - +Create full documentation - +Enhance VFS stuff -]] -bin={} -bin.Version={4,1,0} -bin.stage='stable' -bin.help=[[ -For a list of features do print(bin.Features) -For a list of changes do print(bin.changelog) -For current version do print(bin.Version) -For current stage do print(bin.stage) -For help do print(bin.help) :D -]] -bin.credits=[[ -Credits: - Everything by me, Ryan Ward - Except the randomGen Stuff I forgot who i took that from, edits by me though :) -]] -bin.Features=bin.Version[1]..'.'..bin.Version[2]..'.'..bin.Version[3]..' '..bin.stage..[[ - -print(bin.Features) And you get this thing -print(bin.Version) ]]..bin.Version[1]..'.'..bin.Version[2]..'.'..bin.Version[3]..[[ <-- your version -print(bin.Changlog) -- gives you a list of changes -print(bin.stage) ]]..bin.stage..[[ <-- your stage - -Purpose -------- -Made to assist with the manipulation of binary data and efficent data management -Created by: Ryan Ward - -Full documentation with examples of every function soon to come!!! -This is a brief doc for reference -Misc ----- -nil = log(data,name,fmt) -- data is the text that you want to log to a file, the name argument only needs to be called with the first log. It tells where to log to. If name is used again it will change the location of the log file. -string,string,string = bin.getLuaVersion() -- returns PUC/JIT,major,minor - -Constructors ------------- -binobj = bin.load(filename,s,r) -- creates binobj from file in s and r nil then reads entire file but if not s is the start point of reading and r is either the #to read after s or from s to '#' (like string.sub()) -binobj = bin.new(string data) -- creates binobj from a string -binobj = bin.stream(file,lock) -- creates a streamable binobj lock is defult to true if locked file is read only -binobj = bin.newTempFile(data) -- creates a tempfile in stream mode -bitobj = bits.new(n) -- creates bitobj from a number -vfs = bin.newVFS() -- creates a new virtual file system --Beta -vfs = bin.loadVFS(path) -- loads a saved .lvfs file --Beta -buf = bin:newDataBuffer(s) -- creates a databuffer -binobj = bin.bufferToBin(b) -- converts a buffer object to a bin object -buf = bin.binToBuffer(b) -- converts a bin object to a buffer obj -blockWriter = bin.newNamedBlock(indexSize) -- returns a block writer object index size is the size of the index where labels and pointers are stored -blockWriter = bin.newStreamedNamedBlock(indexSize,path) -- returns a streamed version of the above path is the path to write the file -blockReader = bin.loadNamedBlock(path) -- returns a block reader object, path is where the file is located -blockHandler= bin.namedBlockManager(arg) -- returns a block handler object, if arg is a string it will loade a named block file, if its a number or nil it will create a nambed block object - -Note: the blockWriter that isn't streamed needs to have tofile(path) called on it to write it to a file -Note: the streamed blockWriter must have the close method used when you are done writing to it! - -Helpers -------- -string = bin.randomName(n,ext) -- creates a random file name if n and ext is nil then a random length is used, and '.tmp' extension is added -string = bin.NumtoHEX(n) -- turns number into hex -binobj = bin.HEXtoBin(s) -- turns hex data into binobj -string = bin.HEXtoStr(s) -- turns hex data into string/text -string = bin.tohex(s) -- turns string to hex -string = bin.fromhex(s) -- turns hex to string -string = bin.endianflop(data) -- flips the high order bits to the low order bits and viseversa -string = bin.getVersion() -- returns the version as a string -string = bin.escapeStr(str) -- system function that turns functions into easy light -string = bin.ToStr(tab) -- turns a table into a string (even functions are dumped; used to create compact data files) -nil = bin.packLLIB(name,tab,ext) -- turns a bunch of 'files' into 1 file tab is a table of file names, ext is extension if nil .llib is used Note: Currently does not support directories within .llib -nil = bin.unpackLLIB(name,exe,todir,over,ext) -- takes that file and makes the files Note: if exe is true and a .lua file is in the .llib archive than it is ran after extraction ext is extension if nil .llib is used -boolean = bin.fileExist(path) -- returns true if the file exist false otherwise -boolean*= bin.closeto(a,b,v) -- test data to see how close it is (a,b=tested data v=#difference (v must be <=255)) -String = bin.textToBinary(txt) -- turns text into binary data 10101010's -binobj = bin.decodeBits(bindata) -- turns binary data into text -string = bin.trimNul(s) -- terminates string at the nul char -number = bin.getIndexSize(tab) -- used to get the index size of labels given to a named block -string = bits.numToBytes(num,occ) -- returns the number in base256 string data, occ is the space the number will take up - -Assessors ---------- -nil*** = binobj:tofile(filename) -- writes binobj data as a file -binobj* = binobj:clone() -- clones and returns a binobj -number* = binobj:compare(other binobj,diff) -- returns 0-100 % of simularity based on diff factor (diff must be <=255) -string = binobj:sub(a,b) -- returns string data like segment but dosen't alter the binobject -num,num = binobj:tonumber(a,b) -- converts from a-b (if a and b are nil it uses the entire binobj) into a base 10 number so 'AXG' in data becomes 4675649 returns big,little endian -number = binobj:getbyte(n) -- gets byte at location and converts to base 10 number -bitobj = binobj:tobits(i) -- returns the 8bits of data as a bitobj Ex: if value of byte was a 5 it returns a bitobj with a value of: '00000101' -string = binobj:getHEX(a,b) -- gets the HEX data from 'a' to 'b' if both a,b are nil returns entire file as hex -a,b = binobj:scan(s,n,f) -- searches a binobj for 's'; n is where to start looking, 'f' is weather or not to flip the string data entered 's' -string = binobj:streamData(a,b) -- reads data from a to b or a can be a data handle... I will explain this and more in offical documentation -string# = binobj:streamread(a,b) -- reads data from a stream object between a and b (note: while other functions start at 1 for both stream and non stream 0 is the starting point for this one) -boolean = binobj:canStreamWrite() -- returns true if the binobj is streamable and isn't locked -string = bitobj:conv(n) -- converts number to binary bits (system used) -binobj = bitobj:tobytes() -- converts bit obj into a string byte (0-255) -number = bitobj:tonumber() -- converts '10101010' to a number -boolean = bitobj:isover() -- returns true if the bits exceed 8 bits false if 8 or less -string = bitobj:getBin() -- returns the binary 10100100's of the data as a string -string = binobj:getHash(n) -- returns a Hash of a file (This is my own method of hashing btw) n is the length you want the hash to be -string = binobj:getData() -- returns the bin object as a string -depends = blockReader:getBlock(name) -- returns the value associated with the name, values can be any lua data except userdata - -Mutators (Changes affect the actual object or if streaming the actual file) bin:remove() --------- -nil = binobj:setEndOfFile(n) -- sets the end of a file -nil = binobj:reverse() -- reverses binobj data ex: hello --> 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 deleted file mode 100644 index eca6618..0000000 --- a/Libs/lovebind.lua +++ /dev/null @@ -1,103 +0,0 @@ -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 deleted file mode 100644 index 8b9302a..0000000 Binary files a/Libs/test.dat and /dev/null differ diff --git a/Libs/test.lua b/Libs/test.lua deleted file mode 100644 index f551bde..0000000 --- a/Libs/test.lua +++ /dev/null @@ -1,18 +0,0 @@ -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/README.md b/README.md deleted file mode 100644 index b3e6377..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# VisualNovelCreater - -Heavy usage of the parseManager and multi library. The end goal is to have a visual novel creator that is easy and simple to use diff --git a/Tests.dmf b/Tests.dmf deleted file mode 100644 index 41fea47..0000000 --- a/Tests.dmf +++ /dev/null @@ -1,38 +0,0 @@ -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/GuiManager/Core/Colors.int b/Visual Novel/GuiManager/Core/Colors.int similarity index 98% rename from GuiManager/Core/Colors.int rename to Visual Novel/GuiManager/Core/Colors.int index 896a745..eda5f1e 100644 --- a/GuiManager/Core/Colors.int +++ b/Visual Novel/GuiManager/Core/Colors.int @@ -1,5 +1,19 @@ +local function HSL(h, s, l, a) + if s<=0 then return l,l,l,a end + h, s, l = h/256*6, s/255, l/255 + local c = (1-math.abs(2*l-1))*s + local x = (1-math.abs(h%2-1))*c + local m,r,b,g = (l-.5*c), 0,0,0 + if h < 1 then r,b,g = c,x,0 + elseif h < 2 then r,b,g = x,c,0 + elseif h < 3 then r,b,g = 0,c,x + elseif h < 4 then r,b,g = 0,x,c + elseif h < 5 then r,b,g = x,0,c + else r,b,g = c,0,x + end return (r+m)*255,(g+m)*255,(b+m)*255,a +end Color={ -new=function(r,g,b) +new=function(r,b,g) mt = { __add = function (c1,c2) return Color.new(c1[1]+c2[1],c1[2]+c2[2],c1[2]+c2[2]) @@ -29,7 +43,7 @@ new=function(r,g,b) __lt = Color.LT, __le = Color.LE, } - local temp = {r,g,b,255} + local temp = {r/255,b/255,g/255,1} setmetatable(temp, mt) return temp end, @@ -57,14 +71,13 @@ Darken=function(color,v) currentR=color[1] currentG=color[2] currentB=color[3] - return Color.new(currentR * (1 - v),currentG * (1 - v),currentB * (1 - v)) + return Color.new((currentR*255) * (1 - v),(currentG*255) * (1 - v),(currentB*255) * (1 - v)) end, Lighten=function(color,v) currentR=color[1] currentG=color[2] currentB=color[3] - - return Color.new(currentR + (255 - currentR) * v,currentG + (255 - currentG) * v,currentB + (255 - currentB) * v) + return Color.new(currentR*255 + (255 - (currentR*255)) * v,currentG*255 + (255 - (currentG*255)) * v,currentB*255 + (255 - (currentB*255)) * v) end } Color.IndexColor("Black",20,20,20) diff --git a/Visual Novel/GuiManager/Core/EventDefinitions.int b/Visual Novel/GuiManager/Core/EventDefinitions.int new file mode 100644 index 0000000..5668e97 --- /dev/null +++ b/Visual Novel/GuiManager/Core/EventDefinitions.int @@ -0,0 +1,200 @@ +local buttonConv = {"l","r","m","x1","x2"} -- For the old stuff +function gui:OnClicked(func) + if not self.clickEvnt then + self.clickEvnt = true + self._connClicked = multi:newConnection() + self._connClicked(func) + multi:newThread(self.Name.."_Updater",function() + while true do + thread.hold(function() return self.Active or self.Destroyed end) + if love.mouse.isDown(1) and self:canPress() then + self._connClicked:Fire("1",self,love.mouse.getX()-self.x,love.mouse.getY()-self.y) + end + if love.mouse.isDown(2) and self:canPress() then + self._connClicked:Fire("r",self,love.mouse.getX()-self.x,love.mouse.getY()-self.y) + end + if love.mouse.isDown(3) and self:canPress() then + self._connClicked:Fire("m",self,love.mouse.getX()-self.x,love.mouse.getY()-self.y) + end + if love.mouse.isDown(4) and self:canPress() then + self._connClicked:Fire("x1",self,love.mouse.getX()-self.x,love.mouse.getY()-self.y) + end + if love.mouse.isDown(5) and self:canPress() then + self._connClicked:Fire("x2",self,love.mouse.getX()-self.x,love.mouse.getY()-self.y) + end + if self.Destroyed then + thread.kill() + end + end + end) + else + self._connClicked(func) + end +end +function gui:OnPressed(func) + multi.OnMousePressed(function(x,y,b) + if self:canPress() then + func(buttonConv[b],self,x,y) + end + end) +end +function gui:OnPressedOuter(func) + multi.OnMousePressed(function(x,y,b) + if not(self:canPress()) then + func(buttonConv[b],self) + end + end,nil,1) +end +function gui:OnReleased(func) + multi.OnMouseReleased(function(x,y,b) + if self:canPress() then + func(buttonConv[b],self,x,y) + end + end) +end +function gui:OnReleasedOuter(func) + multi.OnMouseReleased(function(x,y,b) + if not(self:canPress()) then + func(buttonConv[b],self) + end + end,nil,1) +end +function gui:OnUpdate(func) + if not self.updateEvnt then + self._connUpdate = multi:newConnection() + self._connUpdate(func) + self.updateEvnt = true + multi:newThread(self.Name.."_Updater",function() + while true do + thread.hold(function() return self.Active end) + self._connUpdate:Fire(self) + end + end) + else + self._connUpdate(func) + end +end +function gui:OnMouseMoved(func) + multi.OnMouseMoved(function(x,y,dx,dy) + if self:canPress() then + func(self,x-self.x,y-self.y,dx,dy) + end + end,nil,1) +end +gui.WhileHovering=gui.OnMouseMoved -- To keep older features working +local mbenter = multi:newConnection() +function gui:OnMouseEnter(func) + self.HE=false + mbenter(func) + self:OnMouseMoved(function() + if self.HE == false then + self.HE=true + self._HE = true + mbenter:Fire(self) + end + end) +end +function gui:OnMouseExit(func) + if not self.exitEvnt then + self._connExit = multi:newConnection() + self._connExit(func) + self.exitEvnt = true + self.HE=false + multi:newThread(self.Name.."_OnExit",function() + while true do + thread.hold(function() return self.HE or self.Destroyed end) + if not(self:canPress()) then + self.HE=false + self._connExit:Fire(self) + end + if self.Destroyed then + thread.kill() + end + end + end) + else + self._connExit(func) + end +end +--[[ +x=(love.mouse.getX()-self.x) +y=(love.mouse.getY()-self.y) +self:Move(x,y) +]] +function gui:OnMouseWheelMoved(func) + multi.OnMouseWheelMoved(function(...) + if self:canPress() then + func(self,...) + end + end) +end +function gui:enableDragging(bool) + self.draggable = bool + if self.dragEvnt then + return + end + self.dragEvnt = true + self._connDragStart = multi:newConnection() + self._connDragging = multi:newConnection() + self._connDragEnd = multi:newConnection() + self.hasDrag = false + local startX + local startY + self:OnPressed(function(b,self,x,y) + if b~=self.dragbut or not(self.draggable) then return end + self._connDragStart:Fire(self) + self.hasDrag = true + startX = x + startY = y + end) + multi.OnMouseMoved(function(x,y,dx,dy) + if self.hasDrag and self.draggable then + self:Move(dx,dy) + self._connDragging:Fire(self) + end + end) + multi.OnMouseReleased(function(x,y,b) + if buttonConv[b]~=self.dragbut or not(self.draggable) or not(self.hasDrag) then return end + self.hasDrag = false + startX = nil + startY = nil + self._connDragEnd:Fire(self) + end) +end +function gui:OnDragStart(func) + if not self.dragEvnt then + self:enableDragging(true) + self._connDragStart(func) + else + self._connDragStart(func) + end +end +function gui:OnDragging(func) + if not self.dragEvnt then + self:enableDragging(true) + self._connDragging(func) + else + self._connDragging(func) + end +end +function gui:OnDragEnd(func) + if not self.dragEvnt then + self:enableDragging(true) + self._connDragEnd(func) + else + self._connDragEnd(func) + end +end +function gui:OnHotKey(key,func) + local tab=key:split("+") + multi.OnKeyPressed(function() + for i=1,#tab do + if not(love.keyboard.isDown(tab[i])) then + return + end + end + func(self) + end) +end +gui.addHotKey=gui.OnHotKey +gui.setHotKey=gui.OnHotKey \ No newline at end of file diff --git a/GuiManager/Core/_GetAllChildren.int b/Visual Novel/GuiManager/Core/_GetAllChildren.int similarity index 100% rename from GuiManager/Core/_GetAllChildren.int rename to Visual Novel/GuiManager/Core/_GetAllChildren.int diff --git a/GuiManager/Core/_GetAllChildren2.int b/Visual Novel/GuiManager/Core/_GetAllChildren2.int similarity index 100% rename from GuiManager/Core/_GetAllChildren2.int rename to Visual Novel/GuiManager/Core/_GetAllChildren2.int diff --git a/Visual Novel/GuiManager/Core/canPress.int b/Visual Novel/GuiManager/Core/canPress.int new file mode 100644 index 0000000..0e33f11 --- /dev/null +++ b/Visual Novel/GuiManager/Core/canPress.int @@ -0,0 +1,72 @@ +function gui:getParents() + local c,me = {}, self.Parent + while me.Parent~=nil do + c[#c+1]=me + me = me.Parent + end + return c +end +function gui:eventable() + if self.important then + return true + end + if _GuiPro.Hierarchy then + if _GuiPro.TopHovered~=nil then + return self:isDescendant(_GuiPro.TopHovered) or _GuiPro.TopHovered==self + else + return true + end + else + return true + end +end +function gui:parentVisible() + local c = self:getParents() + for i=#c,1,-1 do + if not c[i].Visible then return false end + end + return true +end +function gui:isBeingCovering() + return false + -- if self.allowOverlapping then return false end + -- local ref = self.FrameRef or gui + -- local x,y = love.mouse.getX(),love.mouse.getY() + -- for i = 1,#_GuiPro.Frames do + -- if _GuiPro.Frames[i]~=ref then + -- if (ref.depth or 0)<(_GuiPro.Frames[i].depth or math.huge) then + -- local pos = (x > self.x and x < self.x+self.width and y > self.y and y < self.y+self.height) and (x > _GuiPro.Frames[i].x and x < _GuiPro.Frames[i].x+_GuiPro.Frames[i].width and y > _GuiPro.Frames[i].y and y < _GuiPro.Frames[i].y+_GuiPro.Frames[i].height) and (x > self.x and x < self.x+self.width and y > self.y and y < self.y+self.height ) + -- if not pos then return true end + -- end + -- end + -- end +end +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 my ref.x and x < ref.x+ref.width and y > ref.y and y < ref.y+ref.height) and (x > self.x and x < self.x+self.width and y > self.y and y < self.y+self.height and self:Clickable() and (self:eventable() or self:touchable())) then + return true + else + return false + end + else + return false + end +end \ No newline at end of file diff --git a/GuiManager/Frame/newratioFrame.int b/Visual Novel/GuiManager/Core/fromString.int similarity index 100% rename from GuiManager/Frame/newratioFrame.int rename to Visual Novel/GuiManager/Core/fromString.int diff --git a/GuiManager/Core/full.int b/Visual Novel/GuiManager/Core/full.int similarity index 100% rename from GuiManager/Core/full.int rename to Visual Novel/GuiManager/Core/full.int diff --git a/GuiManager/Core/newBase.int b/Visual Novel/GuiManager/Core/newBase.int similarity index 52% rename from GuiManager/Core/newBase.int rename to Visual Novel/GuiManager/Core/newBase.int index ad4b096..e16bcc4 100644 --- a/GuiManager/Core/newBase.int +++ b/Visual Novel/GuiManager/Core/newBase.int @@ -1,3 +1,6 @@ +_GuiPro.Frames = {} +_GuiPro.Type = "Window" +_GuiPro.depth = 0 function gui.enableAutoWindowScaling(b) _GuiPro.DPI_ENABLED=b or true _defaultfont=love.graphics.newFont(12*love.window.getPixelScale()) @@ -15,6 +18,9 @@ function filter(name, x, y, w, h, sx ,sy ,sw ,sh) end return x,y,w,h,sx,sy,sw,sh end +function gui:getChildren() + return self.Children +end function gui:newBase(tp,name, x, y, w, h, sx ,sy ,sw ,sh) _GuiPro.count=_GuiPro.count+1 local c = {} @@ -24,15 +30,25 @@ function gui:newBase(tp,name, x, y, w, h, sx ,sy ,sw ,sh) else c.Parent=self end - c.segments=nil - c.ry=nil - c.rx=nil - c.DPI=1 - if _GuiPro.DPI_ENABLED then - c.DPI=love.window.getPixelScale() - x, y, w, h=c.DPI*x,c.DPI*y,c.DPI*w,c.DPI*h - end - c.centerFontY=true + if tp:match("Frame") then + _GuiPro.Frames[#_GuiPro.Frames+1] = c + end + if self.Type and self.Type:match("Frame") then + c.FrameRef = self + else + c.FrameRef = self.FrameRef + end + c.segments=nil + c.ry=nil + c.rx=nil + c.DPI=1 + c.isLeaf = true + c.Parent.isLeaf = false + if _GuiPro.DPI_ENABLED then + c.DPI=love.window.getPixelScale() + x, y, w, h=c.DPI*x,c.DPI*y,c.DPI*w,c.DPI*h + end + c.centerFontY=true c.FormFactor="rectangle" c.Type=tp c.Active=true @@ -52,7 +68,6 @@ function gui:newBase(tp,name, x, y, w, h, sx ,sy ,sw ,sh) c.mclicked=false c.clicked=false c.Visibility=1 - c.ClipDescendants=false c.TextWrap=true c.scale={} c.scale.size={} @@ -74,66 +89,23 @@ function gui:newBase(tp,name, x, y, w, h, sx ,sy ,sw ,sh) c.RRE=false c.MRE=false c.Color = {255, 255, 255} - function c:setRoundness(rx,ry,segments) - self.segments=segments - self.ry=ry - self.rx=rx - end - function c.stfunc() - love.graphics.rectangle("fill", c.x, c.y, c.width, c.height,c.rx,c.ry,c.segments) - end - function c:hasRoundness() - return (self.ry or self.rx) - end - c.funcs={function(b,self) - if b=="l" then - self.LRE=true - end - end, - function(b,self) - if b=="r" then - self.RRE=true - end - end, - function(b,self) - if b=="m" then - self.MRE=true - end - end} - c.funcs2={function(b,self) - if b=="l" then - self.LRE=false - end - end, - function(b,self) - if b=="r" then - self.RRE=false - end - end, - function(b,self) - if b=="m" then - self.MRE=false - end - end} - c.HE=false - c.funcs3={function(self) - self.HE=true - end} - c.funcs4={function(self) - self.HE=false - end} - c.funcs5={} + function c:setRoundness(rx,ry,segments) + self.segments=segments + self.ry=ry + self.rx=rx + end + function c.stfunc() + love.graphics.rectangle("fill", c.x, c.y, c.width, c.height,c.rx,c.ry,c.segments) + end + function c:hasRoundness() + return (self.ry or self.rx) + end c.tid={} c.touchcount=0 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 - c.func6={} - c.func7={function() _GuiPro.DragItem={} end} - c.func8={function(self) _GuiPro.DragItem=self end} - c.func9={} - c.func10={} function c:ImageRule() if self.Image then local sx=self.width/self.ImageWidth @@ -177,61 +149,19 @@ function gui:newBase(tp,name, x, y, w, h, sx ,sy ,sw ,sh) _GuiPro.self=self if type(i)=="number" then loadstring("_GuiPro.self:"..v)() + elseif i:match"__self__" then + local ind=i:match"__self__(.+)" + if not self[ind] then self[ind]={} end + loadstring("_GuiPro.self."..ind.."=_GuiPro.self:"..v)() + elseif i:match"__child__" then + local ind,child = i:match"__child__(%S-)_(.+)" + self[ind][child]=v else self[i]=v end end return self end - c:WhileHovering(function(self) - self.omx=self.nmx - self.omy=self.nmy - self.nmx=love.mouse.getX() - self.nmy=love.mouse.getY() - if self.omx~=self.nmx or self.omy~=self.nmy then - for i=1,#self.func10 do - if self and self.nmx and self.nmy and self.omx and self.omy then - self.func10[i](self,self.nmx,self.nmy,self.omx,self.omy) - end - end - end - if self.WasBeingDragged==true and love.mouse.isDown(self.dragbut or "m")==false and self.Type~="TextImageButtonFrameDrag" then - for i=1,#self.func7 do - self.func7[i](self,(love.mouse.getX())-self.width/2,(love.mouse.getY())-self.height/2) - end - end - if _GuiPro.hasDrag==false and love.mouse.isDown(self.dragbut or "m") then - for i=1,#self.func8 do - self.func8[i](self,(love.mouse.getX())-self.width/2,(love.mouse.getY())-self.height/2) - end - end - if self.IsBeingDragged==true then - _GuiPro.hasDrag=true - self.WasBeingDragged=true - elseif self.WasBeingDragged==true and self.IsBeingDragged==false then - self.WasBeingDragged=false - _GuiPro.hasDrag=false - end - if self.Draggable==true and love.mouse.isDown(self.dragbut or "m") and _GuiPro.hasDrag==false then - for i=1,#self.func6 do - self.func6[i](self,(love.mouse.getX())-self.width/2,(love.mouse.getY())-self.height/2) - end - _GuiPro.hasDrag=true - if self.FormFactor:lower()=="circle" or self.FormFactor:lower()=="c" or self.FormFactor:lower()=="cir" then - self.IsBeingDragged=true - x=(love.mouse.getX()-self.x) - y=(love.mouse.getY()-self.y) - self:Move(x,y) - elseif self.FormFactor:lower()=="rectangle" or self.FormFactor:lower()=="r" or self.FormFactor:lower()=="rect" then - self.IsBeingDragged=true - x=(love.mouse.getX()-self.x)-self.width/2 - y=(love.mouse.getY()-self.y)-self.height/2 - self:Move(x,y) - end - else - self.IsBeingDragged=false - end - end) table.insert(c.Parent.Children,c) return c end \ No newline at end of file diff --git a/GuiManager/Core/patches.int b/Visual Novel/GuiManager/Core/patches.int similarity index 100% rename from GuiManager/Core/patches.int rename to Visual Novel/GuiManager/Core/patches.int diff --git a/Visual Novel/GuiManager/Core/toString.int b/Visual Novel/GuiManager/Core/toString.int new file mode 100644 index 0000000..741685c --- /dev/null +++ b/Visual Novel/GuiManager/Core/toString.int @@ -0,0 +1,40 @@ +function gui:toString() -- oh boy this is gonna be painful lol + multi:newThread("saving data: ",function() + local dat=bin.stream("test.dat",false) + function GetAllChildren2(Object) + local Stuff = {} + function Seek(Items) + for i=1,#Items do + --table.insert(Stuff,Items[i]) + for a,v in pairs(Items[i]) do + -- dat:tackE(a.."|"..tostring(v)) + print(a.."|"..tostring(v)) + -- dat.workingfile:flush() + end + thread.skip() + local NItems = Items[i]:getChildren() + if NItems ~= nil then + Seek(NItems) + end + end + end + local Objs = Object:getChildren() + for i=1,#Objs do + -- table.insert(Stuff,Objs[i]) + for a,v in pairs(Objs[i]) do + -- dat:tackE(a.."|"..tostring(v)) + print(Objs[i].Type..":"..a.."|"..tostring(v)) + -- dat.workingfile:flush() + end + thread.skip() + local Items = Objs[i]:getChildren() + if Items ~= nil then + Seek(Items) + end + end + -- dat:tofile("test.dat") + return Stuff + end + GetAllChildren2(self) + end) +end \ No newline at end of file diff --git a/GuiManager/Core/touchManager.int b/Visual Novel/GuiManager/Core/touchManager.int similarity index 98% rename from GuiManager/Core/touchManager.int rename to Visual Novel/GuiManager/Core/touchManager.int index d941ba1..06259c7 100644 --- a/GuiManager/Core/touchManager.int +++ b/Visual Novel/GuiManager/Core/touchManager.int @@ -26,7 +26,7 @@ function gui:touchable(t) end self.id=-1 end -multi:newTask(function() -- A bit of post-loading haha +--multi:newTask(function() -- A bit of post-loading haha gui.touchpressed=multi:newConnection() gui.touchreleased=multi:newConnection() gui.touchmoved=multi:newConnection() @@ -83,9 +83,9 @@ multi:newTask(function() -- A bit of post-loading haha end end end) -end) +--end) -- now that that is done lets set up some more post loading checks -_GuiPro.int=multi:newProcess() +_GuiPro.int=multi:newProcessor() _GuiPro.int:Start() _GuiPro.int:setJobSpeed(.001) _GuiPro.EXACT=0 diff --git a/GuiManager/Drawing/AddDrawRuleB.int b/Visual Novel/GuiManager/Drawing/AddDrawRuleB.int similarity index 100% rename from GuiManager/Drawing/AddDrawRuleB.int rename to Visual Novel/GuiManager/Drawing/AddDrawRuleB.int diff --git a/GuiManager/Drawing/AddDrawRuleE.int b/Visual Novel/GuiManager/Drawing/AddDrawRuleE.int similarity index 100% rename from GuiManager/Drawing/AddDrawRuleE.int rename to Visual Novel/GuiManager/Drawing/AddDrawRuleE.int diff --git a/Visual Novel/GuiManager/Drawing/canvas.int b/Visual Novel/GuiManager/Drawing/canvas.int new file mode 100644 index 0000000..e69de29 diff --git a/GuiManager/Drawing/draw.int b/Visual Novel/GuiManager/Drawing/draw.int similarity index 100% rename from GuiManager/Drawing/draw.int rename to Visual Novel/GuiManager/Drawing/draw.int diff --git a/GuiManager/Drawing/drawC.int b/Visual Novel/GuiManager/Drawing/drawC.int similarity index 89% rename from GuiManager/Drawing/drawC.int rename to Visual Novel/GuiManager/Drawing/drawC.int index 84592b5..95febad 100644 --- a/GuiManager/Drawing/drawC.int +++ b/Visual Novel/GuiManager/Drawing/drawC.int @@ -27,37 +27,37 @@ function gui:drawC() 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) + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility) else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility) 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) + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility) else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility) 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) + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility) else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility) 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) + love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility) else - love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility) 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) + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility) self.hovering=false self.rclicked=false self.lclicked=false @@ -71,7 +71,7 @@ function gui:drawC() 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) + love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],(self.BorderVisibility or 1)) for b=0,self.BorderSize-1 do love.graphics.circle("line",x,y,r+b,s) end @@ -80,7 +80,7 @@ function gui:drawC() 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.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility) love.graphics.setFont(self.Font) love.graphics.printf(self.text, x-(r/2)+(self.XTween), y-(r/2)+self.Tween, r, self.TextFormat) end diff --git a/Visual Novel/GuiManager/Drawing/drawR.int b/Visual Novel/GuiManager/Drawing/drawR.int new file mode 100644 index 0000000..05a96f0 --- /dev/null +++ b/Visual Novel/GuiManager/Drawing/drawR.int @@ -0,0 +1,73 @@ +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.hidden then + 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 + self.VIS = false + end + if self.Visible==true and self.VIS==true then + 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 + 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 + if self.DrawRulesB then + for dr=1,#self.DrawRulesB do + self.DrawRulesB[dr](self) + end + end + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility) + 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.BorderVisibility or 1)) + 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 and self.TextFormat ~= "center" then + love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility) + love.graphics.setFont(self.Font) + love.graphics.printf(self.text, self.x, self.y, self.width, self.TextFormat,self.TextRotaion) + elseif self.text~=nil and self.TextFormat == "center" then + love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility) + love.graphics.setFont(self.Font) + love.graphics.printf(self.text, self.x+(self.width-self.Font:getWidth(self.text))/2, self.y+(self.height-self.Font:getHeight())/2, self.width, "left",self.TextRotaion) + 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/Visual Novel/GuiManager/Frame/newDropFrame.int similarity index 100% rename from GuiManager/Frame/newDropFrame.int rename to Visual Novel/GuiManager/Frame/newDropFrame.int diff --git a/GuiManager/Frame/newFrame.int b/Visual Novel/GuiManager/Frame/newFrame.int similarity index 100% rename from GuiManager/Frame/newFrame.int rename to Visual Novel/GuiManager/Frame/newFrame.int diff --git a/GuiManager/Frame/newFullFrame.int b/Visual Novel/GuiManager/Frame/newFullFrame.int similarity index 100% rename from GuiManager/Frame/newFullFrame.int rename to Visual Novel/GuiManager/Frame/newFullFrame.int diff --git a/GuiManager/Frame/newTabFrame.int b/Visual Novel/GuiManager/Frame/newTabFrame.int similarity index 100% rename from GuiManager/Frame/newTabFrame.int rename to Visual Novel/GuiManager/Frame/newTabFrame.int diff --git a/Visual Novel/GuiManager/Frame/newratioFrame.int b/Visual Novel/GuiManager/Frame/newratioFrame.int new file mode 100644 index 0000000..e69de29 diff --git a/Visual Novel/GuiManager/Image-Animation/SetImage.int b/Visual Novel/GuiManager/Image-Animation/SetImage.int new file mode 100644 index 0000000..7ff105f --- /dev/null +++ b/Visual Novel/GuiManager/Image-Animation/SetImage.int @@ -0,0 +1,16 @@ +function gui:SetImage(i) + if not i then return end + if type(i) == "userdata" and i:type() == "Image" then + self.Image=i + 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) + elseif type(i)=="string" then + gui.loadImageData(i,nil,function(imagedata) + self.Image = love.graphics.newImage(imagedata) + 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) + end +end \ No newline at end of file diff --git a/Visual Novel/GuiManager/Image-Animation/SetThreadedImage.int b/Visual Novel/GuiManager/Image-Animation/SetThreadedImage.int new file mode 100644 index 0000000..c791c5a --- /dev/null +++ b/Visual Novel/GuiManager/Image-Animation/SetThreadedImage.int @@ -0,0 +1,60 @@ +-- local queueUpload = love.thread.getChannel("ImageUploader") +-- local queueDownload = love.thread.getChannel("ImageDownloader") +-- local code = [[ +-- require("love.image") +-- local queueUpload = love.thread.getChannel("ImageUploader") +-- local queueDownload = love.thread.getChannel("ImageDownloader") +-- local clock = os.clock +-- local idle = clock +-- while true do + -- if not idle then + -- love.timer.sleep(.001) + -- elseif clock()-idle>=15 then + -- love.timer.sleep(.01) + -- end + -- local data = queue:pop() + -- if data then + -- idle = clock() + -- print(data[1],data[2]) + -- end +-- end +-- ]] +-- local t = love.thread.newThread(code) +-- t:start() + + +-- _GuiPro.jobqueue:registerJob("LoadImage",function(path) + -- local dat = love.image.newImageData(path) + -- return dat +-- end) +-- local cache = {} +-- _GuiPro.jobqueue.OnJobCompleted(function(JOBID,n) + -- cache[JOBID].Image=love.graphics.newImage(n) + -- cache[JOBID].ImageHeigth=cache[JOBID].Image:getHeight() + -- cache[JOBID].ImageWidth=cache[JOBID].Image:getWidth() + -- cache[JOBID].Quad=love.graphics.newQuad(0,0,cache[JOBID].width,cache[JOBID].height,cache[JOBID].ImageWidth,cache[JOBID].ImageHeigth) +-- end) +-- function gui:ThreadedSetImage(i) + -- local temp = self.Image + -- if _GuiPro.imagecache[i] then + -- self.Image=_GuiPro.imagecache[i] + -- 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) + -- else + -- if type(i)=="string" then + -- local ii = _GuiPro.jobqueue:pushJob("LoadImage",i) + -- cache[ii] = self + -- elseif tostring(i):find("ImageData") then + -- self.Image=love.graphics.newImage(i) + -- 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) + -- elseif i then + -- self.Image=i + -- 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 + -- end +-- end \ No newline at end of file diff --git a/Visual Novel/GuiManager/Image-Animation/imageThreadHandler.int b/Visual Novel/GuiManager/Image-Animation/imageThreadHandler.int new file mode 100644 index 0000000..08d3073 --- /dev/null +++ b/Visual Novel/GuiManager/Image-Animation/imageThreadHandler.int @@ -0,0 +1,44 @@ +local queueUpload = love.thread.getChannel("ImageUploader") +local queueDownload = love.thread.getChannel("ImageDownloader") +local code = [[ +require("love.image") +require("love.timer") +local queueUpload = love.thread.getChannel("ImageUploader") +local queueDownload = love.thread.getChannel("ImageDownloader") +while true do + love.timer.sleep(.001) + local data = queueUpload:pop() + if data then + queueDownload:push{data[1],love.image.newImageData(data[2])} + end +end +]] +local count = 0 +local conn = multi:newConnection() +function gui.loadImageData(path,tag,callback) + local c = count + count = count + 1 + queueUpload:push{c,path} + if not callback then + return conn + else + local cd + cd = conn(function(id,data) + if id == c then + callback(data,tag,id) + cd:Destroy() + end + end) + end + return c +end +multi:newLoop(function() + local dat = queueDownload:pop() + if dat then + conn:Fire(dat[1],dat[2]) + end +end) +for i = 1,love.system.getProcessorCount() do + local t = love.thread.newThread(code) + t:start() +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newAnim.int b/Visual Novel/GuiManager/Image-Animation/newAnim.int similarity index 74% rename from GuiManager/Image-Animation/newAnim.int rename to Visual Novel/GuiManager/Image-Animation/newAnim.int index 30850aa..64bcda9 100644 --- a/GuiManager/Image-Animation/newAnim.int +++ b/Visual Novel/GuiManager/Image-Animation/newAnim.int @@ -1,19 +1,28 @@ function gui:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) + local _files=alphanumsort(love.filesystem.getDirectoryItems(file)) 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) + if not w and not h then + local w,h = love.graphics.newImage(file.."/".._files[1]):getDimensions() + c:setDualDim(nil,nil,w,h) + end c.Visibility=0 c.ImageVisibility=1 c.delay=delay or .05 c.files={} c.AnimStart={} c.AnimEnd={} - local _files=alphanumsort(love.filesystem.getDirectoryItems(file)) + local count = 0 + local max for i=1,#_files do if string.sub(_files[i],-1,-1)~="b" then - table.insert(c.files,love.graphics.newImage(file.."/".._files[i])) + count = count + 1 + gui.loadImageData(file.."/".._files[i],count,function(imagedata,id) + c.files[id] = love.graphics.newImage(imagedata) + end) end end - c.step=multi:newTStep(1,#c.files,1,c.delay) + c.step=multi:newTStep(1,count,1,c.delay) c.step.parent=c c.rotation=0 c.step:OnStart(function(step) @@ -21,7 +30,7 @@ function gui:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) step.parent.AnimStart[i](step.parent) end end) - c.step:OnStep(function(pos,step) + c.step:OnStep(function(step,pos) step.parent:SetImage(step.parent.files[pos]) end) c.step:OnEnd(function(step) @@ -43,6 +52,7 @@ function gui:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) end function c:Reset() self.step.pos=1 + self.step:Reset() end function c:getFrames() return #self.files diff --git a/GuiManager/Image-Animation/newAnimFromData.int b/Visual Novel/GuiManager/Image-Animation/newAnimFromData.int similarity index 100% rename from GuiManager/Image-Animation/newAnimFromData.int rename to Visual Novel/GuiManager/Image-Animation/newAnimFromData.int diff --git a/GuiManager/Image-Animation/newAnimFromTiles.int b/Visual Novel/GuiManager/Image-Animation/newAnimFromTiles.int similarity index 94% rename from GuiManager/Image-Animation/newAnimFromTiles.int rename to Visual Novel/GuiManager/Image-Animation/newAnimFromTiles.int index 70aea2c..56fd0d8 100644 --- a/GuiManager/Image-Animation/newAnimFromTiles.int +++ b/Visual Novel/GuiManager/Image-Animation/newAnimFromTiles.int @@ -1,7 +1,7 @@ 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 im=love.image.newImageData(file) local _x,_y=im:getDimensions() c.Visibility=0 c.ImageVisibility=1 @@ -23,7 +23,7 @@ function gui:newAnimFromTiles(file,xd,yd,delay, x, y, w, h, sx ,sy ,sw ,sh) step.parent.AnimStart[i](step.parent) end end) - c.step:OnStep(function(pos,step) + c.step:OnStep(function(step,pos) step.parent:SetImage(step.parent.files[pos]) end) c.step:OnEnd(function(step) diff --git a/GuiManager/Image-Animation/newFullImageLabel.int b/Visual Novel/GuiManager/Image-Animation/newFullImageLabel.int similarity index 100% rename from GuiManager/Image-Animation/newFullImageLabel.int rename to Visual Novel/GuiManager/Image-Animation/newFullImageLabel.int diff --git a/GuiManager/Image-Animation/newImageButton.int b/Visual Novel/GuiManager/Image-Animation/newImageButton.int similarity index 57% rename from GuiManager/Image-Animation/newImageButton.int rename to Visual Novel/GuiManager/Image-Animation/newImageButton.int index 6d0e51d..3b3810b 100644 --- a/GuiManager/Image-Animation/newImageButton.int +++ b/Visual Novel/GuiManager/Image-Animation/newImageButton.int @@ -1,20 +1,10 @@ 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:SetImage(i) 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) diff --git a/Visual Novel/GuiManager/Image-Animation/newImageLabel.int b/Visual Novel/GuiManager/Image-Animation/newImageLabel.int new file mode 100644 index 0000000..db7d0f3 --- /dev/null +++ b/Visual Novel/GuiManager/Image-Animation/newImageLabel.int @@ -0,0 +1,10 @@ +function gui:newImageLabel(i,name, x, y, w, h, sx ,sy ,sw ,sh) + if not name then name = "Imagelabel" end + 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) + c:SetImage(i) + c.Visibility=0 + c.ImageVisibility=1 + c.rotation=0 + return c +end \ No newline at end of file diff --git a/GuiManager/Image-Animation/newVideo.int b/Visual Novel/GuiManager/Image-Animation/newVideo.int similarity index 100% rename from GuiManager/Image-Animation/newVideo.int rename to Visual Novel/GuiManager/Image-Animation/newVideo.int diff --git a/GuiManager/Item/newDragItem.int b/Visual Novel/GuiManager/Item/newDragItem.int similarity index 100% rename from GuiManager/Item/newDragItem.int rename to Visual Novel/GuiManager/Item/newDragItem.int diff --git a/GuiManager/Item/newItem.int b/Visual Novel/GuiManager/Item/newItem.int similarity index 100% rename from GuiManager/Item/newItem.int rename to Visual Novel/GuiManager/Item/newItem.int diff --git a/GuiManager/Misc/AdvTextBox.int b/Visual Novel/GuiManager/Misc/AdvTextBox.int similarity index 100% rename from GuiManager/Misc/AdvTextBox.int rename to Visual Novel/GuiManager/Misc/AdvTextBox.int diff --git a/GuiManager/Misc/ApplyGradient.int b/Visual Novel/GuiManager/Misc/ApplyGradient.int similarity index 93% rename from GuiManager/Misc/ApplyGradient.int rename to Visual Novel/GuiManager/Misc/ApplyGradient.int index e092739..87cb97d 100644 --- a/GuiManager/Misc/ApplyGradient.int +++ b/Visual Novel/GuiManager/Misc/ApplyGradient.int @@ -1,7 +1,7 @@ function _GuiPro.gradient(colors) local direction = colors.direction or "horizontal" colors.direction=nil - trans = colors.trans or 255 + trans = colors.trans or 1 trans=math.floor(trans) if direction == "horizontal" then direction = true @@ -10,7 +10,7 @@ function _GuiPro.gradient(colors) 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) + local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1,"rgba32f") for __i, color in ipairs(colors) do local x, y if direction then diff --git a/GuiManager/Misc/BottomStack.int b/Visual Novel/GuiManager/Misc/BottomStack.int similarity index 100% rename from GuiManager/Misc/BottomStack.int rename to Visual Novel/GuiManager/Misc/BottomStack.int diff --git a/Visual Novel/GuiManager/Misc/ClipDescendants.int b/Visual Novel/GuiManager/Misc/ClipDescendants.int new file mode 100644 index 0000000..c57d96d --- /dev/null +++ b/Visual Novel/GuiManager/Misc/ClipDescendants.int @@ -0,0 +1,18 @@ +function gui:ClipDescendants(bool) + local c = self:GetAllChildren() + if not c[#c] then return end + if bool then + self.clipParent = self.Parent + self.Clipping = true + c[#c].resetClip = true + for i = 1,#c do + c[i].ClipReference = self + end + else + self.Clipping = nil + c[#c].resetClip = nil + for i = 1,#c do + c[i].ClipReference = nil + end + end +end \ No newline at end of file diff --git a/GuiManager/Misc/Destroy.int b/Visual Novel/GuiManager/Misc/Destroy.int similarity index 64% rename from GuiManager/Misc/Destroy.int rename to Visual Novel/GuiManager/Misc/Destroy.int index 9c524f1..dd8f5de 100644 --- a/GuiManager/Misc/Destroy.int +++ b/Visual Novel/GuiManager/Misc/Destroy.int @@ -6,4 +6,8 @@ function gui:Destroy() table.remove(self.Parent.Children,cc) end end + self.Destroyed = true + if #self.Parent.Children==0 then + self.Parent.isLeaf = true + end end \ No newline at end of file diff --git a/GuiManager/Misc/GetAllChildren.int b/Visual Novel/GuiManager/Misc/GetAllChildren.int similarity index 100% rename from GuiManager/Misc/GetAllChildren.int rename to Visual Novel/GuiManager/Misc/GetAllChildren.int diff --git a/GuiManager/Misc/GetChild.int b/Visual Novel/GuiManager/Misc/GetChild.int similarity index 100% rename from GuiManager/Misc/GetChild.int rename to Visual Novel/GuiManager/Misc/GetChild.int diff --git a/GuiManager/Misc/InGrid.int b/Visual Novel/GuiManager/Misc/InGrid.int similarity index 100% rename from GuiManager/Misc/InGrid.int rename to Visual Novel/GuiManager/Misc/InGrid.int diff --git a/GuiManager/Misc/InGridX.int b/Visual Novel/GuiManager/Misc/InGridX.int similarity index 100% rename from GuiManager/Misc/InGridX.int rename to Visual Novel/GuiManager/Misc/InGridX.int diff --git a/GuiManager/Misc/InGridY.int b/Visual Novel/GuiManager/Misc/InGridY.int similarity index 100% rename from GuiManager/Misc/InGridY.int rename to Visual Novel/GuiManager/Misc/InGridY.int diff --git a/GuiManager/Misc/IsHovering.int b/Visual Novel/GuiManager/Misc/IsHovering.int similarity index 100% rename from GuiManager/Misc/IsHovering.int rename to Visual Novel/GuiManager/Misc/IsHovering.int diff --git a/GuiManager/Misc/Move.int b/Visual Novel/GuiManager/Misc/Move.int similarity index 100% rename from GuiManager/Misc/Move.int rename to Visual Novel/GuiManager/Misc/Move.int diff --git a/GuiManager/Misc/SetDualDim.int b/Visual Novel/GuiManager/Misc/SetDualDim.int similarity index 100% rename from GuiManager/Misc/SetDualDim.int rename to Visual Novel/GuiManager/Misc/SetDualDim.int diff --git a/GuiManager/Misc/SetHand.int b/Visual Novel/GuiManager/Misc/SetHand.int similarity index 100% rename from GuiManager/Misc/SetHand.int rename to Visual Novel/GuiManager/Misc/SetHand.int diff --git a/GuiManager/Misc/SetHover.int b/Visual Novel/GuiManager/Misc/SetHover.int similarity index 100% rename from GuiManager/Misc/SetHover.int rename to Visual Novel/GuiManager/Misc/SetHover.int diff --git a/GuiManager/Misc/SetName.int b/Visual Novel/GuiManager/Misc/SetName.int similarity index 100% rename from GuiManager/Misc/SetName.int rename to Visual Novel/GuiManager/Misc/SetName.int diff --git a/Visual Novel/GuiManager/Misc/SquareX.int b/Visual Novel/GuiManager/Misc/SquareX.int new file mode 100644 index 0000000..c846e39 --- /dev/null +++ b/Visual Novel/GuiManager/Misc/SquareX.int @@ -0,0 +1,9 @@ +function gui:SquareX(n) + local n = n or 1 + local w = self.Parent.width + local rw = w*n + local s = (w-rw)/2 + self:setDualDim(self.x+s,self.y+s,rw,rw,sx,sy) + self:Move(s,s) + return self.Parent.width,rw +end \ No newline at end of file diff --git a/Visual Novel/GuiManager/Misc/SquareY.int b/Visual Novel/GuiManager/Misc/SquareY.int new file mode 100644 index 0000000..c90020b --- /dev/null +++ b/Visual Novel/GuiManager/Misc/SquareY.int @@ -0,0 +1,9 @@ +function gui:SquareY(n) + local n = n or 1 + local w = self.Parent.height + local rw = w*n + local s = (w-rw)/2 + self:setDualDim(nil,nil,rw,rw) + self:Move(s,s) + return self.Parent.height,rw +end \ No newline at end of file diff --git a/GuiManager/Misc/TopStack.int b/Visual Novel/GuiManager/Misc/TopStack.int similarity index 100% rename from GuiManager/Misc/TopStack.int rename to Visual Novel/GuiManager/Misc/TopStack.int diff --git a/GuiManager/Image-Animation/UpdateImage.int b/Visual Novel/GuiManager/Misc/UpdateImage.int similarity index 100% rename from GuiManager/Image-Animation/UpdateImage.int rename to Visual Novel/GuiManager/Misc/UpdateImage.int diff --git a/Libs/Utils.lua b/Visual Novel/GuiManager/Misc/Utils.int similarity index 100% rename from Libs/Utils.lua rename to Visual Novel/GuiManager/Misc/Utils.int diff --git a/Visual Novel/GuiManager/Misc/addDominance.int b/Visual Novel/GuiManager/Misc/addDominance.int new file mode 100644 index 0000000..e01c1b1 --- /dev/null +++ b/Visual Novel/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/alphanumsort.int b/Visual Novel/GuiManager/Misc/alphanumsort.int similarity index 100% rename from GuiManager/Misc/alphanumsort.int rename to Visual Novel/GuiManager/Misc/alphanumsort.int diff --git a/GuiManager/Misc/anchorRight.int b/Visual Novel/GuiManager/Misc/anchorRight.int similarity index 100% rename from GuiManager/Misc/anchorRight.int rename to Visual Novel/GuiManager/Misc/anchorRight.int diff --git a/Visual Novel/GuiManager/Misc/center.int b/Visual Novel/GuiManager/Misc/center.int new file mode 100644 index 0000000..fb22fea --- /dev/null +++ b/Visual Novel/GuiManager/Misc/center.int @@ -0,0 +1,4 @@ +function gui:center() + self:centerX() + self:centerY() +end \ No newline at end of file diff --git a/GuiManager/Misc/centerX.int b/Visual Novel/GuiManager/Misc/centerX.int similarity index 100% rename from GuiManager/Misc/centerX.int rename to Visual Novel/GuiManager/Misc/centerX.int diff --git a/GuiManager/Misc/centerY.int b/Visual Novel/GuiManager/Misc/centerY.int similarity index 100% rename from GuiManager/Misc/centerY.int rename to Visual Novel/GuiManager/Misc/centerY.int diff --git a/GuiManager/Misc/disrespectHierarchy.int b/Visual Novel/GuiManager/Misc/disrespectHierarchy.int similarity index 100% rename from GuiManager/Misc/disrespectHierarchy.int rename to Visual Novel/GuiManager/Misc/disrespectHierarchy.int diff --git a/GuiManager/Misc/getChildren.int b/Visual Novel/GuiManager/Misc/getChildren.int similarity index 100% rename from GuiManager/Misc/getChildren.int rename to Visual Novel/GuiManager/Misc/getChildren.int diff --git a/GuiManager/Misc/getColor.int b/Visual Novel/GuiManager/Misc/getColor.int similarity index 100% rename from GuiManager/Misc/getColor.int rename to Visual Novel/GuiManager/Misc/getColor.int diff --git a/Visual Novel/GuiManager/Misc/getFullSize.int b/Visual Novel/GuiManager/Misc/getFullSize.int new file mode 100644 index 0000000..62c6221 --- /dev/null +++ b/Visual Novel/GuiManager/Misc/getFullSize.int @@ -0,0 +1,14 @@ +function gui:getFullSize() + local maxx,maxy=self.width,self.height + local px,py=self.x,self.y + local temp = self:GetAllChildren() + for i=1,#temp do + if temp[i].width+temp[i].x>maxx then + maxx=temp[i].width+temp[i].x + end + if temp[i].height+temp[i].y>maxy then + maxy=temp[i].height+temp[i].y + end + end + return maxx,maxy,px,py +end \ No newline at end of file diff --git a/GuiManager/Misc/getHighest.int b/Visual Novel/GuiManager/Misc/getHighest.int similarity index 100% rename from GuiManager/Misc/getHighest.int rename to Visual Novel/GuiManager/Misc/getHighest.int diff --git a/GuiManager/Misc/getLowest.int b/Visual Novel/GuiManager/Misc/getLowest.int similarity index 100% rename from GuiManager/Misc/getLowest.int rename to Visual Novel/GuiManager/Misc/getLowest.int diff --git a/GuiManager/Image-Animation/getTile.int b/Visual Novel/GuiManager/Misc/getTile.int similarity index 100% rename from GuiManager/Image-Animation/getTile.int rename to Visual Novel/GuiManager/Misc/getTile.int diff --git a/GuiManager/Misc/isDescendant.int b/Visual Novel/GuiManager/Misc/isDescendant.int similarity index 57% rename from GuiManager/Misc/isDescendant.int rename to Visual Novel/GuiManager/Misc/isDescendant.int index 5c9c2a5..f004182 100644 --- a/GuiManager/Misc/isDescendant.int +++ b/Visual Novel/GuiManager/Misc/isDescendant.int @@ -1,7 +1,7 @@ function gui:isDescendant(obj) - local things=obj:GetAllChildren() + local things = obj:GetAllChildren() for i=1,#things do - if things[i]==self then + if things[i] == self then return true end end diff --git a/GuiManager/Misc/isHighest.int b/Visual Novel/GuiManager/Misc/isHighest.int similarity index 100% rename from GuiManager/Misc/isHighest.int rename to Visual Novel/GuiManager/Misc/isHighest.int diff --git a/GuiManager/Misc/isLowest.int b/Visual Novel/GuiManager/Misc/isLowest.int similarity index 100% rename from GuiManager/Misc/isLowest.int rename to Visual Novel/GuiManager/Misc/isLowest.int diff --git a/GuiManager/Misc/massMutate.int b/Visual Novel/GuiManager/Misc/massMutate.int similarity index 100% rename from GuiManager/Misc/massMutate.int rename to Visual Novel/GuiManager/Misc/massMutate.int diff --git a/GuiManager/Misc/newCheckBox.int b/Visual Novel/GuiManager/Misc/newCheckBox.int similarity index 94% rename from GuiManager/Misc/newCheckBox.int rename to Visual Novel/GuiManager/Misc/newCheckBox.int index ccd530c..607d5d9 100644 --- a/GuiManager/Misc/newCheckBox.int +++ b/Visual Novel/GuiManager/Misc/newCheckBox.int @@ -1,4 +1,4 @@ -if love.filesystem.exists("CheckBoxes.png") then +if love.filesystem.getInfo("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) diff --git a/GuiManager/Misc/newMessageBox.int b/Visual Novel/GuiManager/Misc/newMessageBox.int similarity index 100% rename from GuiManager/Misc/newMessageBox.int rename to Visual Novel/GuiManager/Misc/newMessageBox.int diff --git a/GuiManager/Misc/newPart.int b/Visual Novel/GuiManager/Misc/newPart.int similarity index 100% rename from GuiManager/Misc/newPart.int rename to Visual Novel/GuiManager/Misc/newPart.int diff --git a/GuiManager/Misc/newProgressBar.int b/Visual Novel/GuiManager/Misc/newProgressBar.int similarity index 100% rename from GuiManager/Misc/newProgressBar.int rename to Visual Novel/GuiManager/Misc/newProgressBar.int diff --git a/GuiManager/Misc/newScrollBar.int b/Visual Novel/GuiManager/Misc/newScrollBar.int similarity index 100% rename from GuiManager/Misc/newScrollBar.int rename to Visual Novel/GuiManager/Misc/newScrollBar.int diff --git a/Visual Novel/GuiManager/Misc/newScrollMenu.int b/Visual Novel/GuiManager/Misc/newScrollMenu.int new file mode 100644 index 0000000..f7ee5ac --- /dev/null +++ b/Visual Novel/GuiManager/Misc/newScrollMenu.int @@ -0,0 +1,81 @@ +function gui:newScrollMenu(name) + local temp = self:newFullFrame(name) + temp.ref = { + [[setNewFont(16)]], + [[setRoundness(10,10,180)]], + Tween = 6 + } + temp.allowOverlapping = true + temp.Visibility = 0 + local ScrollY = temp:newFrame(name.."ScrollY",-20,0,20,0,1,0,0,1) + temp.scroll = ScrollY + ScrollY.Color=Color.new(80,80,80) + ScrollY.allowOverlapping = true + ScrollY.Mover = ScrollY:newFrame(name.."MoverY",5,5,10,80) + ScrollY.Mover.Color = Color.new(60,60,60) + local func = function(b,self,x,y,nn) + temp.symbolicY = y + if y>45 and yScrollY.height-40 then + temp.symbolicY = ScrollY.height-40 + end + func("l",ScrollY,x,temp.symbolicY,true) + end) + temp.ClipDescendants=true + temp.first = temp:newTextLabel("","",15,10,-50,40,0,0,1) + local nice = temp:newTextLabel(name,name,15,10,-50,40,0,0,1) + temp.header = nice + temp.last = temp.first + temp.last.BorderSize = 0 + temp.last.Visibility = 0 + nice:setNewFont(26) + nice.Tween = 6 + temp.list = {} + local alarm + multi:newLoop(function() + for i=1,#temp.list do + local val = (temp.first.y+(temp.list[i].staticpos)+10) + if val>temp.y and val self.x+width then + curpos = #hiddenText+1 + elseif x < self.x then + curpos = 1 + else + for i = 1,#hiddenText do + width = self.Font:getWidth(self.text:sub(1,i)) + if x-self.x < width then + curpos = i + break + end + end + end + end) + c:OnPressedOuter(function(b,self) + if Focused then + self:unfocus() + end + end) + c:OnUpdate(function(self) + if #hiddenText==0 then self.text = "" return end + if self.hideText then + self.text = table.concat(hiddenText) + else + self.text = table.concat(realText) + end + self.TextFormat = "left" + end) + multi.OnTextInput(function(t) + table.insert(hiddenText,curpos,"*") + table.insert(realText,curpos,t) + curpos = curpos + 1 + if autoScaleFont then + c:fitFont() + end + end) + multi.OnKeyPressed(function(key, scancode, isrepeat ) + if key == "backspace" then + table.remove(hiddenText,curpos-1) + table.remove(realText,curpos-1) + curpos = curpos - 1 + if curpos < 1 then + curpos = 1 + end + if autoScaleFont then + c:fitFont() + end + elseif key == "enter" then + + elseif key == "delete" then + realText = {} + hiddenText = {} + curpos = 1 + elseif key == "left" then + curpos = curpos - 1 + if curpos < 1 then + curpos = 1 + end + moved = true + alarm:Reset() + elseif key == "right" then + curpos = curpos + 1 + if curpos > #realText+1 then + curpos = #realText+1 + end + moved = true + alarm:Reset() + end + end) + local blink = false + multi:newThread("TextCursonBlinker",function() + while true do + thread.sleep(1.5) + blink = not blink + end + end) + self.DrawRulesE = {function() + if --[[blink or moved]] true then + local width = c.Font:getWidth(c.text:sub(1,curpos-1)) + local height = c.Font:getHeight() + if c.TextFormat == "center" then + -- print(c.x+(c.width/2+width),c.height,c.x+(c.width/2+width),c.height+height) + -- love.graphics.line(c.x+(c.width/2+width),c.height,c.x+(c.width/2+width),c.height+height) + elseif c.TextFormat == "right" then + --love.graphics.line(c.x+width,c.y,c.x+width,c.y+c.Font:getHeight()) + elseif c.TextFormat == "left" then + love.graphics.line(c.x+width,c.y,c.x+width,c.y+height) + end + end + end} + return c +end \ No newline at end of file diff --git a/Visual Novel/GuiManager/Text/newTextButton.int b/Visual Novel/GuiManager/Text/newTextButton.int new file mode 100644 index 0000000..be43ef0 --- /dev/null +++ b/Visual Novel/GuiManager/Text/newTextButton.int @@ -0,0 +1,11 @@ +function gui:newTextButton(t,name, x, y, w, h, sx ,sy ,sw ,sh) + local x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newTextBase("TextButton",t,name, x, y, w, h, sx ,sy ,sw ,sh) + c:OnMouseEnter(function() + love.mouse.setCursor(_GuiPro.CursorH) + end) + c:OnMouseExit(function() + love.mouse.setCursor(_GuiPro.CursorN) + end) + return c +end \ No newline at end of file diff --git a/Visual Novel/GuiManager/Text/newTextLabel.int b/Visual Novel/GuiManager/Text/newTextLabel.int new file mode 100644 index 0000000..679224d --- /dev/null +++ b/Visual Novel/GuiManager/Text/newTextLabel.int @@ -0,0 +1,4 @@ +function gui:newTextLabel(t,name, x, y, w, h, sx ,sy ,sw ,sh) + local x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + return self:newTextBase("TextLabel",t,name, x, y, w, h, sx ,sy ,sw ,sh) +end \ No newline at end of file diff --git a/GuiManager/Misc/setDefualtFont.int b/Visual Novel/GuiManager/Text/setDefualtFont.int similarity index 100% rename from GuiManager/Misc/setDefualtFont.int rename to Visual Novel/GuiManager/Text/setDefualtFont.int diff --git a/Visual Novel/GuiManager/Text/setNewFont.int b/Visual Novel/GuiManager/Text/setNewFont.int new file mode 100644 index 0000000..9b0c840 --- /dev/null +++ b/Visual Novel/GuiManager/Text/setNewFont.int @@ -0,0 +1,9 @@ +function gui:setNewFont(filename,FontSize) + if type(filename)=="string" then + self.FontFile = filename + self.Font = love.graphics.newFont(filename, tonumber(FontSize)) + else + self.Font=love.graphics.newFont(tonumber(filename)) + end + self.Font:setFilter("linear","nearest",4) +end \ No newline at end of file diff --git a/GuiManager/Misc/setgetText.int b/Visual Novel/GuiManager/Text/setgetText.int similarity index 100% rename from GuiManager/Misc/setgetText.int rename to Visual Novel/GuiManager/Text/setgetText.int diff --git a/Visual Novel/GuiManager/Text/widthToTextSize.int b/Visual Novel/GuiManager/Text/widthToTextSize.int new file mode 100644 index 0000000..a36b6dc --- /dev/null +++ b/Visual Novel/GuiManager/Text/widthToTextSize.int @@ -0,0 +1,5 @@ +function gui:widthToTextSize(n) + if self.Font then + self:setDualDim(nil,nil,self.Font:getWidth(self.text)+(n or 4),nil,nil,nil,0) + end +end \ No newline at end of file diff --git a/GuiManager/init.lua b/Visual Novel/GuiManager/init.lua similarity index 53% rename from GuiManager/init.lua rename to Visual Novel/GuiManager/init.lua index c9c33db..a1d65f0 100644 --- a/GuiManager/init.lua +++ b/Visual Novel/GuiManager/init.lua @@ -1,23 +1,45 @@ +local multi = require("multi") +local GLOBAL,THREAD=require("multi.integration.loveManager").init() +local p = print +print = multi.print +-- automatic resource loading will be added soonish 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={ + GLOBAL = GLOBAL, + THREAD = THREAD, + jobqueue = multi:newSystemThreadedJobQueue("ImageJobQueue"), + imagecache = {}, + GBoost=true, + hasDrag=false, + DragItem={}, + Children={}, + Visible=true, + count=0, + x=0, + y=0, + height=0, + width=0, + getChildren=function(self) + return self.Children + end +} _GuiPro.Clips={} _GuiPro.rotate=0 +_defaultfont = love.graphics.setNewFont(12) 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 + if love.filesystem.getInfo(file..add) then a,b=pcall(love.filesystem.load(file..add)) if a then - print("Loaded: "..file) + --print("Loaded: "..file) else - print("Error loading file: "..file) - print(a,b) + print("Error loading file: "..file,b) end else print("File does not exist!") @@ -42,15 +64,19 @@ 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) +multi:newLoop(function() _GuiPro.width,_GuiPro.height=love.graphics.getDimensions() end):setName("gui.mainUpdater") +multi:onDraw(function() + local items=GetAllChildren(_GuiPro) + for i=1,#items do + items[i]:draw() + end +end) gui.ff=gui:newFrame("",0,0,0,0,0,0,1,1) -gui.ff.Color={255,255,255} +gui.ff.Color={0,0,0} gui.ff:OnUpdate(function(self) self:BottomStack() end) +print = p diff --git a/Libs/AudioManager.lua b/Visual Novel/Libs/AudioManager.lua similarity index 96% rename from Libs/AudioManager.lua rename to Visual Novel/Libs/AudioManager.lua index fceda6c..84a807f 100644 --- a/Libs/AudioManager.lua +++ b/Visual Novel/Libs/AudioManager.lua @@ -1,11 +1,12 @@ -audio = {} +local audio = {} audio.__index = audio function audio:new(f,t) + t=t or "stream" local obj={} setmetatable(obj, audio) obj.source=love.audio.newSource(f,t) obj.f=f - obj.t=t or "stream" + obj.t=t obj.endEvent=multi:newLoop() obj.endEvent.Pare=obj obj.wasPlaying=false @@ -13,7 +14,7 @@ function audio:new(f,t) obj.func2={} obj.func3={} obj.func4={} - obj.endEvent:OnLoop(function(time,loop) + obj.endEvent:OnLoop(function(loop,time) 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() @@ -59,7 +60,7 @@ function audio:pause() self.source:pause() end function audio:resume() - self.source:resume() + self.source:play() end function audio:rewind() self.source:rewind() @@ -105,7 +106,7 @@ function audio:isPlaying() return self.source:isPlaying() end function audio:isPaused() - return self.source:isPaused() + return not self.source:isPlaying() end function audio:isStopped() return self.source:isStopped() @@ -171,6 +172,7 @@ end function audio:onStop(func) table.insert(self.func,func) end +return audio --[[ Object:type |Done Object:typeOf |Done diff --git a/Libs/Library.lua b/Visual Novel/Libs/Library.lua similarity index 100% rename from Libs/Library.lua rename to Visual Novel/Libs/Library.lua diff --git a/Visual Novel/bin/compressors/lzw.lua b/Visual Novel/bin/compressors/lzw.lua new file mode 100644 index 0000000..57653b3 --- /dev/null +++ b/Visual Novel/bin/compressors/lzw.lua @@ -0,0 +1,73 @@ +--[[ +LZW String Compression demo for Gideros +This code is MIT licensed, see http://www.opensource.org/licenses/mit-license.php +(C) 2013 - Guava7 +]] +CLZWCompression = {} +function CLZWCompression:InitDictionary(isEncode) + self.mDictionary = {} + -- local s = " !#$%&'\"()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + local s={} + for i=1,255 do + s[#s+1]=string.char(i) + end + s=table.concat(s) + local len = #s + for i = 1, len do + if isEncode then + self.mDictionary[s:sub(i, i)] = i + else + self.mDictionary[i] = s:sub(i, i) + end + end + self.mDictionaryLen = len +end +function CLZWCompression:Encode(sInput) + self:InitDictionary(true) + local s = "" + local ch + local len = #sInput + local result = {} + local dic = self.mDictionary + local temp + for i = 1, len do + ch = sInput:sub(i, i) + temp = s..ch + if dic[temp] then + s = temp + else + result[#result + 1] = dic[s] + self.mDictionaryLen = self.mDictionaryLen + 1 + dic[temp] = self.mDictionaryLen + s = ch + end + end + result[#result + 1] = dic[s] + return result +end +function CLZWCompression:Decode(data) + self:InitDictionary(false) + local dic = self.mDictionary + local entry + local ch + local prevCode, currCode + local result = {} + prevCode = data[1] + result[#result + 1] = dic[prevCode] + for i = 2, #data do + currCode = data[i] + entry = dic[currCode] + if entry then + ch = entry:sub(1, 1) + result[#result + 1] = entry + else + ch = dic[prevCode]:sub(1, 1) + result[#result + 1] = dic[prevCode]..ch + end + dic[#dic + 1] = dic[prevCode]..ch + prevCode = currCode + end + return table.concat(result) +end + +return CLZWCompression diff --git a/Visual Novel/bin/converters/base64.lua b/Visual Novel/bin/converters/base64.lua new file mode 100644 index 0000000..d66cc90 --- /dev/null +++ b/Visual Novel/bin/converters/base64.lua @@ -0,0 +1,40 @@ +local bin = require("bin") +local base64={} +local bs = { [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','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','0','1','2','3','4','5','6','7','8','9','+','/', +} +local bsd=table.flip(bs) +local char=string.char +function base64.encode(s) + local byte, rep, pad = string.byte, string.rep, 2 - ((#s-1) % 3) + s = (s..rep('\0', pad)):gsub("...", function(cs) + local a, b, c = byte(cs, 1, 3) + return bs[bit.rshift(a,2)] .. bs[bit.bor(bit.lshift(bit.band(a,3),4),bit.rshift(b,4))] .. bs[bit.bor(bit.lshift(bit.band(b,15),2),bit.rshift(c,6))] .. bs[bit.band(c,63)] + end) + return s:sub(1, #s-pad) .. rep('=', pad) +end +function base64.decode(s) + local s=s:match("["..s.."=]+") + local p,cc=s:gsub("=","A") + local r="" + local n=0 + s=s:sub(1,#s-#p)..p + for c = 1,#s,4 do + n = bit.lshift(bsd[s:sub(c, c)], 18) + bit.lshift(bsd[s:sub(c+1, c+1)], 12) + bit.lshift(bsd[s:sub(c + 2, c + 2)], 6) + bsd[s:sub(c + 3, c + 3)] + r = r .. char(bit.band(bit.arshift(n, 16), 0xFF)) .. char(bit.band(bit.arshift(n, 8), 0xFF)) .. char(bit.band(n, 0xFF)) + end + return r:sub(1,-(cc+1)) +end +function bin.newFromBase91(data) + return bin.new(bin.fromBase91(data)) +end +function bin.toBase91(s) + return base91.encode(s) +end +function bin.fromBase91(s) + return base91.decode(s) +end +return base64 diff --git a/Visual Novel/bin/converters/base91.lua b/Visual Novel/bin/converters/base91.lua new file mode 100644 index 0000000..cb2f447 --- /dev/null +++ b/Visual Novel/bin/converters/base91.lua @@ -0,0 +1,82 @@ +local bin = require("bin") +local base91={} +local b91enc={[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', + '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', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '#', '$', + '%', '&', '(', ')', '*', '+', ',', '.', '/', ':', ';', '<', '=', + '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~', '"' +} +local b91dec=table.flip(b91enc) +function base91.decode(d) + local l,v,o,b,n = #d,-1,"",0,0 + for i in d:gmatch(".") do + local c=b91dec[i] + if not(c) then + -- Continue + else + if v < 0 then + v = c + else + v = v+c*91 + b = bit.bor(b, bit.lshift(v,n)) + if bit.band(v,8191) then + n = n + 13 + else + n = n + 14 + end + while true do + o=o..string.char(bit.band(b,255)) + b=bit.rshift(b,8) + n=n-8 + if not (n>7) then + break + end + end + v=-1 + end + end + end + if v + 1>0 then + o=o..string.char(bit.band(bit.bor(b,bit.lshift(v,n)),255)) + end + return o +end +function base91.encode(d) + local b,n,o,l=0,0,"",#d + for i in d:gmatch(".") do + b=bit.bor(b,bit.lshift(string.byte(i),n)) + n=n+8 + if n>13 then + v=bit.band(b,8191) + if v>88 then + b=bit.rshift(b,13) + n=n-13 + else + v=bit.band(b,16383) + b=bit.rshift(b,14) + n=n-14 + end + o=o..b91enc[v % 91] .. b91enc[math.floor(v / 91)] + end + end + if n>0 then + o=o..b91enc[b % 91] + if n>7 or b>90 then + o=o .. b91enc[math.floor(b / 91)] + end + end + return o +end +function bin.newFromBase64(data) + return bin.new(bin.fromBase64(data)) +end +function bin.toBase64(s) + return base64.encode(s) +end +function bin.fromBase64(s) + return base64.decode(s) +end +return base91 diff --git a/Visual Novel/bin/hashes/md5.lua b/Visual Novel/bin/hashes/md5.lua new file mode 100644 index 0000000..c2cc716 --- /dev/null +++ b/Visual Novel/bin/hashes/md5.lua @@ -0,0 +1,394 @@ +local bin = require("bin") +local md5 = { + _VERSION = "md5.lua 1.1.0", + _DESCRIPTION = "MD5 computation in Lua (5.1-3, LuaJIT)", + _URL = "https://github.com/kikito/md5.lua", + _LICENSE = [[ + MIT LICENSE + + Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software + ]] +} + +-- bit lib implementions + +local char, byte, format, rep, sub = + string.char, string.byte, string.format, string.rep, string.sub +local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift + +local ok, bit = pcall(require, 'bit') +if ok then + bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift = bit.bor, bit.band, bit.bnot, bit.bxor, bit.rshift, bit.lshift +else + ok, bit = pcall(require, 'bit32') + + if ok then + + bit_not = bit.bnot + + local tobit = function(n) + return n <= 0x7fffffff and n or -(bit_not(n) + 1) + end + + local normalize = function(f) + return function(a,b) return tobit(f(tobit(a), tobit(b))) end + end + + bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor) + bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift) + + else + + local function tbl2number(tbl) + local result = 0 + local power = 1 + for i = 1, #tbl do + result = result + tbl[i] * power + power = power * 2 + end + return result + end + + local function expand(t1, t2) + local big, small = t1, t2 + if(#big < #small) then + big, small = small, big + end + -- expand small + for i = #small + 1, #big do + small[i] = 0 + end + end + + local to_bits -- needs to be declared before bit_not + + bit_not = function(n) + local tbl = to_bits(n) + local size = math.max(#tbl, 32) + for i = 1, size do + if(tbl[i] == 1) then + tbl[i] = 0 + else + tbl[i] = 1 + end + end + return tbl2number(tbl) + end + + -- defined as local above + to_bits = function (n) + if(n < 0) then + -- negative + return to_bits(bit_not(math.abs(n)) + 1) + end + -- to bits table + local tbl = {} + local cnt = 1 + local last + while n > 0 do + last = n % 2 + tbl[cnt] = last + n = (n-last)/2 + cnt = cnt + 1 + end + + return tbl + end + + bit_or = function(m, n) + local tbl_m = to_bits(m) + local tbl_n = to_bits(n) + expand(tbl_m, tbl_n) + + local tbl = {} + for i = 1, #tbl_m do + if(tbl_m[i]== 0 and tbl_n[i] == 0) then + tbl[i] = 0 + else + tbl[i] = 1 + end + end + + return tbl2number(tbl) + end + + bit_and = function(m, n) + local tbl_m = to_bits(m) + local tbl_n = to_bits(n) + expand(tbl_m, tbl_n) + + local tbl = {} + for i = 1, #tbl_m do + if(tbl_m[i]== 0 or tbl_n[i] == 0) then + tbl[i] = 0 + else + tbl[i] = 1 + end + end + + return tbl2number(tbl) + end + + bit_xor = function(m, n) + local tbl_m = to_bits(m) + local tbl_n = to_bits(n) + expand(tbl_m, tbl_n) + + local tbl = {} + for i = 1, #tbl_m do + if(tbl_m[i] ~= tbl_n[i]) then + tbl[i] = 1 + else + tbl[i] = 0 + end + end + + return tbl2number(tbl) + end + + bit_rshift = function(n, bits) + local high_bit = 0 + if(n < 0) then + -- negative + n = bit_not(math.abs(n)) + 1 + high_bit = 0x80000000 + end + + local floor = math.floor + + for i=1, bits do + n = n/2 + n = bit_or(floor(n), high_bit) + end + return floor(n) + end + + bit_lshift = function(n, bits) + if(n < 0) then + -- negative + n = bit_not(math.abs(n)) + 1 + end + + for i=1, bits do + n = n*2 + end + return bit_and(n, 0xFFFFFFFF) + end + end +end + +-- convert little-endian 32-bit int to a 4-char string +local function lei2str(i) + local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end + return f(0)..f(8)..f(16)..f(24) +end + +-- convert raw string to big-endian int +local function str2bei(s) + local v=0 + for i=1, #s do + v = v * 256 + byte(s, i) + end + return v +end + +-- convert raw string to little-endian int +local function str2lei(s) + local v=0 + for i = #s,1,-1 do + v = v*256 + byte(s, i) + end + return v +end + +-- cut up a string in little-endian ints of given size +local function cut_le_str(s,...) + local o, r = 1, {} + local args = {...} + for i=1, #args do + table.insert(r, str2lei(sub(s, o, o + args[i] - 1))) + o = o + args[i] + end + return r +end + +local swap = function (w) return str2bei(lei2str(w)) end + +-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh) +-- 10/02/2001 jcw@equi4.com + +local CONSTS = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 +} + +local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end +local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end +local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end +local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end +local z=function (ff,a,b,c,d,x,s,ac) + a=bit_and(a+ff(b,c,d)+x+ac,0xFFFFFFFF) + -- be *very* careful that left shift does not cause rounding! + return bit_or(bit_lshift(bit_and(a,bit_rshift(0xFFFFFFFF,s)),s),bit_rshift(a,32-s))+b +end + +local function transform(A,B,C,D,X) + local a,b,c,d=A,B,C,D + local t=CONSTS + + a=z(f,a,b,c,d,X[ 0], 7,t[ 1]) + d=z(f,d,a,b,c,X[ 1],12,t[ 2]) + c=z(f,c,d,a,b,X[ 2],17,t[ 3]) + b=z(f,b,c,d,a,X[ 3],22,t[ 4]) + a=z(f,a,b,c,d,X[ 4], 7,t[ 5]) + d=z(f,d,a,b,c,X[ 5],12,t[ 6]) + c=z(f,c,d,a,b,X[ 6],17,t[ 7]) + b=z(f,b,c,d,a,X[ 7],22,t[ 8]) + a=z(f,a,b,c,d,X[ 8], 7,t[ 9]) + d=z(f,d,a,b,c,X[ 9],12,t[10]) + c=z(f,c,d,a,b,X[10],17,t[11]) + b=z(f,b,c,d,a,X[11],22,t[12]) + a=z(f,a,b,c,d,X[12], 7,t[13]) + d=z(f,d,a,b,c,X[13],12,t[14]) + c=z(f,c,d,a,b,X[14],17,t[15]) + b=z(f,b,c,d,a,X[15],22,t[16]) + + a=z(g,a,b,c,d,X[ 1], 5,t[17]) + d=z(g,d,a,b,c,X[ 6], 9,t[18]) + c=z(g,c,d,a,b,X[11],14,t[19]) + b=z(g,b,c,d,a,X[ 0],20,t[20]) + a=z(g,a,b,c,d,X[ 5], 5,t[21]) + d=z(g,d,a,b,c,X[10], 9,t[22]) + c=z(g,c,d,a,b,X[15],14,t[23]) + b=z(g,b,c,d,a,X[ 4],20,t[24]) + a=z(g,a,b,c,d,X[ 9], 5,t[25]) + d=z(g,d,a,b,c,X[14], 9,t[26]) + c=z(g,c,d,a,b,X[ 3],14,t[27]) + b=z(g,b,c,d,a,X[ 8],20,t[28]) + a=z(g,a,b,c,d,X[13], 5,t[29]) + d=z(g,d,a,b,c,X[ 2], 9,t[30]) + c=z(g,c,d,a,b,X[ 7],14,t[31]) + b=z(g,b,c,d,a,X[12],20,t[32]) + + a=z(h,a,b,c,d,X[ 5], 4,t[33]) + d=z(h,d,a,b,c,X[ 8],11,t[34]) + c=z(h,c,d,a,b,X[11],16,t[35]) + b=z(h,b,c,d,a,X[14],23,t[36]) + a=z(h,a,b,c,d,X[ 1], 4,t[37]) + d=z(h,d,a,b,c,X[ 4],11,t[38]) + c=z(h,c,d,a,b,X[ 7],16,t[39]) + b=z(h,b,c,d,a,X[10],23,t[40]) + a=z(h,a,b,c,d,X[13], 4,t[41]) + d=z(h,d,a,b,c,X[ 0],11,t[42]) + c=z(h,c,d,a,b,X[ 3],16,t[43]) + b=z(h,b,c,d,a,X[ 6],23,t[44]) + a=z(h,a,b,c,d,X[ 9], 4,t[45]) + d=z(h,d,a,b,c,X[12],11,t[46]) + c=z(h,c,d,a,b,X[15],16,t[47]) + b=z(h,b,c,d,a,X[ 2],23,t[48]) + + a=z(i,a,b,c,d,X[ 0], 6,t[49]) + d=z(i,d,a,b,c,X[ 7],10,t[50]) + c=z(i,c,d,a,b,X[14],15,t[51]) + b=z(i,b,c,d,a,X[ 5],21,t[52]) + a=z(i,a,b,c,d,X[12], 6,t[53]) + d=z(i,d,a,b,c,X[ 3],10,t[54]) + c=z(i,c,d,a,b,X[10],15,t[55]) + b=z(i,b,c,d,a,X[ 1],21,t[56]) + a=z(i,a,b,c,d,X[ 8], 6,t[57]) + d=z(i,d,a,b,c,X[15],10,t[58]) + c=z(i,c,d,a,b,X[ 6],15,t[59]) + b=z(i,b,c,d,a,X[13],21,t[60]) + a=z(i,a,b,c,d,X[ 4], 6,t[61]) + d=z(i,d,a,b,c,X[11],10,t[62]) + c=z(i,c,d,a,b,X[ 2],15,t[63]) + b=z(i,b,c,d,a,X[ 9],21,t[64]) + + return bit_and(A+a,0xFFFFFFFF),bit_and(B+b,0xFFFFFFFF), + bit_and(C+c,0xFFFFFFFF),bit_and(D+d,0xFFFFFFFF) +end + +---------------------------------------------------------------- + +local function md5_update(self, s) + self.pos = self.pos + #s + s = self.buf .. s + for ii = 1, #s - 63, 64 do + local X = cut_le_str(sub(s,ii,ii+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4) + assert(#X == 16) + X[0] = table.remove(X,1) -- zero based! + self.a,self.b,self.c,self.d = transform(self.a,self.b,self.c,self.d,X) + end + self.buf = sub(s, math.floor(#s/64)*64 + 1, #s) + return self +end + +local function md5_finish(self) + local msgLen = self.pos + local padLen = 56 - msgLen % 64 + + if msgLen % 64 > 56 then padLen = padLen + 64 end + + if padLen == 0 then padLen = 64 end + + local s = char(128) .. rep(char(0),padLen-1) .. lei2str(bit_and(8*msgLen, 0xFFFFFFFF)) .. lei2str(math.floor(msgLen/0x20000000)) + md5_update(self, s) + + assert(self.pos % 64 == 0) + return lei2str(self.a) .. lei2str(self.b) .. lei2str(self.c) .. lei2str(self.d) +end + +---------------------------------------------------------------- + +function md5.new() + return { a = CONSTS[65], b = CONSTS[66], c = CONSTS[67], d = CONSTS[68], + pos = 0, + buf = '', + update = md5_update, + finish = md5_finish } +end + +function md5.tohex(s) + return format("%08x%08x%08x%08x", str2bei(sub(s, 1, 4)), str2bei(sub(s, 5, 8)), str2bei(sub(s, 9, 12)), str2bei(sub(s, 13, 16))) +end + +function md5.sum(s) + return md5.new():update(s):finish() +end + +function md5.sumhexa(s) + return md5.tohex(md5.sum(s)) +end +bin.md5 = md5 +function bin:getMD5Hash() + self:setSeek(1) + local len=self:getSize() + local md5=bin.md5.new() + local SIZE=2048 + if len>SIZE then + local dat=self:read(SIZE) + while dat~=nil do + md5:update(dat) + dat=self:read(SIZE) + end + return bin.md5.tohex(md5:finish()):upper() + else + return bin.md5.sumhexa(self:getData()):upper() + end +end +return md5 diff --git a/Visual Novel/bin/init.lua b/Visual Novel/bin/init.lua new file mode 100644 index 0000000..e646d1c --- /dev/null +++ b/Visual Novel/bin/init.lua @@ -0,0 +1,1432 @@ +local bin={} +bin.Version={6,0,0} +bin.stage='stable' +bin.data='' +bin.t='bin' +bin.__index = bin +bin.__tostring=function(self) return self:getData() end +bin.__len=function(self) return self:getlength() end +bin.lastBlockSize=0 +bin.streams={} +-- Helpers +function bin.getVersion() + return bin.Version[1]..'.'..bin.Version[2]..'.'..bin.Version[3] +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) + elseif type(v) == 'boolean' then + print(formatting .. tostring(v)) + else + print(formatting .. tostring(v)) + end + end +end +function table.flip(t) + local tt={} + for i,v in pairs(t) do + tt[v]=i + end + return tt +end +function toFraction(n) + local w,p=math.modf(n) + if p~=0 then + p=tonumber(tostring(p):sub(3)) + end + return w,p +end +function io.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 #str1 or #d<1 then + error("A byte must be one character!") + else + c.data=string.byte(d) + end + elseif type(d)=="number" then + if d>255 or d<0 then + error("A byte must be between 0 and 255!") + else + c.data=d + end + else + error("cannot use type "..type(d).." as an argument! Takes only strings or numbers!") + end + c.__index=function(self,k) + if k>=0 and k<9 then + if self.data==0 then + return 0 + elseif self.data==255 then + return 1 + else + return bits.ref[self.data][k] + end + end + end + c.__tostring=function(self) + return bits.ref[tostring(self.data)] + end + setmetatable(c,c) + return c +end +function bits.newByteArray(s) + local c={} + if type(s)~="string" then + error("Must be a string type or bin/buffer type") + elseif type(s)=="table" then + if s.t=="sink" or s.t=="buffer" or s.t=="bin" then + local data=s:getData() + for i=1,#data do + c[#c+1]=bits.newByte(data:sub(i,i)) + end + else + error("Must be a string type or bin/buffer type") + end + else + for i=1,#s do + c[#c+1]=bits.newByte(s:sub(i,i)) + end + end + return c +end +function bits.new(n,binary) + local temp={} + temp.t="bits" + temp.Type="bits" + if type(n)=="string" then + if binary then + temp.data=n:match("[10]+") + else + local t={} + for i=#n,1,-1 do + table.insert(t,bits:conv(string.byte(n,i))) + end + temp.data=table.concat(t) + end + elseif type(n)=="number" or type(n)=="table" then + temp.data=basen(n,2) + end + if #temp.data%8~=0 then + temp.data=string.rep('0',8-#temp.data%8)..temp.data + end + setmetatable(temp, bits) + return temp +end +--~ for i=0,255 do +--~ local d=bits.new(i).data +--~ bits.ref[i]={d:match("(%d)(%d)(%d)(%d)(%d)(%d)(%d)(%d)")} +--~ bits.ref[tostring(i)]=d +--~ bits.ref[d]=i +--~ bits.ref["\255"..string.char(i)]=d +--~ end +function bits.numToBytes(n,fit,func) + local num=string.reverse(bits.new(n):toSbytes()) + local ref={["num"]=num,["fit"]=fit} + if fit then + if fit<#num then + if func then + print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!") + func(ref) + else + print("Warning: attempting to store a number that takes up more space than allotted!") + end + return ref.num:sub(1,ref.fit) + elseif fit==#num then + return string.reverse(num) + else + return string.reverse(string.rep("\0",fit-#num)..num) + end + else + return string.reverse(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 or #str==0 then + str=string.rep('0',8-#str%8)..str + end + return str +end +function bits:tonumber(s,e) + if s==0 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 +local binNum=require("bin.numbers.BigNum") +local infinabits={} +bin.infinabits = infinabits +infinabits.data='' +infinabits.t='infinabits' +infinabits.Type='infinabits' +infinabits.__index = infinabits +infinabits.__tostring=function(self) return self.data end +infinabits.__len=function(self) return (#self.data)/8 end +local floor,insert = math.floor, table.insert +function 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 = tonumber(tostring(n % b)) + 1 + n = n / b + insert(t, 1, digits:sub(d,d)) + until n == BigNum.new(0) + return sign .. table.concat(t,"") +end +function base2to10(num) + local n=BigNum.new(0) + for i = #num-1,0,-1 do + nn=BigNum.new(num:sub(i+1,i+1))*(BigNum.new(2)^((#num-i)-1)) + n=n+nn + end + return n +end +function infinabits.newBitBuffer(n) + -- WIP +end +function infinabits.newConverter(bitsIn,bitsOut) + local c={} + -- WIP +end +infinabits.ref={} +function infinabits.newByte(d)-- WIP + local c={} + if type(d)=="string" then + if #d>1 or #d<1 then + error("A byte must be one character!") + else + c.data=string.byte(d) + end + elseif type(d)=="number" then + if d>255 or d<0 then + error("A byte must be between 0 and 255!") + else + c.data=d + end + else + error("cannot use type "..type(d).." as an argument! Takes only strings or numbers!") + end + c.__index=function(self,k) + if k>=0 and k<9 then + if self.data==0 then + return 0 + elseif self.data==255 then + return 1 + else + return infinabits.ref[self.data][k] + end + end + end + c.__tostring=function(self) + return infinabits.ref[tostring(self.data)] + end + setmetatable(c,c) + return c +end +function infinabits.newByteArray(s)-- WIP + local c={} + if type(s)~="string" then + error("Must be a string type or bin/buffer type") + elseif type(s)=="table" then + if s.t=="sink" or s.t=="buffer" or s.t=="bin" then + local data=s:getData() + for i=1,#data do + c[#c+1]=infinabits.newByte(data:sub(i,i)) + end + else + error("Must be a string type or bin/buffer type") + end + else + for i=1,#s do + c[#c+1]=infinabits.newByte(s:sub(i,i)) + end + end + return c +end +function infinabits.new(n,binary) + local temp={} + temp.t="infinabits" + temp.Type="infinabits" + if type(n)=="string" then + if binary then + temp.data=n:match("[10]+") + else + local t={} + for i=#n,1,-1 do + table.insert(t,infinabits:conv(string.byte(n,i))) + end + temp.data=table.concat(t) + end + elseif type(n)=="number" or type(n)=="table" then + temp.data=basen(tostring(n),2) + end + if #temp.data%8~=0 then + temp.data=string.rep('0',8-#temp.data%8)..temp.data + end + setmetatable(temp, infinabits) + return temp +end +for i=0,255 do + local d=infinabits.new(i).data + infinabits.ref[i]={d:match("(%d)(%d)(%d)(%d)(%d)(%d)(%d)(%d)")} + infinabits.ref[tostring(i)]=d + infinabits.ref[d]=i + infinabits.ref["\255"..string.char(i)]=d +end +bits.ref = infinabits.ref +function infinabits.numToBytes(n,fit,func) + local num=string.reverse(infinabits.new(BigNum.new(n)):toSbytes()) + local ref={["num"]=num,["fit"]=fit} + if fit then + if fit<#num then + if func then + print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!") + func(ref) + else + print("Warning: attempting to store a number that takes up more space than allotted!") + end + return ref.num:sub(1,ref.fit) + elseif fit==#num then + return string.reverse(num) + else + return string.reverse(string.rep("\0",fit-#num)..num) + end + else + return string.reverse(num) + end +end +function infinabits.numToBytes(n,fit,fmt,func) + if fmt=="%e" then + local num=string.reverse(infinabits.new(BigNum.new(n)):toSbytes()) + local ref={["num"]=num,["fit"]=fit} + if fit then + if fit<#num then + if func then + print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!") + func(ref) + else + print("Warning: attempting to store a number that takes up more space than allotted!") + end + return ref.num:sub(1,ref.fit) + elseif fit==#num then + return num + else + return string.rep("\0",fit-#num)..num + end + else + return num + end + + else + local num=string.reverse(infinabits.new(BigNum.new(n)):toSbytes()) + local ref={["num"]=num,["fit"]=fit} + if fit then + if fit<#num then + if func then + print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!") + func(ref) + else + print("Warning: attempting to store a number that takes up more space than allotted!") + end + return ref.num:sub(1,ref.fit) + elseif fit==#num then + return string.reverse(num) + else + return string.reverse(string.rep("\0",fit-#num)..num) + end + else + return string.reverse(num) + end + end +end +function infinabits:conv(n) + local tab={} + local one=BigNum.new(1) + local n=BigNum.new(n) + while n>=one do + table.insert(tab,tonumber(tostring(n%2))) + n=n/2 + end + local str=string.reverse(table.concat(tab)) + if #str%8~=0 or #str==0 then + str=string.rep('0',8-#str%8)..str + end + return str +end +function infinabits:tonumber(s) + if s==0 then + return tonumber(self.data,2) + end + s=s or 1 + return tonumber(tostring(base2to10(string.sub(self.data,(8*(s-1))+1,8*s)))) or error('Bounds!') +end +function infinabits:isover() + return #self.data>8 +end +function infinabits:flipbits() + tab={} + local s=self.data + s=s:gsub("1","_") + s=s:gsub("0","1") + s=s:gsub("_","0") + self.data=s +end +function infinabits: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 infinabits: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 infinabits:getBin() + return self.data +end +function infinabits:getbytes() + return #self.data/8 +end +local randomGen=require("bin.numbers.random") +function bin.setBitsInterface(int) + bin.defualtBit=int or infinabits +end +bin.setBitsInterface() +function bin.normalizeData(data) -- unified function to allow for all types to string + if type(data)=="string" then return data end + if type(data)=="table" then + if data.Type=="bin" or data.Type=="streamable" or data.Type=="buffer" then + return data:getData() + elseif data.Type=="bits" or data.Type=="infinabits" then + return data:toSbytes() + elseif data.Type=="sink" then + -- LATER + else + return "" + end + elseif type(data)=="userdata" then + if tostring(data):sub(1,4)=="file" then + local cur=data:seek("cur") + data:seek("set",0) + local dat=data:read("*a") + data:seek("set",cur) + return dat + else + error("File handles are the only userdata that can be used!") + end + end +end +function bin.resolveType(tab) -- used in getblock for auto object creation. Internal method + if tab.Type then + if tab.Type=="bin" then + return bin.new(tab.data) + elseif tab.Type=="streamable" then + if bin.fileExist(tab.file) then return nil,"Cannot load the stream file, source file does not exist!" end + return bin.stream(tab.file,tab.lock) + elseif tab.Type=="buffer" then + local buf=bin.newDataBuffer(tab.size) + buf[1]=tab:getData() + return buf + elseif tab.Type=="bits" then + local b=bits.new("") + b.data=tab.data + return b + elseif tab.Type=="infinabits" then + local b=infinabits.new("") + b.data=tab.data + return b + elseif tab.Type=="sink" then + return bin.newSync(tab.data) + else -- maybe a type from another library + return tab + end + else return tab end +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.toHex(str) + local str=bin.normalizeData(str) + return (str:gsub('.', function (c) + return string.format('%02X', string.byte(c)) + end)) +end +function bin.fromHex(str) + return (str:gsub('..', function (cc) + return string.char(tonumber(cc, 16)) + end)) +end + +-- Constructors +function bin.new(data) + data=bin.normalizeData(data) + local c = {} + setmetatable(c, bin) + c.data=data + c.Type="bin" + c.t="bin" + c.pos=1 + c.stream=false + return c +end + +function bin.newFromHex(data) + return bin.new(bin.fromHex(data)) +end +function bin.load(path) + if type(path) ~= "string" then error("Path must be a string!") end + local f = io.open(path, 'rb') + local content = f:read('*a') + f:close() + return bin.new(content) +end +function bin.stream(file,l) + if not(l==false) then l=true end + local c=bin.new() + c.Type="streamable" + c.t="streamable" + if bin.streams[file]~=nil then + c.file=file + c.lock = l + c.workingfile=bin.streams[file][1].workingfile + bin.streams[file][2]=bin.streams[file][2]+1 + c.stream=true + return c + end + 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 + bin.streams[file]={c,1} + return c +end +function bin.newTempFile() + local c=bin.new() + c.file=file + c.lock = false + c.workingfile=io.tmpfile() + c.stream=true + return c +end +function bin.freshStream(file) + bin.new():tofile(file) + return bin.stream(file,false) +end +function bin.newStreamFileObject(file) + local c=bin.new() + c.Type="streamable" + c.t="streamable" + c.file="FILE_OBJECT" + c.lock = false + c.workingfile=file + c.stream=true + return c +end +-- Core Methods +function bin:canStreamWrite() + return (self.stream and not(self.lock)) +end +function bin:getSeek() + if self.stream then + return self.workingfile:seek("cur")+1 + else + return self.pos + end +end +function bin:setSeek(n) + if self.stream then + self.workingfile:seek("set",n-1) + else + self.pos=n + end +end +function bin:seek(n) + if self.stream then + if not n then return self.workingfile:seek("cur") end + local cur=self.workingfile:seek("cur") + self.workingfile:seek("set",cur+n) + else + if not n then return self.pos end + if #self.data-(self.pos-1)size then + data = data:sub(1,size) + elseif dsize255 then + nn=nn%256 + elseif nn<0 then + nn=256-math.abs(nn) + end + buf[i]=nn + end + self:setSeek(1) + self:write(buf:getData()) +end +function bin:getData(a,b,fmt) + local data="" + if a or b then + data=self:sub(a,b) + else + if self.stream then + local cur=self.workingfile:seek("cur") + self.workingfile:seek("set",0) + data=self.workingfile:read("*a") + self.workingfile:seek("set",cur) + else + data=self.data + end + end + if fmt=="%x" or fmt=="hex" then + return bin.toHex(data):lower() + elseif fmt=="%X" or fmt=="HEX" then + return bin.toHex(data) + elseif fmt=="%b" or fmt=="b64" then + return bin.toB64(data) + elseif fmt then + return bin.new(data):getBlock(fmt,#data) + end + return data +end +function bin:getSize(fmt) + local len=0 + if self.stream then + local cur=self.workingfile:seek("cur") + len=self.workingfile:seek("end") + self.workingfile:seek("set",cur) + else + len=#self.data + end + if fmt=="%b" then + return bin.toB64() + elseif fmt then + return string.format(fmt, len) + else + return len + end +end +function bin:tackE(data,size,h) + local data=bin.normalizeData(data) + local cur=self:getSize() + self:setSeek(self:getSize()+1) + self:write(data,size) + if h then + self:setSeek(cur+1) + 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.endianflop(data) + return string.reverse(data) +end +function bin:tofile(name) + if self.stream then return end + if not name then error("Must include a filename to save as!") end + file = io.open(name, "wb") + file:write(self.data) + file:close() +end +function bin:close() + if self.stream then + if bin.streams[self.file][2]==1 then + bin.streams[self.file]=nil + self.workingfile:close() + else + bin.streams[self.file][2]=bin.streams[self.file][2]-1 + self.workingfile=io.tmpfile() + self.workingfile:close() + end + end +end +function bin:getBlock(t,n) + local data="" + if not n then + if bin.registerBlocks[t] then + return bin.registerBlocks[t][1](nil,self) + else + error("Unknown format! Cannot read from file: "..tostring(t)) + end + else + if t=="n" or t=="%e" or t=="%E" then + data=self:read(n) + local numB=bin.defualtBit.new(data) + local numL=bin.defualtBit.new(string.reverse(data)) + local little=numL:tonumber(0) + local big=numB:tonumber(0) + if t=="%E" then + return big + elseif t=="%X" then + return bin.toHex(data):upper() + elseif t=="%x" then + return bin.toHex(data):lower() + elseif t=="%b" then + return bin.toB64(data) + elseif t=="%e" then + return little + end + return big,little + elseif t=="s" then + return self:read(n) + elseif bin.registerBlocks[t] then + return bin.registerBlocks[t][1](n,self) + else + error("Unknown format! Cannot read from file: "..tostring(t)) + end + end +end +function bin:addBlock(d,fit,fmt) + if not fmt then fmt=type(d):sub(1,1) end + if bin.registerBlocks[fmt] then + self:tackE(bin.registerBlocks[fmt][2](d,fit,fmt,self,bin.registerBlocks[fmt][2])) + elseif type(d)=="number" then + local data=bin.defualtBit.numToBytes(d,fit or 4,fmt,function() + error("Overflow! Space allotted for number is smaller than the number takes up. Increase the fit!") + end) + self:tackE(data) + elseif type(d)=="string" then + local data=d:sub(1,fit or -1) + if #data<(fit or #data) then + data=data..string.rep("\0",fit-#data) + end + self:tackE(data) + end +end +bin.registerBlocks={} +function bin.registerBlock(t,funcG,funcA) + bin.registerBlocks[t]={funcG,funcA} +end +function bin.newDataBuffer(size,fill) -- fills with \0 or nul or with what you enter + local c={} + local fill=fill or "\0" + c.data={self=c} + c.Type="buffer" + c.size=size or 0 -- 0 means an infinite buffer, sometimes useful + for i=1,c.size do + c.data[i]=fill + end + local mt={ + __index=function(t,k) + if type(k)=="number" then + local data=t.data[k] + if data then + return string.byte(data) + else + error("Index out of range!") + end + elseif type(k)=="string" then + local num=tonumber(k) + if num then + local data=t.data[num] + if data then + return data + else + error("Index out of range!") + end + else + error("Only number-strings and numbers can be indexed!") + end + else + error("Only number-strings and numbers can be indexed!") + end + end, + __newindex=function(t,k,v) + if type(k)~="number" then error("Can only set a buffers data with a numeric index!") end + local data="" + if type(v)=="string" then + data=v + elseif type(v)=="number" then + data=string.char(v) + else + -- try to normalize the data of type v + data=bin.normalizeData(v) + end + t:fillBuffer(k,data) + end, + __tostring=function(t) + return t:getData() + end, + } + function c:fillBuffer(a,data) + local len=#data + if len==1 then + self.data[a]=data + else + local i=a-1 + for d in data:gmatch(".") do + i=i+1 + if i>c.size then + return #data-i+a + end + self.data[i]=d + end + return #data-i+(a-1) + end + end + function c:getData(a,b,fmt) -- LATER + local dat=bin.new(table.concat(self.data,"",a,b)) + local n=dat:getSize() + return dat:getBlock(fmt or "s",n) + end + function c:getSize() + return #self:getData() + end + setmetatable(c,mt) + return c +end +function bin:newDataBufferFromStream(pos,size,fill) -- fills with \0 or nul or with what you enter IF the nothing exists inside the bin file. + local s=self:getSize() + if not self.stream then error("Can only created a streamed buffer on a streamable file!") end + if s==0 then + self:write(string.rep("\0",pos+size)) + end + self:setSeek(1) + local c=bin.newDataBuffer(size,fill) + rawset(c,"pos",pos) + rawset(c,"size",size) + rawset(c,"fill",fill) + rawset(c,"bin",self) + rawset(c,"sync",function(self) + local cur=self.bin:getSeek() + self.bin:setSeek(self.pos) + self.bin:write(self:getData(),size) + self.bin:setSeek(cur) + end) + c:fillBuffer(1,self:sub(pos,pos+size)) + function c:fillBuffer(a,data) + local len=#data + if len==1 then + self.data[a]=data + self:sync() + else + local i=a-1 + for d in data:gmatch(".") do + i=i+1 + if i>c.size then + self:sync() + return #data-i+a + end + self.data[i]=d + end + self:sync() + return #data-i+(a-1) + end + end + return c +end +function bin:toDataBuffer() + local s=self:getSize() + -- if self:canStreamWrite() then + -- return self:newDataBufferFromStream(0,s) + -- end + local buf=bin.newDataBuffer(s) + local data=self:read(512) + local i=1 + while data~=nil do + buf[i]=data + data=self:read(512) + i=i+512 + end + return buf +end +function bin:getHash() + if self:getSize()==0 then + return "NaN" + end + n=32 + local rand = randomGen:newND(1,self:getSize(),self:getSize()) + 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:flipbits() + if self:canStreamWrite() then + self:setSeek(1) + for i=1,self:getSize() do + self:write(string.char(255-string.byte(self:sub(i,i)))) + end + else + 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:encrypt() + self:flipbits() +end +function bin:decrypt() + self:flipbits() +end +-- Use with small files! +function bin:gsub(...) + local data=self:getData() + local pos=self:getSeek() + self:setSeek(1) + self:write((data:gsub(...)) or data) + self:setSeek(loc) +end +function bin:gmatch(pat) + return self:getData():gmatch(pat) +end +function bin:match(pat) + return self:getData():match(pat) +end +function bin:trim() + local data=self:getData() + local pos=self:getSeek() + self:setSeek(1) + self:write(data:match'^()%s*$' and '' or data:match'^%s*(.*%S)') + self:setSeek(loc) +end +function bin:lines() + local t = {} + local function helper(line) table.insert(t, line) return '' end + helper((self:getData():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:wipe() + if self:canStreamWrite() then + self:close() + local c=bin.freshStream(self.file) + self.workingfile=c.workingfile + else + self.data="" + end + self:setSeek(1) +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:wipe() + self:write(table.concat(t,"\n")) +end +local __CURRENTVERSION=2 +bin.registerBlock("t",function(SIZE_OR_NIL,ref) + local header=ref:read(3) + if not header:match("(LT.)") then error("Not a valid table struct!") end + if bin.defualtBit.new(header:sub(3,3)):tonumber(1)>__CURRENTVERSION then error("Incompatible Version of LuaTable!") end + local len=ref:getBlock("n",4) -- hehe lets make life easier + local tab={} + local ind + local n=0 + while true do + local _dat=ref:read(2) + if _dat==nil then break end + local it,dt=_dat:match("(.)(.)") + n=n+2 + if it=="N" then -- get the index stuff out of the way first + ind=ref:getBlock("n",4) + n=n+4 + else + indL=ref:getBlock("n",1) + n=n+1+indL + ind=ref:read(indL) + end + if dt=="N" then + tab[ind]=ref:getBlock("d") + n=n+8 + elseif dt=="I" then + tab[ind]=math.huge + ref:getBlock("n",4) + n=n+4 + elseif dt=="i" then + tab[ind]=-math.huge + ref:getBlock("n",4) + n=n+4 + elseif dt=="S" then + local nn=ref:getBlock("n",4) + tab[ind]=ref:read(nn) + n=n+4+nn + elseif dt=="B" then + tab[ind]=({["\255"]=true,["\0"]=false})[ref:read(1)] + n=n+1 + elseif dt=="F" then + local nn=ref:getBlock("n",4) + tab[ind]=loadstring(ref:read(nn)) + n=n+4+nn + elseif dt=="T" then + local cur=ref:getSeek() + local size=ref:getBlock("n",4) + ref:setSeek(cur) + ref:read(4) + if size==7 then + tab[ind]={} + ref:read(7) + n=n+11 + else + local data=bin.new(ref:read(size)) + local dat=data:getBlock("t") + if dat.__RECURSIVE then + tab[ind]=tab + else + tab[ind]=dat + end + n=n+data:getSize()+4 + end + end + if n==len then break end + end + return bin.resolveType(tab) +end,function(d,fit,fmt,self,rec,tabsaw) + -- INGORE FIT WE ARE CREATING A STRUCT!!! + -- fmt will apply to all numbers + local __rem=nil + if not tabsaw then rem=true end + local tabsaw=tabsaw or {} + if rem then + table.insert(tabsaw,d) + end + local bData={} + for i,v in pairs(d) do -- this is for tables, all but userdata is fine. Depending on where you are using lua functions may or may not work + local tp=type(v):sub(1,1):upper() -- uppercase of datatype + if type(i)=="number" then -- Lets handle indexies + if v==math.huge then + tp="I" + v=0 + elseif v==-math.huge then + tp="i" + v=0 + end + table.insert(bData,"N"..tp..bin.defualtBit.numToBytes(i,4)) -- number index? + elseif type(i)=="string" then + if #i>255 then error("A string index cannot be larger than 255 bytes!") end + table.insert(bData,"S"..tp..bin.defualtBit.numToBytes(#i,1)..i) -- string index? + else + error("Only numbers and strings can be a table index!") -- throw error? + end + if type(v)=="number" then + -- How do we handle number data + local temp=bin.new() + temp:addBlock(v,nil,"d") + table.insert(bData,temp.data) + elseif type(v)=="string" then + -- Lets work on strings + table.insert(bData,bin.defualtBit.numToBytes(#v,4)) -- add length of string + table.insert(bData,v) -- add string + elseif type(v)=="boolean" then -- bools are easy :D + table.insert(bData,({[true]="\255",[false]="\0"})[v]) + elseif type(v)=="function" then -- should we allow this? why not... + local dump=string.dump(v) + table.insert(bData,bin.defualtBit.numToBytes(#dump,4)) -- add length of dumped string + table.insert(bData,dump) -- add it + elseif type(v)=="table" then -- tables... + if tabsaw[1]==v then + v={__RECURSIVE=i} + else + tabsaw[i]=v + end + local data=rec(v,nil,"t",self,rec,tabsaw) + table.insert(bData,bin.defualtBit.numToBytes(#data,4)) -- add length of string + table.insert(bData,data) -- add string + end + end + local data=table.concat(bData) + return "LT"..string.char(__CURRENTVERSION)..bin.defualtBit.numToBytes(#data,4)..data +end) +bin.registerBlock("b",function(SIZE_OR_NIL,ref) + return ({["\255"]=true,["\0"]=false})[ref:read(1)] +end,function(d) + return ({[true]="\255",[false]="\0"})[d] +end) +bin.registerBlock("f",function(SIZE_OR_NIL,ref) + local nn=ref:getBlock("n",4) + return loadstring(ref:read(nn)) +end,function(d) + local dump=string.dump(d) + return bin.defualtBit.numToBytes(#dump,4)..dump +end) +bin.registerBlock("d",function(SIZE_OR_NIL,ref) + local w,p=ref:getBlock("n",4),ref:getBlock("n",4) + p=tonumber("0."..tostring(p)) + return w+p +end,function(d,fit,fmt,self,rec,tabsaw) + local w,p = toFraction(d) + local temp=bin.new() + temp:addBlock(w,4) + temp:addBlock(p,4) + return temp.data +end) +if love then + 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.fileExists(name) + return love.filesystem.getInfo(name) + end + function bin:tofile(filename) + if not(filename) or self.Stream then return nil end + love.filesystem.write(filename,self.data) + end + function bin.loadS(path,s,r) + local path = love.filesystem.getSaveDirectory( ).."\\"..path + if type(path) ~= "string" then error("Path must be a string!") end + local f = io.open(path, 'rb') + local content = f:read('*a') + f:close() + return bin.new(content) + end + function bin:tofileS(filename) + if self.stream then return end + local filename = love.filesystem.getSaveDirectory( ).."\\"..filename + print(#self.data,filename) + if not filename then error("Must include a filename to save as!") end + file = io.open(filename, "wb") + file:write(self.data) + file:close() + end + function bin.stream(file) + return bin.newStreamFileObject(love.filesystem.newFile(file)) + end + function bin:getSize(fmt) + local len=0 + if self.stream then + local len=self.workingfile:getSize() + else + len=#self.data + end + if fmt=="%b" then + return bin.toB64() + elseif fmt then + return string.format(fmt, len) + else + return len + end + end + function bin:getSeek() + if self.stream then + return self.workingfile:tell()+1 + else + return self.pos + end + end + function bin:setSeek(n) + if self.stream then + self.workingfile:seek(n-1) + else + self.pos=n + end + end + function bin:seek(n) + if self.stream then + self.workingfile:seek(n) + else + if not n then return self.pos end + if #self.data-(self.pos-1) 0 then + for i = bnum.len - 2 , 0 , -1 do + for j = 0 , RADIX_LEN - string.len( bnum[i] ) - 1 do + temp = temp .. '0' ; + end + temp = temp .. bnum[i] ; + end + if bnum[bnum.len - 1]==nil then + return "nil" + end + temp = bnum[bnum.len - 1] .. temp ; + if bnum.signal == '-' then + temp = bnum.signal .. temp ; + end + return temp ; + else + return "" ; + end +end + +function BigNum.mt.pow( num1 , num2 ) + local bnum1 = BigNum.new( num1 ) ; + local bnum2 = BigNum.new( num2 ) ; + return BigNum.pow( bnum1 , bnum2 ) ; +end + +function BigNum.mt.eq( num1 , num2 ) + local bnum1 = BigNum.new( num1 ) ; + local bnum2 = BigNum.new( num2 ) ; + return BigNum.eq( bnum1 , bnum2 ) ; +end + +function BigNum.mt.lt( num1 , num2 ) + local bnum1 = BigNum.new( num1 ) ; + local bnum2 = BigNum.new( num2 ) ; + return BigNum.lt( bnum1 , bnum2 ) ; +end + +function BigNum.mt.le( num1 , num2 ) + local bnum1 = BigNum.new( num1 ) ; + local bnum2 = BigNum.new( num2 ) ; + return BigNum.le( bnum1 , bnum2 ) ; +end + +function BigNum.mt.unm( num ) + local ret = BigNum.new( num ) + if ret.signal == '+' then + ret.signal = '-' + else + ret.signal = '+' + end + return ret +end + +BigNum.mt.__metatable = "hidden" +BigNum.mt.__tostring = BigNum.mt.tostring ; +BigNum.mt.__add = BigNum.mt.add ; +BigNum.mt.__sub = BigNum.mt.sub ; +BigNum.mt.__mul = BigNum.mt.mul ; +BigNum.mt.__div = BigNum.mt.div ; +BigNum.mt.__pow = BigNum.mt.pow ; +BigNum.mt.__unm = BigNum.mt.unm ; +BigNum.mt.__mod = BigNum.mt.mod ; +BigNum.mt.__eq = BigNum.mt.eq ; +BigNum.mt.__le = BigNum.mt.le ; +BigNum.mt.__lt = BigNum.mt.lt ; +setmetatable( BigNum.mt, { __index = "inexistent field", __newindex = "not available", __metatable="hidden" } ) ; +function BigNum.add( bnum1 , bnum2 , bnum3 ) + local maxlen = 0 ; + local i = 0 ; + local carry = 0 ; + local signal = '+' ; + local old_len = 0 ; + --Handle the signals + if bnum1 == nil or bnum2 == nil or bnum3 == nil then + error("Function BigNum.add: parameter nil") ; + elseif bnum1.signal == '-' and bnum2.signal == '+' then + bnum1.signal = '+' ; + BigNum.sub( bnum2 , bnum1 , bnum3 ) ; + + if not rawequal(bnum1, bnum3) then + bnum1.signal = '-' ; + end + return 0 ; + elseif bnum1.signal == '+' and bnum2.signal == '-' then + bnum2.signal = '+' ; + BigNum.sub( bnum1 , bnum2 , bnum3 ) ; + if not rawequal(bnum2, bnum3) then + bnum2.signal = '-' ; + end + return 0 ; + elseif bnum1.signal == '-' and bnum2.signal == '-' then + signal = '-' ; + end + -- + old_len = bnum3.len ; + if bnum1.len > bnum2.len then + maxlen = bnum1.len ; + else + maxlen = bnum2.len ; + bnum1 , bnum2 = bnum2 , bnum1 ; + end + --School grade sum + for i = 0 , maxlen - 1 do + if bnum2[i] ~= nil then + bnum3[i] = bnum1[i] + bnum2[i] + carry ; + else + bnum3[i] = bnum1[i] + carry ; + end + if bnum3[i] >= RADIX then + bnum3[i] = bnum3[i] - RADIX ; + carry = 1 ; + else + carry = 0 ; + end + end + --Update the answer's size + if carry == 1 then + bnum3[maxlen] = 1 ; + end + bnum3.len = maxlen + carry ; + bnum3.signal = signal ; + for i = bnum3.len, old_len do + bnum3[i] = nil ; + end + return 0 ; +end + +function BigNum.sub( bnum1 , bnum2 , bnum3 ) + local maxlen = 0 ; + local i = 0 ; + local carry = 0 ; + local old_len = 0 ; + if bnum1 == nil or bnum2 == nil or bnum3 == nil then + error("Function BigNum.sub: parameter nil") ; + elseif bnum1.signal == '-' and bnum2.signal == '+' then + bnum1.signal = '+' ; + BigNum.add( bnum1 , bnum2 , bnum3 ) ; + bnum3.signal = '-' ; + if not rawequal(bnum1, bnum3) then + bnum1.signal = '-' ; + end + return 0 ; + elseif bnum1.signal == '-' and bnum2.signal == '-' then + bnum1.signal = '+' ; + bnum2.signal = '+' ; + BigNum.sub( bnum2, bnum1 , bnum3 ) ; + if not rawequal(bnum1, bnum3) then + bnum1.signal = '-' ; + end + if not rawequal(bnum2, bnum3) then + bnum2.signal = '-' ; + end + return 0 ; + elseif bnum1.signal == '+' and bnum2.signal == '-' then + bnum2.signal = '+' ; + BigNum.add( bnum1 , bnum2 , bnum3 ) ; + if not rawequal(bnum2, bnum3) then + bnum2.signal = '-' ; + end + return 0 ; + end + --Tests if bnum2 > bnum1 + if BigNum.compareAbs( bnum1 , bnum2 ) == 2 then + BigNum.sub( bnum2 , bnum1 , bnum3 ) ; + bnum3.signal = '-' ; + return 0 ; + else + maxlen = bnum1.len ; + end + old_len = bnum3.len ; + bnum3.len = 0 ; + --School grade subtraction + for i = 0 , maxlen - 1 do + if bnum2[i] ~= nil then + bnum3[i] = bnum1[i] - bnum2[i] - carry ; + else + bnum3[i] = bnum1[i] - carry ; + end + if bnum3[i] < 0 then + bnum3[i] = RADIX + bnum3[i] ; + carry = 1 ; + else + carry = 0 ; + end + + if bnum3[i] ~= 0 then + bnum3.len = i + 1 ; + end + end + bnum3.signal = '+' ; + --Check if answer's size if zero + if bnum3.len == 0 then + bnum3.len = 1 ; + bnum3[0] = 0 ; + end + if carry == 1 then + error( "Error in function sub" ) ; + end + for i = bnum3.len , max( old_len , maxlen - 1 ) do + bnum3[i] = nil ; + end + return 0 ; +end + +function BigNum.mul( bnum1 , bnum2 , bnum3 ) + local i = 0 ; j = 0 ; + local temp = BigNum.new( ) ; + local temp2 = 0 ; + local carry = 0 ; + local oldLen = bnum3.len ; + if bnum1 == nil or bnum2 == nil or bnum3 == nil then + error("Function BigNum.mul: parameter nil") ; + --Handle the signals + elseif bnum1.signal ~= bnum2.signal then + BigNum.mul( bnum1 , -bnum2 , bnum3 ) ; + bnum3.signal = '-' ; + return 0 ; + end + bnum3.len = ( bnum1.len ) + ( bnum2.len ) ; + --Fill with zeros + for i = 1 , bnum3.len do + bnum3[i - 1] = 0 ; + end + --Places nil where passes through this + for i = bnum3.len , oldLen do + bnum3[i] = nil ; + end + --School grade multiplication + for i = 0 , bnum1.len - 1 do + for j = 0 , bnum2.len - 1 do + carry = ( bnum1[i] * bnum2[j] + carry ) ; + carry = carry + bnum3[i + j] ; + bnum3[i + j] = ( carry % RADIX ) ; + temp2 = bnum3[i + j] ; + carry = math.floor ( carry / RADIX ) ; + end + if carry ~= 0 then + bnum3[i + bnum2.len] = carry ; + end + carry = 0 ; + end + + --Update the answer's size + for i = bnum3.len - 1 , 1 , -1 do + if bnum3[i] ~= nil and bnum3[i] ~= 0 then + break ; + else + bnum3[i] = nil ; + end + bnum3.len = bnum3.len - 1 ; + end + return 0 ; +end + +function BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) + local temp = BigNum.new() ; + local temp2 = BigNum.new() ; + local one = BigNum.new( "1" ) ; + local zero = BigNum.new( "0" ) ; + --Check division by zero + if BigNum.compareAbs( bnum2 , zero ) == 0 then + error( "Function BigNum.div: Division by zero" ) ; + end + --Handle the signals + if bnum1 == nil or bnum2 == nil or bnum3 == nil or bnum4 == nil then + error( "Function BigNum.div: parameter nil" ) ; + elseif bnum1.signal == "+" and bnum2.signal == "-" then + bnum2.signal = "+" ; + BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ; + bnum2.signal = "-" ; + bnum3.signal = "-" ; + return 0 ; + elseif bnum1.signal == "-" and bnum2.signal == "+" then + bnum1.signal = "+" ; + BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ; + bnum1.signal = "-" ; + if bnum4 < zero then --Check if remainder is negative + BigNum.add( bnum3 , one , bnum3 ) ; + BigNum.sub( bnum2 , bnum4 , bnum4 ) ; + end + bnum3.signal = "-" ; + return 0 ; + elseif bnum1.signal == "-" and bnum2.signal == "-" then + bnum1.signal = "+" ; + bnum2.signal = "+" ; + BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ; + bnum1.signal = "-" ; + if bnum4 < zero then --Check if remainder is negative + BigNum.add( bnum3 , one , bnum3 ) ; + BigNum.sub( bnum2 , bnum4 , bnum4 ) ; + end + bnum2.signal = "-" ; + return 0 ; + end + temp.len = bnum1.len - bnum2.len - 1 ; + + --Reset variables + BigNum.change( bnum3 , "0" ) ; + BigNum.change( bnum4 , "0" ) ; + + BigNum.copy( bnum1 , bnum4 ) ; + + --Check if can continue dividing + while( BigNum.compareAbs( bnum4 , bnum2 ) ~= 2 ) do + if bnum4[bnum4.len - 1] >= bnum2[bnum2.len - 1] then + BigNum.put( temp , math.floor( bnum4[bnum4.len - 1] / bnum2[bnum2.len - 1] ) , bnum4.len - bnum2.len ) ; + temp.len = bnum4.len - bnum2.len + 1 ; + else + BigNum.put( temp , math.floor( ( bnum4[bnum4.len - 1] * RADIX + bnum4[bnum4.len - 2] ) / bnum2[bnum2.len -1] ) , bnum4.len - bnum2.len - 1 ) ; + temp.len = bnum4.len - bnum2.len ; + end + + if bnum4.signal ~= bnum2.signal then + temp.signal = "-"; + else + temp.signal = "+"; + end + BigNum.add( temp , bnum3 , bnum3 ) ; + temp = temp * bnum2 ; + BigNum.sub( bnum4 , temp , bnum4 ) ; + end + + --Update if the remainder is negative + if bnum4.signal == '-' then + decr( bnum3 ) ; + BigNum.add( bnum2 , bnum4 , bnum4 ) ; + end + return 0 ; +end + +function BigNum.pow( bnum1 , bnum2 ) + local n = BigNum.new( bnum2 ) ; + local y = BigNum.new( 1 ) ; + local z = BigNum.new( bnum1 ) ; + local zero = BigNum.new( "0" ) ; + if bnum2 < zero then + error( "Function BigNum.exp: domain error" ) ; + elseif bnum2 == zero then + return y ; + end + while 1 do + if ( n[0] % 2 ) == 0 then + n = n / 2 ; + else + n = n / 2 ; + y = z * y ; + if n == zero then + return y ; + end + end + z = z * z ; + end +end +-- Português : +BigNum.exp = BigNum.pow + +function BigNum.gcd( bnum1 , bnum2 ) + local a = {} ; + local b = {} ; + local c = {} ; + local d = {} ; + local zero = {} ; + zero = BigNum.new( "0" ) ; + if bnum1 == zero or bnum2 == zero then + return BigNum.new( "1" ) ; + end + a = BigNum.new( bnum1 ) ; + b = BigNum.new( bnum2 ) ; + a.signal = '+' ; + b.signal = '+' ; + c = BigNum.new() ; + d = BigNum.new() ; + while b > zero do + BigNum.div( a , b , c , d ) ; + a , b , d = b , d , a ; + end + return a ; +end +-- Português: +BigNum.mmc = BigNum.gcd + +function BigNum.eq( bnum1 , bnum2 ) + if BigNum.compare( bnum1 , bnum2 ) == 0 then + return true ; + else + return false ; + end +end + +function BigNum.lt( bnum1 , bnum2 ) + if BigNum.compare( bnum1 , bnum2 ) == 2 then + return true ; + else + return false ; + end +end + +function BigNum.le( bnum1 , bnum2 ) + local temp = -1 ; + temp = BigNum.compare( bnum1 , bnum2 ) + if temp == 0 or temp == 2 then + return true ; + else + return false ; + end +end + +function BigNum.compareAbs( bnum1 , bnum2 ) + if bnum1 == nil or bnum2 == nil then + error("Function compare: parameter nil") ; + elseif bnum1.len > bnum2.len then + return 1 ; + elseif bnum1.len < bnum2.len then + return 2 ; + else + local i ; + for i = bnum1.len - 1 , 0 , -1 do + if bnum1[i] > bnum2[i] then + return 1 ; + elseif bnum1[i] < bnum2[i] then + return 2 ; + end + end + end + return 0 ; +end + +function BigNum.compare( bnum1 , bnum2 ) + local signal = 0 ; + + if bnum1 == nil or bnum2 == nil then + error("Funtion BigNum.compare: parameter nil") ; + elseif bnum1.signal == '+' and bnum2.signal == '-' then + return 1 ; + elseif bnum1.signal == '-' and bnum2.signal == '+' then + return 2 ; + elseif bnum1.signal == '-' and bnum2.signal == '-' then + signal = 1 ; + end + if bnum1.len > bnum2.len then + return 1 + signal ; + elseif bnum1.len < bnum2.len then + return 2 - signal ; + else + local i ; + for i = bnum1.len - 1 , 0 , -1 do + if bnum1[i] > bnum2[i] then + return 1 + signal ; + elseif bnum1[i] < bnum2[i] then + return 2 - signal ; + end + end + end + return 0 ; +end + +function BigNum.copy( bnum1 , bnum2 ) + if bnum1 ~= nil and bnum2 ~= nil then + local i ; + for i = 0 , bnum1.len - 1 do + bnum2[i] = bnum1[i] ; + end + bnum2.len = bnum1.len ; + else + error("Function BigNum.copy: parameter nil") ; + end +end + +function BigNum.change( bnum1 , num ) + local j = 0 ; + local len = 0 ; + local num = num ; + local l ; + local oldLen = 0 ; + if bnum1 == nil then + error( "BigNum.change: parameter nil" ) ; + elseif type( bnum1 ) ~= "table" then + error( "BigNum.change: parameter error, type unexpected" ) ; + elseif num == nil then + bnum1.len = 1 ; + bnum1[0] = 0 ; + bnum1.signal = "+"; + elseif type( num ) == "table" and num.len ~= nil then --check if num is a big number + --copy given table to the new one + for i = 0 , num.len do + bnum1[i] = num[i] ; + end + if num.signal ~= '-' and num.signal ~= '+' then + bnum1.signal = '+' ; + else + bnum1.signal = num.signal ; + end + oldLen = bnum1.len ; + bnum1.len = num.len ; + elseif type( num ) == "string" or type( num ) == "number" then + if string.sub( num , 1 , 1 ) == '+' or string.sub( num , 1 , 1 ) == '-' then + bnum1.signal = string.sub( num , 1 , 1 ) ; + num = string.sub(num, 2) ; + else + bnum1.signal = '+' ; + end + num = string.gsub( num , " " , "" ) ; + local sf = string.find( num , "e" ) ; + --Handles if the number is in exp notation + if sf ~= nil then + num = string.gsub( num , "%." , "" ) ; + local e = string.sub( num , sf + 1 ) ; + e = tonumber(e) ; + if e ~= nil and e > 0 then + e = tonumber(e) ; + else + error( "Function BigNum.change: string is not a valid number" ) ; + end + num = string.sub( num , 1 , sf - 2 ) ; + for i = string.len( num ) , e do + num = num .. "0" ; + end + else + sf = string.find( num , "%." ) ; + if sf ~= nil then + num = string.sub( num , 1 , sf - 1 ) ; + end + end + + l = string.len( num ) ; + oldLen = bnum1.len ; + if (l > RADIX_LEN) then + local mod = l-( math.floor( l / RADIX_LEN ) * RADIX_LEN ) ; + for i = 1 , l-mod, RADIX_LEN do + bnum1[j] = tonumber( string.sub( num, -( i + RADIX_LEN - 1 ) , -i ) ); + --Check if string dosn't represents a number + if bnum1[j] == nil then + error( "Function BigNum.change: string is not a valid number" ) ; + bnum1.len = 0 ; + return 1 ; + end + j = j + 1 ; + len = len + 1 ; + end + if (mod ~= 0) then + bnum1[j] = tonumber( string.sub( num , 1 , mod ) ) ; + bnum1.len = len + 1 ; + else + bnum1.len = len ; + end + --Eliminate trailing zeros + for i = bnum1.len - 1 , 1 , -1 do + if bnum1[i] == 0 then + bnum1[i] = nil ; + bnum1.len = bnum1.len - 1 ; + else + break ; + end + end + + else + -- string.len(num) <= RADIX_LEN + bnum1[j] = tonumber( num ) ; + bnum1.len = 1 ; + end + else + error( "Function BigNum.change: parameter error, type unexpected" ) ; + end + + --eliminates the deprecated higher order 'algarisms' + if oldLen ~= nil then + for i = bnum1.len , oldLen do + bnum1[i] = nil ; + end + end + + return 0 ; +end + +function BigNum.put( bnum , int , pos ) + if bnum == nil then + error("Function BigNum.put: parameter nil") ; + end + local i = 0 ; + for i = 0 , pos - 1 do + bnum[i] = 0 ; + end + bnum[pos] = int ; + for i = pos + 1 , bnum.len do + bnum[i] = nil ; + end + bnum.len = pos ; + return 0 ; +end + +--printraw{{{2 +function printraw( bnum ) + local i = 0 ; + if bnum == nil then + error( "Function printraw: parameter nil" ) ; + end + while 1 == 1 do + if bnum[i] == nil then + io.write( ' len '..bnum.len ) ; + if i ~= bnum.len then + io.write( ' ERRO!!!!!!!!' ) ; + end + io.write( "\n" ) ; + return 0 ; + end + io.write( 'r'..bnum[i] ) ; + i = i + 1 ; + end +end +--max{{{2 +function max( int1 , int2 ) + if int1 > int2 then + return int1 ; + else + return int2 ; + end +end + +--decr{{{2 +function decr( bnum1 ) + local temp = {} ; + temp = BigNum.new( "1" ) ; + BigNum.sub( bnum1 , temp , bnum1 ) ; + return 0 ; +end diff --git a/Visual Novel/bin/numbers/BigRat.lua b/Visual Novel/bin/numbers/BigRat.lua new file mode 100644 index 0000000..40e9777 --- /dev/null +++ b/Visual Novel/bin/numbers/BigRat.lua @@ -0,0 +1,227 @@ +require( "bin.numbers.BigNum" ) ; + +BigRat = {} ; +BigRat.mt = {} ; +function BigRat.new( num1 , num2 ) --{{{2 + local bigrat = {} ; + local f ; + setmetatable(bigrat, BigRat.mt) ; + if type( num1 ) == "table" then + if num1.num ~= nil and num1.den ~= nil then + bigrat.num = BigNum.new( num1.num ) ; + bigrat.den = BigNum.new( num1.den ) ; + else + bigrat.num = BigNum.new( num1 ) ; + bigrat.den = BigNum.new( "1" ) ; + end + elseif num1 ~= nil then + if num2 == nil then + bigrat.den = BigNum.new( "1" ) ; + else + bigrat.den = BigNum.new( num2 ) ; + end + bigrat.num = BigNum.new( num1 ) ; + else + bigrat.den = BigNum.new( ) ; + bigrat.num = BigNum.new( ) ; + end + + --Update the signals + if bigrat.den.signal == "-" then + if bigrat.num.signal == "-" then + bigrat.num.signal = "+" ; + else + bigrat.num.signal = "-" ; + end + bigrat.den.signal = "+" ; + end + + return bigrat ; +end + +function BigRat.mt.sub( num1 , num2 ) + local temp = BigRat.new() ; + local brat1 = BigRat.new( num1 ) ; + local brat2 = BigRat.new( num2 ) ; + BigRat.sub( brat1 , brat2 , temp ) ; + return temp ; +end + +function BigRat.mt.add( num1 , num2 ) + local temp = BigRat.new() ; + local brat1 = BigRat.new( num1 ) ; + local brat2 = BigRat.new( num2 ) ; + BigRat.add( brat1 , brat2 , temp ) ; + return temp ; +end + +function BigRat.mt.mul( num1 , num2 ) + local temp = BigRat.new() ; + local brat1 = BigRat.new( num1 ) ; + local brat2 = BigRat.new( num2 ) ; + BigRat.mul( brat1 , brat2 , temp ) ; + return temp ; +end + +function BigRat.mt.div( num1 , num2 ) + local brat1 = BigRat.new( num1 ) ; + local brat2 = BigRat.new( num2 ) ; + local brat3 = BigRat.new() ; + local brat4 = BigRat.new() ; + BigRat.div( brat1 , brat2 , brat3 , brat4 ) ; + return brat3 , brat4 ; +end + +function BigRat.mt.tostring( brat ) + BigRat.simplify( brat ) ; + return BigNum.mt.tostring( brat.num ) .. " / " .. BigNum.mt.tostring( brat.den ) ; +end + +function BigRat.mt.pow ( num1 , num2 ) + local brat1 = BigRat.new( num1 ) ; + local brat2 = BigRat.new( num2 ) ; + return BigRat.pow( brat1 , brat2 ) +end + +function BigRat.mt.eq ( num1 , num2 ) + return BigRat.eq( num1 , num2 ) +end + +function BigRat.mt.lt ( num1 , num2 ) + return BigRat.lt( num1 , num2 ) +end + +function BigRat.mt.le ( num1 , num2 ) + return BigRat.le( num1 , num2 ) +end + +function BigRat.mt.unm ( num ) + local ret = BigRat.new( num ) + if ret.num.signal == '-' then + ret.num.signal = '+' + else + ret.num.signal = '-' + end + return ret +end + +BigRat.mt.__metatable = "hidden" +BigRat.mt.__tostring = BigRat.mt.tostring +BigRat.mt.__add = BigRat.mt.add +BigRat.mt.__sub = BigRat.mt.sub +BigRat.mt.__mul = BigRat.mt.mul +BigRat.mt.__div = BigRat.mt.div +BigRat.mt.__pow = BigRat.mt.pow +BigRat.mt.__unm = BigRat.mt.unm +BigRat.mt.__eq = BigRat.mt.eq +BigRat.mt.__le = BigRat.mt.le +BigRat.mt.__lt = BigRat.mt.lt +setmetatable( BigRat.mt, { __index = "inexistent field", __newindex = "not available", __metatable="hidden" } ) ; +function BigRat.add( brat1 , brat2 , brat3 ) + brat3.den = brat1.den * brat2.den ; + brat3.num = ( brat1.num * brat2.den ) + ( brat2.num * brat1.den ) ; + return brat3 ; +end +function BigRat.sub( brat1 , brat2 , brat3 ) + brat3.den = brat1.den * brat2.den ; + brat3.num = ( brat1.num * brat2.den ) - ( brat2.num * brat1.den ) ; + return brat3 ; +end + +function BigRat.mul( brat1 , brat2 , brat3 ) + brat3.num = brat1.num * brat2.num ; + brat3.den = brat1.den * brat2.den ; + return 0 ; +end + +function BigRat.div( brat1 , brat2 , brat3 ) + brat3.num = brat1.num * brat2.den ; + brat3.den = brat1.den * brat2.num ; + return brat3 ; +end + +function BigRat.pow( bnum1 , bnum2 ) + if bnum1 == nil or bnum2 == nil then + error( "Function BigRat.pow: parameter nil" ) ; + end + local x = BigRat.new( "8" ) ; + local n = BigRat.new( bnum2.den ) ; + local n2 ; + local y = BigRat.new( ) ; + local i ; + local temp = BigRat.new( ) ; + + BigRat.simplify( bnum2 ) ; + temp.num = BigNum.exp( bnum1.num , bnum2.num ) ; + temp.den = BigNum.exp( bnum1.den , bnum2.num ) ; + n2 = n - 1 ; + + for i = 0 , 4 do + y.num = x.num ^ n2.num ; + y.den = x.den ^ n2.num ; + x = (( temp / y ) + ( n2 * x )) / n ; + end + return x ; +end + +function BigRat.simplify( brat ) + if brat == nil then + error( "Function BigRat.simplify: parameter nil" ) ; + end + local gcd = BigNum.new( ) ; + local temp = BigRat.new( brat ) ; + local devnull = BigNum.new( ) ; + local zero = BigNum.new( "0" ) ; + --Check if numerator is zero + if BigNum.compareAbs( brat.num , zero ) == 0 then + brat.den = BigNum.new( "1" ) ; + return 0 ; + end + gcd = BigNum.gcd( brat.num , brat.den ) ; + BigNum.div( temp.num , gcd , brat.num , devnull ) ; + BigNum.div( temp.den , gcd , brat.den , devnull ) ; + --Update the signal + if brat.num.signal == '-' and brat.den.signal == '-' then + brat.num.signal = '+' ; + brat.den.signal = '+' ; + end + return 0 ; +end + +function BigRat.eq( brat1 , brat2 ) + if BigRat.compare( brat1 , brat2 ) == 0 then + return true ; + else + return false ; + end +end + +function BigRat.lt( brat1 , brat2 ) + if BigRat.compare( brat1 , brat2 ) == 2 then + return true ; + else + return false ; + end +end + +function BigRat.le( brat1 , brat2 ) + local temp = -1 ; + temp = BigRat.compare( brat1 , brat2 ) + if temp == 0 or temp == 2 then + return true ; + else + return false ; + end +end + +function BigRat.compare( bnum1 , bnum2 ) + local temp ; + temp = bnum1 - bnum2 ; + if temp.num[0] == 0 and temp.num.len == 1 then --Check if is zero + return 0 ; + elseif temp.num.signal == "-" then + return 2 ; + else + return 1 ; + end +end diff --git a/Visual Novel/bin/numbers/no_jit_bit.lua b/Visual Novel/bin/numbers/no_jit_bit.lua new file mode 100644 index 0000000..2cfdc1d --- /dev/null +++ b/Visual Novel/bin/numbers/no_jit_bit.lua @@ -0,0 +1,333 @@ +--[[ +LICENSE + + (c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT). +--]] + +local M = {_TYPE='module', _NAME='bit.numberlua', _VERSION='0.3.1.20120131'} + +local floor = math.floor + +local MOD = 2^32 +local MODM = MOD-1 + +local function memoize(f) + local mt = {} + local t = setmetatable({}, mt) + function mt:__index(k) + local v = f(k); t[k] = v + return v + end + return t +end + +local function make_bitop_uncached(t, m) + local function bitop(a, b) + local res,p = 0,1 + while a ~= 0 and b ~= 0 do + local am, bm = a%m, b%m + res = res + t[am][bm]*p + a = (a - am) / m + b = (b - bm) / m + p = p*m + end + res = res + (a+b)*p + return res + end + return bitop +end + +local function make_bitop(t) + local op1 = make_bitop_uncached(t,2^1) + local op2 = memoize(function(a) + return memoize(function(b) + return op1(a, b) + end) + end) + return make_bitop_uncached(op2, 2^(t.n or 1)) +end + +-- ok? probably not if running on a 32-bit int Lua number type platform +function M.tobit(x) + return x % 2^32 +end + +M.bxor = make_bitop {[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0}, n=4} +local bxor = M.bxor + +function M.bnot(a) return MODM - a end +local bnot = M.bnot + +function M.band(a,b) return ((a+b) - bxor(a,b))/2 end +local band = M.band + +function M.bor(a,b) return MODM - band(MODM - a, MODM - b) end +local bor = M.bor + +local lshift, rshift -- forward declare + +function M.rshift(a,disp) -- Lua5.2 insipred + if disp < 0 then return lshift(a,-disp) end + return floor(a % 2^32 / 2^disp) +end +rshift = M.rshift + +function M.lshift(a,disp) -- Lua5.2 inspired + if disp < 0 then return rshift(a,-disp) end + return (a * 2^disp) % 2^32 +end +lshift = M.lshift + +function M.tohex(x, n) -- BitOp style + n = n or 8 + local up + if n <= 0 then + if n == 0 then return '' end + up = true + n = - n + end + x = band(x, 16^n-1) + return ('%0'..n..(up and 'X' or 'x')):format(x) +end +local tohex = M.tohex + +function M.extract(n, field, width) -- Lua5.2 inspired + width = width or 1 + return band(rshift(n, field), 2^width-1) +end +local extract = M.extract + +function M.replace(n, v, field, width) -- Lua5.2 inspired + width = width or 1 + local mask1 = 2^width-1 + v = band(v, mask1) -- required by spec? + local mask = bnot(lshift(mask1, field)) + return band(n, mask) + lshift(v, field) +end +local replace = M.replace + +function M.bswap(x) -- BitOp style + local a = band(x, 0xff); x = rshift(x, 8) + local b = band(x, 0xff); x = rshift(x, 8) + local c = band(x, 0xff); x = rshift(x, 8) + local d = band(x, 0xff) + return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d +end +local bswap = M.bswap + +function M.rrotate(x, disp) -- Lua5.2 inspired + disp = disp % 32 + local low = band(x, 2^disp-1) + return rshift(x, disp) + lshift(low, 32-disp) +end +local rrotate = M.rrotate + +function M.lrotate(x, disp) -- Lua5.2 inspired + return rrotate(x, -disp) +end +local lrotate = M.lrotate + +M.rol = M.lrotate -- LuaOp inspired +M.ror = M.rrotate -- LuaOp insipred + + +function M.arshift(x, disp) -- Lua5.2 inspired + local z = rshift(x, disp) + if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end + return z +end +local arshift = M.arshift + +function M.btest(x, y) -- Lua5.2 inspired + return band(x, y) ~= 0 +end + +M.bit32 = {} -- Lua 5.2 'bit32' compatibility + + +local function bit32_bnot(x) + return (-1 - x) % MOD +end +M.bit32.bnot = bit32_bnot + +local function bit32_bxor(a, b, c, ...) + local z + if b then + a = a % MOD + b = b % MOD + z = bxor(a, b) + if c then + z = bit32_bxor(z, c, ...) + end + return z + elseif a then + return a % MOD + else + return 0 + end +end +M.bit32.bxor = bit32_bxor + +local function bit32_band(a, b, c, ...) + local z + if b then + a = a % MOD + b = b % MOD + z = ((a+b) - bxor(a,b)) / 2 + if c then + z = bit32_band(z, c, ...) + end + return z + elseif a then + return a % MOD + else + return MODM + end +end +M.bit32.band = bit32_band + +local function bit32_bor(a, b, c, ...) + local z + if b then + a = a % MOD + b = b % MOD + z = MODM - band(MODM - a, MODM - b) + if c then + z = bit32_bor(z, c, ...) + end + return z + elseif a then + return a % MOD + else + return 0 + end +end +M.bit32.bor = bit32_bor + +function M.bit32.btest(...) + return bit32_band(...) ~= 0 +end + +function M.bit32.lrotate(x, disp) + return lrotate(x % MOD, disp) +end + +function M.bit32.rrotate(x, disp) + return rrotate(x % MOD, disp) +end + +function M.bit32.lshift(x,disp) + if disp > 31 or disp < -31 then return 0 end + return lshift(x % MOD, disp) +end + +function M.bit32.rshift(x,disp) + if disp > 31 or disp < -31 then return 0 end + return rshift(x % MOD, disp) +end + +function M.bit32.arshift(x,disp) + x = x % MOD + if disp >= 0 then + if disp > 31 then + return (x >= 0x80000000) and MODM or 0 + else + local z = rshift(x, disp) + if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end + return z + end + else + return lshift(x, -disp) + end +end + +function M.bit32.extract(x, field, ...) + local width = ... or 1 + if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end + x = x % MOD + return extract(x, field, ...) +end + +function M.bit32.replace(x, v, field, ...) + local width = ... or 1 + if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end + x = x % MOD + v = v % MOD + return replace(x, v, field, ...) +end + +M.bit = {} -- LuaBitOp "bit" compatibility + +function M.bit.tobit(x) + x = x % MOD + if x >= 0x80000000 then x = x - MOD end + return x +end +local bit_tobit = M.bit.tobit + +function M.bit.tohex(x, ...) + return tohex(x % MOD, ...) +end + +function M.bit.bnot(x) + return bit_tobit(bnot(x % MOD)) +end + +local function bit_bor(a, b, c, ...) + if c then + return bit_bor(bit_bor(a, b), c, ...) + elseif b then + return bit_tobit(bor(a % MOD, b % MOD)) + else + return bit_tobit(a) + end +end +M.bit.bor = bit_bor + +local function bit_band(a, b, c, ...) + if c then + return bit_band(bit_band(a, b), c, ...) + elseif b then + return bit_tobit(band(a % MOD, b % MOD)) + else + return bit_tobit(a) + end +end +M.bit.band = bit_band + +local function bit_bxor(a, b, c, ...) + if c then + return bit_bxor(bit_bxor(a, b), c, ...) + elseif b then + return bit_tobit(bxor(a % MOD, b % MOD)) + else + return bit_tobit(a) + end +end +M.bit.bxor = bit_bxor + +function M.bit.lshift(x, n) + return bit_tobit(lshift(x % MOD, n % 32)) +end + +function M.bit.rshift(x, n) + return bit_tobit(rshift(x % MOD, n % 32)) +end + +function M.bit.arshift(x, n) + return bit_tobit(arshift(x % MOD, n % 32)) +end + +function M.bit.rol(x, n) + return bit_tobit(lrotate(x % MOD, n % 32)) +end + +function M.bit.ror(x, n) + return bit_tobit(rrotate(x % MOD, n % 32)) +end + +function M.bit.bswap(x) + return bit_tobit(bswap(x % MOD)) +end + +return M diff --git a/Visual Novel/bin/numbers/random.lua b/Visual Novel/bin/numbers/random.lua new file mode 100644 index 0000000..091a7f5 --- /dev/null +++ b/Visual Novel/bin/numbers/random.lua @@ -0,0 +1,232 @@ +--[[---------------------------------------- +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) + 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(os.time()) +end + +--Mersenne twister +local 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 = 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 + +local function twister(s) + local temp = {} + setmetatable(temp, mersenne_twister) + temp.mt = {} + temp.index = 0 + temp:randomseed(s) + return temp +end + +--Linear Congruential Generator +local 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 + +local 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 +local 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 + +local 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 +local 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 +return randomGen diff --git a/Visual Novel/bin/support/vfs.lua b/Visual Novel/bin/support/vfs.lua new file mode 100644 index 0000000..dae0b43 --- /dev/null +++ b/Visual Novel/bin/support/vfs.lua @@ -0,0 +1 @@ +local bin = require("bin") \ No newline at end of file diff --git a/conf.lua b/Visual Novel/conf.lua similarity index 87% rename from conf.lua rename to Visual Novel/conf.lua index 80d26f1..a39d08a 100644 --- a/conf.lua +++ b/Visual Novel/conf.lua @@ -1,14 +1,14 @@ 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.version = "11.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.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.width = 1540 -- The window width (number) + t.window.height = 960 -- 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.resizable = true -- 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) diff --git a/Visual Novel/init.dms b/Visual Novel/init.dms new file mode 100644 index 0000000..aa2a5fc --- /dev/null +++ b/Visual Novel/init.dms @@ -0,0 +1,6 @@ +ENTRY init +[init]{ + "Hi!" + "hmm..." + "wait!" +} \ No newline at end of file diff --git a/Visual Novel/main.lua b/Visual Novel/main.lua new file mode 100644 index 0000000..50f8adc --- /dev/null +++ b/Visual Novel/main.lua @@ -0,0 +1,36 @@ +require("Libs/Library") +local multi = require("multi") +local bin = require("bin") +GLOBAL,sThread = require("multi.integration.loveManager").init() +require("GuiManager") +require("parseManager") +local handle = parseManager:load("init.dms") +handle:define{ + sleep = thread.sleep +} +local disp = gui:newTextLabel("","",0,0,200,100) +local go = false +disp:OnReleased(function() + go = true +end) +parseManager.print(handle:dump()) +handle.__TEXT = function(text) + disp.text = text + thread.hold(function() + return go + end) + go = false +end +multi:newThread("Runner",function() + local active = true + while true do + thread.skip() + active = handle:think() + end +end) +function love.update() + multi:uManager() +end +multi.OnError(function(...) + print(...) +end) \ No newline at end of file diff --git a/Visual Novel/multi/compat/love2d.lua b/Visual Novel/multi/compat/love2d.lua new file mode 100644 index 0000000..7048deb --- /dev/null +++ b/Visual Novel/multi/compat/love2d.lua @@ -0,0 +1,76 @@ +--[[ +MIT License + +Copyright (c) 2019 Ryan Ward + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] +local multi = require("multi") +os.sleep=love.timer.sleep +multi.drawF={} +function multi:onDraw(func,i) + i=i or 1 + table.insert(self.drawF,i,func) +end +multi.OnKeyPressed = multi:newConnection() +multi.OnKeyReleased = multi:newConnection() +multi.OnMousePressed = multi:newConnection() +multi.OnMouseReleased = multi:newConnection() +multi.OnMouseWheelMoved = multi:newConnection() +multi.OnMouseMoved = multi:newConnection() +multi.OnDraw = multi:newConnection() +multi.OnTextInput = multi:newConnection() +multi.OnUpdate = multi:newConnection() +multi.OnQuit = multi:newConnection() +multi.OnPreLoad(function() + local function Hook(func,conn) + if love[func]~=nil then + love[func] = Library.convert(love[func]) + love[func]:inject(function(...) + conn:Fire(...) + return {...} + end,1) + elseif love[func]==nil then + love[func] = function(...) + conn:Fire(...) + end + end + end + Hook("quit",multi.OnQuit) + Hook("keypressed",multi.OnKeyPressed) + Hook("keyreleased",multi.OnKeyReleased) + Hook("mousepressed",multi.OnMousePressed) + Hook("mousereleased",multi.OnMouseReleased) + Hook("wheelmoved",multi.OnMouseWheelMoved) + Hook("mousemoved",multi.OnMouseMoved) + Hook("draw",multi.OnDraw) + Hook("textinput",multi.OnTextInput) + Hook("update",multi.OnUpdate) + multi.OnDraw(function() + for i=1,#multi.drawF do + love.graphics.setColor(255,255,255,255) + multi.drawF[i]() + end + end) +end) +multi.OnQuit(function() + multi.Stop() + love.event.quit() +end) +return multi diff --git a/Visual Novel/multi/init.lua b/Visual Novel/multi/init.lua new file mode 100644 index 0000000..418bc26 --- /dev/null +++ b/Visual Novel/multi/init.lua @@ -0,0 +1,2481 @@ +--[[ +MIT License + +Copyright (c) 2019 Ryan Ward + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] +local bin = pcall(require,"bin") +local multi = {} +local clock = os.clock +multi.Version = "13.0.0" +multi._VERSION = "13.0.0" +multi.stage = "stable" +multi.__index = multi +multi.Name = "multi.root" +multi.Mainloop = {} +multi.Garbage = {} +multi.ender = {} +multi.Children = {} +multi.Active = true +multi.fps = 60 +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.lastTime = clock() +local mainloopActive = false +local isRunning = false +local next +local ncount = 0 +multi.defaultSettings = { + priority = 0, + protect = false, +} +--Do not change these ever...Any other number will not work (Unless you are using enablePriority2()) +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.PriorityResolve = { + [1]="Core", + [4]="High", + [16]="Above Normal", + [64]="Normal", + [256]="Below Normal", + [1024]="Low", + [4096]="Idle", +} +multi.PStep = 1 +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.PriorityTick=1 -- Between 1, 2 and 4 +multi.Priority=multi.Priority_High +multi.threshold=256 +multi.threstimed=.001 +function multi.queuefinal(self) + self:Destroy() + if self.Parent.Mainloop[#self.Parent.Mainloop] then + if self.Parent.Mainloop[#self.Parent.Mainloop].Type=="alarm" then + self.Parent.Mainloop[#self.Parent.Mainloop]:Reset() + self.Parent.Mainloop[#self.Parent.Mainloop].Active=true + else + self.Parent.Mainloop[#self.Parent.Mainloop]:Resume() + end + else + for i=1,#self.Parent.funcE do + self.Parent.funcE[i](self) + end + self.Parent:Remove() + end +end +if table.unpack and not 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 +function multi:setThrestimed(n) + self.deltaTarget=n or .1 +end +function multi:enableLoadDetection() + if multi.maxSpd then return end + -- here we are going to run a quick benchMark solo + local temp = multi:newProcessor() + temp:Start() + local t = os.clock() + local stop = false + temp:benchMark(.01):OnBench(function(time,steps) + stop = steps + end) + while not stop do + temp:uManager() + end + temp:Destroy() + multi.maxSpd = stop +end +local MaxLoad = nil +function multi:setLoad(n) + MaxLoad = n +end +local busy = false +local lastVal = 0 +local bb = 0 +function multi:getLoad() + if not multi.maxSpd then multi:enableLoadDetection() end + if busy then return lastVal end + local val = nil + if thread.isThread() then + local bench + multi:benchMark(.01):OnBench(function(time,steps) + bench = steps + bb = steps + end) + thread.hold(function() + return bench + end) + bench = bench^1.5 + val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100) + else + busy = true + local bench + multi:benchMark(.01):OnBench(function(time,steps) + bench = steps + bb = steps + end) + while not bench do + multi:uManager() + end + bench = bench^1.5 + val = math.ceil((1-(bench/(multi.maxSpd/2.2)))*100) + busy = false + end + if val<0 then val = 0 end + if val > 100 then val = 100 end + lastVal = val + return val,bb*100 +end +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()=='a' 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()=='b' 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 + self.solid = true + end + if not self.PrioritySet then + self.defPriority = self.Priority + self.PrioritySet = true + end +end +function multi:ResetPriority() + self.Priority = self.defPriority +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.randomString(n) + local str = '' + local 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 + str = str..''..strings[math.random(1,#strings)] + end + return str +end +function multi:getParentProcess() + return self.Mainloop[self.CID] +end +multi.GetParentProcess=multi.getParentProcess +function multi.Stop() + mainloopActive=false +end +function multi:isHeld() + return self.held +end +multi.important={} +multi.IsHeld=multi.isHeld +function multi.executeFunction(name,...) + if type(_G[name])=='function' then + _G[name](...) + else + multi.print('Error: Not a function') + end +end +function multi:getChildren() + return self.Mainloop +end +function multi:getVersion() + return multi.Version +end +function multi:getPlatform() + if love then + if love.thread then + return "love2d" + end + else + return "lanes" + end +end +function multi:canSystemThread() + return false +end +--Processor +function multi:getError() + if self.error then + return self.error + end +end +function multi:benchMark(sec,p,pt) + local c = 0 + local temp=self:newLoop(function(self,t) + if t>sec then + if pt then + multi.print(pt.." "..c.." Steps in "..sec.." second(s)!") + end + self.tt(sec,c) + self:Destroy() + else + c=c+1 + end + end) + temp:setPriority(p or 1) + function temp:OnBench(func) + self.tt=func + end + self.tt=function() end + return temp +end +function multi.Round(num, numDecimalPlaces) + local mult = 10^(numDecimalPlaces or 0) + return math.floor(num * mult + 0.5) / mult +end +function multi.AlignTable(tab) + local longest = {} + local columns = #tab[1] + local rows = #tab + for i=1, columns do + longest[i] = -math.huge + end + for i = 1,rows do + for j = 1,columns do + tab[i][j] = tostring(tab[i][j]) + if #tab[i][j]>longest[j] then + longest[j] = #tab[i][j] + end + end + end + for i = 1,rows do + for j = 1,columns do + if tab[i][j]~=nil and #tab[i][j]","Uptime","Priority","TID"} + } + local count = 0 + for i,v in pairs(self.Mainloop) do + local name = v.Name or "" + if name~="" then + name = " <"..name..">" + end + count = count + 1 + table.insert(str,{v.Type:sub(1,1):upper()..v.Type:sub(2,-1)..name,multi.Round(os.clock()-v.creationTime,3),self.PriorityResolve[v.Priority],i}) + end + if count == 0 then + table.insert(str,{"Currently no processes running!","","",""}) + end + local s = multi.AlignTable(str) + dat = "" + dat2 = "" + if multi.SystemThreads then + for i = 1,#multi.SystemThreads do + dat2 = dat2.."\n" + end + end + local load,steps = multi:getLoad() + if multi.scheduler then + for i=1,#multi.scheduler.Threads do + dat = dat .. "\n" + end + return "Load on "..ProcessName[self.Type=="process"].."<"..(self.Name or "Unnamed")..">"..": "..multi.Round(load,2).."%\nCycles Per Second Per Task: "..steps.."\nMemory Usage: "..math.ceil(collectgarbage("count")).." KB\nThreads Running: "..#multi.scheduler.Threads.."\nSystemThreads Running: "..#(multi.SystemThreads or {}).."\nPriority Scheme: "..priorityTable[multi.defaultSettings.priority or 0].."\n\n"..s.."\n\n"..dat..dat2 + else + return "Load on "..ProcessName[self.Type=="process"].."<"..(self.Name or "Unnamed")..">"..": "..multi.Round(load,2).."%\nCycles Per Second Per Task: "..steps.."\n\nMemory Usage: "..math.ceil(collectgarbage("count")).." KB\nThreads Running: 0\nPriority Scheme: "..priorityTable[multi.defaultSettings.priority or 0].."\n\n"..s..dat2 + end + elseif t == "t" or t == "table" then + local load,steps = multi:getLoad() + str = { + ProcessName = (self.Name or "Unnamed"), + ThreadCount = #multi.scheduler.Threads, + MemoryUsage = math.ceil(collectgarbage("count")).." KB", + PriorityScheme = priorityTable[multi.defaultSettings.priority or 0], + SystemLoad = multi.Round(load,2), + CyclesPerSecondPerTask = steps, + } + str.threads = {} + str.systemthreads = {} + for i,v in pairs(self.Mainloop) do + str[#str+1]={Type=v.Type,Name=v.Name,Uptime=os.clock()-v.creationTime,Priority=self.PriorityResolve[v.Priority],TID = i} + end + for i=1,#multi.scheduler.Threads do + str.threads[multi.scheduler.Threads[i].Name]={Uptime = os.clock()-multi.scheduler.Threads[i].creationTime} + end + if multi.canSystemThread then + for i=1,#multi.SystemThreads do + str.systemthreads[multi.SystemThreads[i].Name]={Uptime = os.clock()-multi.SystemThreads[i].creationTime} + end + end + return str + end +end +function multi:endTask(TID) + self.Mainloop[TID]:Destroy() +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.timer(func,...) + local timer=multi:newTimer() + timer:Start() + args={func(...)} + local t = timer:Get() + timer = nil + return t,unpack(args) +end +function multi:IsAnActor() + return self.Act~=nil +end +function multi:OnMainConnect(func) + table.insert(self.func,func) + return self +end +function multi:reallocate(o,n) + n=n or #o.Mainloop+1 + local int=self.Parent + self:Destroy() + self.Parent=o + table.insert(o.Mainloop,n,self) + self.Active=true +end +multi.Reallocate=multi.Reallocate +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) + local count = 0 + for i=#self.Jobs,1,-1 do + if self.Jobs[i][2]==name then + table.remove(self.Jobs,i) + count = count + 1 + end + end + return count +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 + multi.print("Warning!!! "..self.Type.." doesn't contain a Final Connection State! Use "..self.Type..":Break(func) to trigger it's final event!") + self:OnBreak(func) + end +end +multi.ConnectFinal=multi.connectFinal +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 +multi.IsPaused=multi.isPaused +function multi:isActive() + return self.Active +end +multi.IsActive=multi.isActive +function multi:getType() + return self.Type +end +multi.GetType=multi.getType +-- Advance Timer stuff +function multi:SetTime(n) + if not n then n=3 end + local c=multi:newBase() + c.Type='timemaster' + c.timer=multi:newTimer() + c.timer:Start() + c.set=n + c.link=self + self._timer=c.timer + function c:Act() + if self.timer:Get()>=self.set then + self.link:Pause() + for i=1,#self.link.funcTM do + self.link.funcTM[i](self.link) + end + self:Destroy() + end + end + return self +end +multi.ResetTime=multi.SetTime +function multi:ResolveTimer(...) + self._timer:Pause() + for i=1,#self.funcTMR do + self.funcTMR[i](self,...) + end + self:Pause() + return self +end +function multi:OnTimedOut(func) + self.funcTM[#self.funcTM+1]=func + return self +end +function multi:OnTimerResolved(func) + self.funcTMR[#self.funcTMR+1]=func + return self +end +-- Timer stuff done +function multi:Pause() + if self.Type=='mainprocess' then + multi.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 + local loop = self.Parent.Mainloop + for i=1,#loop do + if loop[i] == self then + table.remove(loop,i) + break + end + end + end + return self +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.Active==false then + table.insert(self.Parent.Mainloop,self) + self.Active=true + end + end + return self +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 + return self +end +function multi:Reset(n) + self:Resume() + return self +end +function multi:isDone() + return self.Active~=true +end +multi.IsDone=multi.isDone +function multi:create(ref) + multi.OnObjectCreated:Fire(ref,self) +end +function multi:setName(name) + self.Name = name + return self +end +multi.SetName = multi.setName +--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.funcTM={} + c.funcTMR={} + c.ender={} + c.important={} + c.Act=function() end + c.Parent=self + c.held=false + c.creationTime = os.clock() + if ins then + table.insert(self.Mainloop,ins,c) + else + table.insert(self.Mainloop,c) + end + return c +end +function multi:newProcessor(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.Type='process' + c.Mainloop={} + c.Garbage={} + c.Children={} + c.Active=false + c.Rest=0 + c.Jobs={} + c.queue={} + c.jobUS=2 + c.l=self:newLoop(function(self,dt) + if self.link.Active then + c:uManager() + end + end) + c.l.link = c + c.l.Type = "processor" + function c:getController() + return c.l + end + function c:Start() + self.Active = true + return self + end + function c:Resume() + self.Active = false + return self + end + function c:setName(name) + c.l.Name = name + return self + end + function c:Pause() + if self.l then + self.l:Pause() + end + return self + end + function c:Remove() + if self.Type == "process" then + self:__Destroy() + self.l:Destroy() + else + self:__Destroy() + end + end + function c:Destroy() + if self == c then + self.l:Destroy() + else + for i = #c.Mainloop,1,-1 do + if c.Mainloop[i] == self then + table.remove(c.Mainloop,i) + break + end + end + end + end + if file then + self.Cself=c + loadstring('local process=multi.Cself '..io.open(file,'rb'):read('*all'))() + end + -- c.__Destroy = self.Destroy + -- c.Destroy = c.Remove + self:create(c) +--~ c:IngoreObject() + return c +end +function multi:newTimer() + local c={} + c.Type='timer' + local time=0 + local count=0 + local paused=false + function c:Start() + time=os.clock() + return self + end + function c:Get() + if self:isPaused() then return time end + return (clock()-time)+count + end + function c:isPaused() + return paused + end + c.Reset=c.Start + function c:Pause() + time=self:Get() + paused=true + return self + end + function c:Resume() + paused=false + time=os.clock()-time + return self + end + function c:tofile(path) + local m=bin.new() + count=count+self:Get() + m:addBlock(self.Type) + m:addBlock(count) + m:tofile(path) + return self + end + self:create(c) + return c +end +function multi:newConnector() + local c = {Type = "connector"} + return c +end +function multi:newConnection(protect,func) + local c={} + c.callback = func + c.Parent=self + setmetatable(c,{__call=function(self,...) + local t = ... + if type(t)=="table" and t.Type ~= nil then + return self:Fire(args,select(2,...)) + else + return self:connect(...) + end + end}) + c.Type='connector' + c.func={} + c.ID=0 + c.protect=protect or true + c.connections={} + c.fconnections={} + c.FC=0 + function c:holdUT(n) + local n=n or 0 + self.waiting=true + local count=0 + local id=self:connect(function() + count = count + 1 + if n<=count then + self.waiting=false + end + end) + repeat + self.Parent:uManager(multi.defaultSettings) + until self.waiting==false + id:Destroy() + return self + end + c.HoldUT=c.holdUT + function c:fConnect(func) + local temp=self:connect(func) + table.insert(self.fconnections,temp) + self.FC=self.FC+1 + return self + end + c.FConnect=c.fConnect + function c:getConnection(name,ingore) + if ingore then + return self.connections[name] or { + Fire=function() return end -- if the connection doesn't exist lets call all of them or silently ignore + } + else + return self.connections[name] or self + end + end + 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 + multi.print(temp[2]) + end + else + table.insert(ret,{self.func[i][1](...)}) + end + end + return ret + end + function c:Bind(t) + self.func=t + return self + end + function c:Remove() + self.func={} + return self + end + function c:connect(func,name,num) + self.ID=self.ID+1 + table.insert(self.func,num or #self.func+1,{func,self.ID}) + local temp = { + Link=self.func, + func=func, + ID=self.ID, + Parent=self, + Fire=function(self,...) +--~ if self.Parent.FC>0 then +--~ for i=1,#self.Parent.FC do +--~ self.Parent.FC[i]:Fire(...) +--~ end +--~ end + if self.Parent.protect then + local t=pcall(self.func,...) + if t then + return t + end + else + return self.func(...) + end + end, + 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, + } + temp.Destroy=temp.Remove + if name then + self.connections[name]=temp + end + if self.callback then + self.callback(temp) + end + return temp + end + c.Connect=c.connect + c.GetConnection=c.getConnection + function c:tofile(path) + local m=bin.new() + m:addBlock(self.Type) + m:addBlock(self.func) + m:tofile(path) + return self + end + return c +end +multi.OnObjectCreated=multi:newConnection() +multi.OnObjectDestroyed=multi:newConnection() +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.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):setName("multi.jobHandler") + 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.nextStep(func) + ncount = ncount+1 + if not next then + next = {func} + else + next[#next+1] = func + end +end +multi.OnPreLoad=multi:newConnection() +--Core Actors +function multi:newCustomObject(objRef,isActor) + local c={} + if isActor then + c=self:newBase() + 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 + self:create(c) + return c +end +function multi:newEvent(task) + local c=self:newBase() + c.Type='event' + c.Task=task or function() end + function c:Act() + local t = {self.Task(self)} + if t[1] then + self:Pause() + self.returns = t + for _E=1,#self.func do + self.func[_E](self) + end + end + end + function c:SetTask(func) + self.Task=func + return self + end + function c:OnEvent(func) + table.insert(self.func,func) + return self + end + self:setPriority("core") + self:create(c) + return c +end +function multi:newUpdater(skip) + local c=self:newBase() + 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 + return self + end + c.OnUpdate=self.OnMainConnect + self:create(c) + return c +end +function multi:newAlarm(set) + local c=self:newBase() + c.Type='alarm' + c:setPriority("Low") + c.set=set or 0 + local count = 0 + local t = clock() + function c:Act() + if clock()-t>=self.set then + self:Pause() + self.Active=false + for i=1,#self.func do + self.func[i](self) + end + t = clock() + end + end + function c:Resume() + self.Parent.Resume(self) + t = count + t + return self + end + function c:Reset(n) + if n then self.set=n end + self:Resume() + t = clock() + return self + end + function c:OnRing(func) + table.insert(self.func,func) + return self + end + function c:Pause() + count = clock() + self.Parent.Pause(self) + return self + end + self:create(c) + return c +end +function multi:newLoop(func) + local c=self:newBase() + c.Type='loop' + local start=self.clock() + local funcs = {} + if func then + funcs={func} + end + function c:Act() + for i=1,#funcs do + funcs[i](self,clock()-start) + end + end + function c:OnLoop(func) + table.insert(funcs,func) + return self + end + self:create(c) + return c +end +function multi:newFunction(func) + local c={} + c.func=func + mt={ + __index=multi, + __call=function(self,...) + if self.Active then + return self:func(...) + end + return nil,true + end + } + c.Parent=self + function c:Pause() + self.Active=false + return self + end + function c:Resume() + self.Active=true + return self + end + setmetatable(c,mt) + self:create(c) + 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.funcS={} + 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.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,self.pos) + 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) + return self + end + function c:OnStep(func) + table.insert(self.func,1,func) + return self + end + function c:OnEnd(func) + table.insert(self.funcE,func) + return self + end + function c:Break() + self.Active=nil + return self + 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() + return self + end + self:create(c) + return c +end +function multi:newTLoop(func,set) + local c=self:newBase() + c.Type='tloop' + c.set=set or 0 + c.timer=self:newTimer() + c.life=0 + c:setPriority("Low") + if func then + c.func={func} + end + function c:Act() + if self.timer:Get()>=self.set then + self.life=self.life+1 + for i=1,#self.func do + self.func[i](self,self.life) + end + self.timer:Reset() + end + end + function c:Resume() + self.Parent.Resume(self) + self.timer:Resume() + return self + end + function c:Pause() + self.timer:Pause() + self.Parent.Pause(self) + return self + end + function c:OnLoop(func) + table.insert(self.func,func) + return self + end + self:create(c) + return c +end +function multi:newTrigger(func) + local c={} + c.Type='trigger' + c.trigfunc=func or function() end + function c:Fire(...) + self:trigfunc(...) + return self + end + self:create(c) + return c +end +function multi:newTStep(start,reset,count,set) + local c=self:newBase() + think=1 + c.Type='tstep' + c:setPriority("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() + return self + 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,self.pos) + 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) + return self + end + function c:OnStep(func) + table.insert(self.func,func) + return self + end + function c:OnEnd(func) + table.insert(self.funcE,func) + return self + end + function c:Break() + self.Active=nil + return self + end + function c:Reset(n) + if n then self.set=n end + self.timer=self.clock() + self:Resume() + return self + end + self:create(c) + return c +end +function multi:newTimeStamper() + local c=self:newUpdater(self.Priority_Idle) + c:OnUpdate(function() + c:Run() + end) + local feb = 28 + local leap = tonumber(os.date("%Y"))%4==0 and (tonumber(os.date("%Y"))%100~=0 or tonumber(os.date("%Y"))%400==0) + if leap then + feb = 29 + end + local dInM = { + ["01"] = 31, + ["02"] = feb, + ["03"] = 31, + ["04"] = 30, + ["05"] = 31, + ["06"] = 30, + ["07"] = 31, -- This is dumb, why do we still follow this double 31 days!? + ["08"] = 31, + ["09"] = 30, + ["10"] = 31, + ["11"] = 30, + ["12"] = 31, + } + c.Type='timestamper' + c:setPriority("Idle") + c.hour = {} + c.minute = {} + c.second = {} + c.time = {} + c.day = {} + c.month = {} + c.year = {} + function c:Run() + for i=1,#self.hour do + if self.hour[i][1]==os.date("%H") and self.hour[i][3] then + self.hour[i][2](self) + self.hour[i][3]=false + elseif self.hour[i][1]~=os.date("%H") and not self.hour[i][3] then + self.hour[i][3]=true + end + end + for i=1,#self.minute do + if self.minute[i][1]==os.date("%M") and self.minute[i][3] then + self.minute[i][2](self) + self.minute[i][3]=false + elseif self.minute[i][1]~=os.date("%M") and not self.minute[i][3] then + self.minute[i][3]=true + end + end + for i=1,#self.second do + if self.second[i][1]==os.date("%S") and self.second[i][3] then + self.second[i][2](self) + self.second[i][3]=false + elseif self.second[i][1]~=os.date("%S") and not self.second[i][3] then + self.second[i][3]=true + end + end + for i=1,#self.day do + if type(self.day[i][1])=="string" then + if self.day[i][1]==os.date("%a") and self.day[i][3] then + self.day[i][2](self) + self.day[i][3]=false + elseif self.day[i][1]~=os.date("%a") and not self.day[i][3] then + self.day[i][3]=true + end + else + local dday = self.day[i][1] + if dday < 0 then + dday = dInM[os.date("%m")]+(dday+1) + end + if string.format("%02d",dday)==os.date("%d") and self.day[i][3] then + self.day[i][2](self) + self.day[i][3]=false + elseif string.format("%02d",dday)~=os.date("%d") and not self.day[i][3] then + self.day[i][3]=true + end + end + end + for i=1,#self.month do + if self.month[i][1]==os.date("%m") and self.month[i][3] then + self.month[i][2](self) + self.month[i][3]=false + elseif self.month[i][1]~=os.date("%m") and not self.month[i][3] then + self.month[i][3]=true + end + end + for i=1,#self.time do + if self.time[i][1]==os.date("%X") and self.time[i][3] then + self.time[i][2](self) + self.time[i][3]=false + elseif self.time[i][1]~=os.date("%X") and not self.time[i][3] then + self.time[i][3]=true + end + end + for i=1,#self.year do + if self.year[i][1]==os.date("%y") and self.year[i][3] then + self.year[i][2](self) + self.year[i][3]=false + elseif self.year[i][1]~=os.date("%y") and not self.year[i][3] then + self.year[i][3]=true + end + end + end + function c:OnTime(hour,minute,second,func) + if type(hour)=="number" then + self.time[#self.time+1]={string.format("%02d:%02d:%02d",hour,minute,second),func,true} + else + self.time[#self.time+1]={hour,minute,true} + end + return self + end + function c:OnHour(hour,func) + self.hour[#self.hour+1]={string.format("%02d",hour),func,true} + return self + end + function c:OnMinute(minute,func) + self.minute[#self.minute+1]={string.format("%02d",minute),func,true} + return self + end + function c:OnSecond(second,func) + self.second[#self.second+1]={string.format("%02d",second),func,true} + return self + end + function c:OnDay(day,func) + self.day[#self.day+1]={day,func,true} + return self + end + function c:OnMonth(month,func) + self.month[#self.month+1]={string.format("%02d",month),func,true} + return self + end + function c:OnYear(year,func) + self.year[#self.year+1]={string.format("%02d",year),func,true} + return self + end + self:create(c) + return c +end +function multi:newWatcher(namespace,name) + local function WatcherObj(ns,n) + if self.Type=='queue' then + multi.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) + return self + 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 + multi.print('Warning, invalid arguments! Nothing returned!') + end +end +-- Threading stuff +thread={} +multi.GlobalVariables={} +if os.getOS()=="windows" then + thread.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) +else + thread.__CORES=tonumber(io.popen("nproc --all"):read("*n")) +end +function thread.sleep(n) + coroutine.yield({"_sleep_",n or 0}) +end +function thread.hold(n) + return coroutine.yield({"_hold_",n or function() return true end}) +end +function thread.skip(n) + coroutine.yield({"_skip_",n or 0}) +end +function thread.kill() + coroutine.yield({"_kill_",":)"}) +end +function thread.yeild() + coroutine.yield({"_sleep_",0}) +end +function thread.isThread() + return coroutine.running()~=nil +end +function thread.getCores() + return thread.__CORES +end +function thread.set(name,val) + multi.GlobalVariables[name]=val + return true +end +function thread.get(name) + return multi.GlobalVariables[name] +end +function thread.waitFor(name) + thread.hold(function() return thread.get(name)~=nil end) + return thread.get(name) +end +function thread.testFor(name,_val,sym) + thread.hold(function() + local val = thread.get(name)~=nil + if val then + if sym == "==" or sym == "=" then + return _val==val + elseif sym == ">" then + return _val>val + elseif sym == "<" then + return _val=" then + return _val>=val + end + end + end) + return thread.get(name) +end +function multi.print(...) + if multi.defaultSettings.print then + print(...) + end +end +multi:setDomainName("Threads") +multi:setDomainName("Globals") +local initT = false +local threadCount = 0 +function multi:newThread(name,func) + local func = func + if type(name) == "function" then + func = name + name = "Thread#"..threadCount + end + local c={} + c.ref={} + c.Name=name + c.thread=coroutine.create(func) + c.sleep=1 + c.Type="thread" + c.firstRunDone=false + c.timer=multi: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) + if type(n)=="function" then + ret=coroutine.yield({"_hold_",n}) + self:syncGlobals(ret) + elseif type(n)=="number" then + n = tonumber(n) or 0 + ret=coroutine.yield({"_sleep_",n}) + self:syncGlobals(ret) + else + error("Invalid Type for sleep!") + end + end + function c.ref:syncGlobals(v) + self.Globals=v + end + table.insert(self:linkDomain("Threads"),c) + if initT==false then + multi.initThreads() + end + c.creationTime = os.clock() +end +function multi.initThreads() + initT = true + multi.scheduler=multi:newLoop():setName("multi.thread") + multi.scheduler.Type="scheduler" + function multi.scheduler:setStep(n) + self.skip=tonumber(n) or 24 + end + multi.scheduler.skip=0 + multi.scheduler.counter=0 + multi.scheduler.Threads=multi:linkDomain("Threads") + multi.scheduler.Globals=multi:linkDomain("Globals") + multi.scheduler:OnLoop(function(self) + self.counter=self.counter+1 + 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() + if unpack(self.Threads[i].returns or {}) then + _,ret=coroutine.resume(self.Threads[i].thread,unpack(self.Threads[i].returns)) + else + _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) + end + else + if unpack(self.Threads[i].returns or {}) then + _,ret=coroutine.resume(self.Threads[i].thread,unpack(self.Threads[i].returns)) + else + _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) + end + end + if _==false then + self.Parent.OnError:Fire(self.Threads[i],"Error in thread: <"..self.Threads[i].Name.."> "..ret) + end + if ret==true or ret==false then + multi.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[1]=="_skip_" then + self.Threads[i].timer:Reset() + self.Threads[i].sleep=math.huge + local event=multi:newEvent(function(evnt) return multi.scheduler.counter>=evnt.counter end) + event.link=self.Threads[i] + event.counter=self.counter+ret[2] + event:OnEvent(function(evnt) + evnt.link.sleep=0 + evnt:Destroy() + end):setName("multi.thread.skip") + elseif ret[1]=="_hold_" then + self.Threads[i].timer:Reset() + self.Threads[i].sleep=math.huge + local event=multi:newEvent(ret[2]) + event.returns = nil + event.link=self.Threads[i] + event:OnEvent(function(evnt) + evnt.link.sleep=0 + evnt.link.returns = evnt.returns + multi.nextStep(function() + evnt:Destroy() + end) + end):setName("multi.thread.hold") + elseif ret.Name then + self.Globals[ret.Name]=ret.Value + end + end + end + end + end) +end +multi.OnError=multi:newConnection() +function multi:newThreadedProcess(name) + local c = {} + local holding = false + local kill = false + setmetatable(c, multi) + function c:newBase(ins) + local ct = {} + ct.Active=true + ct.func={} + ct.ender={} + ct.Act=function() end + ct.Parent=self + ct.held=false + ct.ref=self.ref + table.insert(self.Mainloop,ct) + return ct + end + c.Parent=self + c.Active=true + c.func={} + c.Type='threadedprocess' + c.Mainloop={} + c.Garbage={} + c.Children={} + c.Active=true + c.Rest=0 + c.updaterate=.01 + c.restRate=.1 + c.Jobs={} + c.queue={} + c.jobUS=2 + c.rest=false + function c:getController() + return nil + end + function c:Start() + self.rest=false + return self + end + function c:Resume() + self.rest=false + return self + end + function c:Pause() + self.rest=true + return self + end + function c:Remove() + self.ref:kill() + return self + end + function c:Kill() + kill = true + return self + end + function c:Sleep(n) + holding = true + if type(n)=="number" then + multi:newAlarm(n):OnRing(function(a) + holding = false + a:Destroy() + end):setName("multi.TPSleep") + elseif type(n)=="function" then + multi:newEvent(n):OnEvent(function(e) + holding = false + e:Destroy() + end):setName("multi.TPHold") + end + return self + end + c.Hold=c.Sleep + multi:newThread(name,function(ref) + while true do + thread.hold(function() + return not(holding) + end) + c:uManager() + end + end) + return c +end +function multi:newHyperThreadedProcess(name) + if not name then error("All threads must have a name!") end + local c = {} + setmetatable(c, multi) + local ind = 0 + local holding = true + local kill = false + function c:newBase(ins) + local ct = {} + ct.Active=true + ct.func={} + ct.ender={} + ct.Act=function() end + ct.Parent=self + ct.held=false + ct.ref=self.ref + ind = ind + 1 + multi:newThread("Proc <"..name.."> #"..ind,function() + while true do + thread.hold(function() + return not(holding) + end) + if kill then + err=coroutine.yield({"_kill_"}) + if err then + error("Failed to kill a thread! Exiting...") + end + end + ct:Act() + end + end) + return ct + end + c.Parent=self + c.Active=true + c.func={} + c.Type='hyperthreadedprocess' + c.Mainloop={} + c.Garbage={} + c.Children={} + c.Active=true + c.Rest=0 + c.updaterate=.01 + c.restRate=.1 + c.Jobs={} + c.queue={} + c.jobUS=2 + c.rest=false + function c:getController() + return nil + end + function c:Start() + holding = false + return self + end + function c:Resume() + holding = false + return self + end + function c:Pause() + holding = true + return self + end + function c:Remove() + self.ref:kill() + return self + end + function c:Kill() + kill = true + return self + end + function c:Sleep(b) + holding = true + if type(b)=="number" then + local t = os.clock() + multi:newAlarm(b):OnRing(function(a) + holding = false + a:Destroy() + end):setName("multi.HTPSleep") + elseif type(b)=="function" then + multi:newEvent(b):OnEvent(function(e) + holding = false + e:Destroy() + end):setName("multi.HTPHold") + end + return self + end + c.Hold=c.Sleep + return c +end +-- Multi runners +function multi:threadloop(settings) + multi.scheduler:Destroy() -- destroy is an interesting thing... if you dont set references to nil, then you only remove it from the mainloop + local Threads=multi:linkDomain("Threads") + local Globals=multi:linkDomain("Globals") + local counter=0 + local tick = 0 + while true do + tick = tick + 1 + if tick == 1024 then + tick = 0 + multi:uManager(settings) + end + counter=counter+1 + for i=#Threads,1,-1 do + ret={} + if coroutine.status(Threads[i].thread)=="dead" then + table.remove(Threads,i) + else + if Threads[i].timer:Get()>=Threads[i].sleep then + if Threads[i].firstRunDone==false then + Threads[i].firstRunDone=true + Threads[i].timer:Start() + _,ret=coroutine.resume(Threads[i].thread,Threads[i].ref) + else + _,ret=coroutine.resume(Threads[i].thread,Globals) + end + if _==false then + multi.OnError:Fire(Threads[i],"Error in thread: <"..Threads[i].Name.."> "..ret) + end + if ret==true or ret==false then + ret={} + end + end + if ret then + if ret[1]=="_kill_" then + table.remove(Threads,i) + elseif ret[1]=="_sleep_" then + Threads[i].timer:Reset() + Threads[i].sleep=ret[2] + elseif ret[1]=="_skip_" then + Threads[i].timer:Reset() + Threads[i].sleep=math.huge + local event=multi:newEvent(function(evnt) return counter>=evnt.counter end) + event.link=Threads[i] + event.counter=counter+ret[2] + event:OnEvent(function(evnt) + evnt.link.sleep=0 + evnt:Destroy() + end) + elseif ret[1]=="_hold_" then + Threads[i].timer:Reset() + Threads[i].sleep=math.huge + local event=multi:newEvent(ret[2]) + event.link=Threads[i] + event:OnEvent(function(evnt) + evnt.link.sleep=0 + evnt:Destroy() + end) + elseif ret.Name then + Globals[ret.Name]=ret.Value + end + end + end + end + end +end +function multi:mainloop(settings) + multi.defaultSettings = settings or multi.defaultSettings + self.uManager=self.uManagerRef + multi.OnPreLoad:Fire() + local p_c,p_h,p_an,p_n,p_bn,p_l,p_i = self.Priority_Core,self.Priority_High,self.Priority_Above_Normal,self.Priority_Normal,self.Priority_Below_Normal,self.Priority_Low,self.Priority_Idle + local P_LB = p_i + if not isRunning then + local protect = false + local priority = false + local stopOnError = true + local delay = 3 + if settings then + priority = settings.priority + if settings.auto_priority then + priority = -1 + end + if settings.preLoop then + settings.preLoop(self) + end + if settings.stopOnError then + stopOnError = settings.stopOnError + end + if settings.auto_stretch then + p_i = p_i * settings.auto_stretch + end + if settings.auto_delay then + delay = settings.auto_delay + end + if settings.auto_lowerbound then + P_LB = settings.auto_lowerbound + end + protect = settings.protect + end + local t,tt = clock(),0 + isRunning=true + local lastTime = clock() + rawset(self,'Start',clock()) + mainloopActive = true + local Loop=self.Mainloop + local PS=self + local PStep = 1 + local autoP = 0 + local solid,sRef + local cc=0 + while mainloopActive do + if next then + local DD = table.remove(next,1) + while DD do + DD() + DD = table.remove(next,1) + end + end + if priority == 1 then + for _D=#Loop,1,-1 do + for P=1,7 do + if Loop[_D] then + if (PS.PList[P])%Loop[_D].Priority==0 then + if Loop[_D].Active then + self.CID=_D + if not protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + end + elseif priority == 2 then + for _D=#Loop,1,-1 do + if Loop[_D] then + if (PStep)%Loop[_D].Priority==0 then + if Loop[_D].Active then + self.CID=_D + if not protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + PStep=PStep+1 + if PStep==p_i then + PStep=0 + end + elseif priority == 3 then + cc=cc+1 + if cc == 1000 then + tt = clock()-t + t = clock() + cc=0 + end + for _D=#Loop,1,-1 do + if Loop[_D] then + if Loop[_D].Priority == p_c or (Loop[_D].Priority == p_h and tt<.5) or (Loop[_D].Priority == p_an and tt<.125) or (Loop[_D].Priority == p_n and tt<.063) or (Loop[_D].Priority == p_bn and tt<.016) or (Loop[_D].Priority == p_l and tt<.003) or (Loop[_D].Priority == p_i and tt<.001) then + if Loop[_D].Active then + self.CID=_D + if not protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + elseif priority == -1 then + for _D=#Loop,1,-1 do + sRef = Loop[_D] + if Loop[_D] then + if (sRef.Priority == p_c) or PStep==0 then + if sRef.Active then + self.CID=_D + if not protect then + if sRef.solid then + sRef:Act() + solid = true + else + time = multi.timer(sRef.Act,sRef) + sRef.solid = true + solid = false + end + if Loop[_D] and not solid then + if time == 0 then + Loop[_D].Priority = p_c + else + Loop[_D].Priority = P_LB + end + end + else + if Loop[_D].solid then + Loop[_D]:Act() + solid = true + else + time, status, err=multi.timer(pcall,Loop[_D].Act,Loop[_D]) + Loop[_D].solid = true + solid = false + end + if Loop[_D] and not solid then + if time == 0 then + Loop[_D].Priority = p_c + else + Loop[_D].Priority = P_LB + end + end + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + PStep=PStep+1 + if PStep>p_i then + PStep=0 + if clock()-lastTime>delay then + lastTime = clock() + for i = 1,#Loop do + Loop[i]:ResetPriority() + end + end + end + else + for _D=#Loop,1,-1 do + if Loop[_D] then + if Loop[_D].Active then + self.CID=_D + if not protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + end + else + return "Already Running!" + end +end +function multi:uManager(settings) + multi.OnPreLoad:Fire() + multi.defaultSettings = settings or multi.defaultSettings + self.t,self.tt = clock(),0 + if settings then + priority = settings.priority + if settings.auto_priority then + priority = -1 + end + if settings.preLoop then + settings.preLoop(self) + end + if settings.stopOnError then + stopOnError = settings.stopOnError + end + multi.defaultSettings.p_i = self.Priority_Idle + if settings.auto_stretch then + multi.defaultSettings.p_i = settings.auto_stretch*self.Priority_Idle + end + multi.defaultSettings.delay = settings.auto_delay or 3 + multi.defaultSettings.auto_lowerbound = settings.auto_lowerbound or self.Priority_Idle + protect = settings.protect + end + self.uManager=self.uManagerRef +end +function multi:uManagerRef(settings) + if self.Active then + if next then + local DD = table.remove(next,1) + while DD do + DD() + DD = table.remove(next,1) + end + end + local Loop=self.Mainloop + local PS=self + if multi.defaultSettings.priority==1 then + for _D=#Loop,1,-1 do + for P=1,7 do + if Loop[_D] then + if (PS.PList[P])%Loop[_D].Priority==0 then + if Loop[_D].Active then + self.CID=_D + if not multi.defaultSettings.protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if multi.defaultSettings.stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + end + elseif multi.defaultSettings.priority==2 then + for _D=#Loop,1,-1 do + if Loop[_D] then + if (PS.PStep)%Loop[_D].Priority==0 then + if Loop[_D].Active then + self.CID=_D + if not multi.defaultSettings.protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if multi.defaultSettings.stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + PS.PStep=PS.PStep+1 + if PS.PStep>self.Priority_Idle then + PS.PStep=0 + end + elseif priority == 3 then + self.tt = clock()-self.t + self.t = clock() + for _D=#Loop,1,-1 do + if Loop[_D] then + if Loop[_D].Priority == self.Priority_Core or (Loop[_D].Priority == self.Priority_High and tt<.5) or (Loop[_D].Priority == self.Priority_Above_Normal and tt<.125) or (Loop[_D].Priority == self.Priority_Normal and tt<.063) or (Loop[_D].Priority == self.Priority_Below_Normal and tt<.016) or (Loop[_D].Priority == self.Priority_Low and tt<.003) or (Loop[_D].Priority == self.Priority_Idle and tt<.001) then + if Loop[_D].Active then + self.CID=_D + if not protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if multi.defaultSettings.stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + elseif priority == -1 then + for _D=#Loop,1,-1 do + local sRef = Loop[_D] + if Loop[_D] then + if (sRef.Priority == self.Priority_Core) or PStep==0 then + if sRef.Active then + self.CID=_D + if not protect then + if sRef.solid then + sRef:Act() + solid = true + else + time = multi.timer(sRef.Act,sRef) + sRef.solid = true + solid = false + end + if Loop[_D] and not solid then + if time == 0 then + Loop[_D].Priority = self.Priority_Core + else + Loop[_D].Priority = multi.defaultSettings.auto_lowerbound + end + end + else + if Loop[_D].solid then + Loop[_D]:Act() + solid = true + else + time, status, err=multi.timer(pcall,Loop[_D].Act,Loop[_D]) + Loop[_D].solid = true + solid = false + end + if Loop[_D] and not solid then + if time == 0 then + Loop[_D].Priority = self.Priority_Core + else + Loop[_D].Priority = multi.defaultSettings.auto_lowerbound + end + end + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + if multi.defaultSettings.stopOnError then + Loop[_D]:Destroy() + end + end + end + end + end + end + end + self.PStep=self.PStep+1 + if self.PStep>multi.defaultSettings.p_i then + self.PStep=0 + if clock()-self.lastTime>multi.defaultSettings.delay then + self.lastTime = clock() + for i = 1,#Loop do + Loop[i]:ResetPriority() + end + end + end + else + for _D=#Loop,1,-1 do + if Loop[_D] then + if Loop[_D].Active then + self.CID=_D + if not multi.defaultSettings.protect then + Loop[_D]:Act() + else + local status, err=pcall(Loop[_D].Act,Loop[_D]) + if err then + Loop[_D].error=err + self.OnError:Fire(Loop[_D],err) + end + end + end + end + end + end + end +end +-- State Saving Stuff +function multi:IngoreObject() + self.Ingore=true + return self +end +function multi:ToString() + if self.Ingore then return end + local t=self.Type + local data; + multi.print(t) + if t:sub(-6)=="Thread" then + data={ + Type=t, + rest=self.rest, + updaterate=self.updaterest, + restrate=self.restrate, + name=self.name, + func=self.func, + important=self.important, + Active=self.Active, + ender=self.ender, + held=self.held, + } + else + data={ + Type=t, + func=self.func, + funcTM=self.funcTM, + funcTMR=self.funcTMR, + important=self.important, + ender=self.ender, + held=self.held, + } + end + if t=="eventThread" or t=="event" then + table.merge(data,{ + Task=self.Task, + }) + elseif t=="loopThread" or t=="loop" then + table.merge(data,{ + Start=self.Start, + }) + elseif t=="stepThread" or t=="step" then + table.merge(data,{ + funcE=self.funcE, + funcS=self.funcS, + pos=self.pos, + endAt=self.endAt, + start=self.start, + spos=self.spos, + skip=self.skip, + count=self.count, + }) + elseif t=="tloopThread" then + table.merge(data,{ + restN=self.restN, + }) + elseif t=="tloop" then + table.merge(data,{ + set=self.set, + life=self.life, + }) + elseif t=="tstepThread" or t=="tstep" then + table.merge(data,{ + funcE=self.funcE, + funcS=self.funcS, + pos=self.pos, + endAt=self.endAt, + start=self.start, + spos=self.spos, + skip=self.skip, + count=self.count, + timer=self.timer, + set=self.set, + reset=self.reset, + }) + elseif t=="updaterThread" or t=="updater" then + table.merge(data,{ + pos=self.pos, + skip=self.skip, + }) + elseif t=="alarmThread" or t=="alarm" then + table.merge(data,{ + set=self.set, + }) + elseif t=="watcher" then + multi.print("Currently cannot sterilize a watcher object!") + -- needs testing + -- table.merge(data,{ + -- ns=self.ns, + -- n=self.n, + -- cv=self.cv, + -- }) + elseif t=="timemaster" then + -- Weird stuff is going on here! + -- Need to do some testing + table.merge(data,{ + timer=self.timer, + _timer=self._timer, + set=self.set, + link=self.link, + }) + elseif t=="process" or t=="mainprocess" then + local loop=self.Mainloop + local dat={} + for i=1,#loop do + local ins=loop[i]:ToString() + if ins~=nil then + table.insert(dat,ins) + end + end + local str=bin.new() + str:addBlock({Type=t}) + str:addBlock(#dat,4,"n") + for i=1,#dat do + str:addBlock(#dat[i],4,"n") + str:addBlock(dat[i]) + end + return str.data + end + for i,v in pairs(self.important) do + data[v]=self[v] + end + local str=bin.new() + str:addBlock(data) + return str.data +end +function multi:newFromString(str) + if type(str)=="table" then + if str.Type=="bin" then + str=str.data + end + end + local handle=bin.new(str) + local data=handle:getBlock("t") + local t=data.Type + if t=="mainprocess" then + local objs=handle:getBlock("n",4) + for i=1,objs do + self:newFromString(handle:getBlock("s",(handle:getBlock("n",4)))) + end + return self + elseif t=="process" then + local temp=multi:newProcessor() + local objs=handle:getBlock("n",4) + for i=1,objs do + temp:newFromString(handle:getBlock("s",(handle:getBlock("n",4)))) + end + return temp + elseif t=="step" then -- GOOD + local item=self:newStep() + table.merge(item,data) + return item + elseif t=="tstep" then -- GOOD + local item=self:newTStep() + table.merge(item,data) + return item + elseif t=="tloop" then -- GOOD + local item=self:newTLoop() + table.merge(item,data) + return item + elseif t=="event" then -- GOOD + local item=self:newEvent(data.task) + table.merge(item,data) + return item + elseif t=="alarm" then -- GOOD + local item=self:newAlarm() + table.merge(item,data) + return item + elseif t=="watcher" then -- NEEDS TESTING + local item=self:newWatcher() + table.merge(item,data) + return item + elseif t=="updater" then -- GOOD + local item=self:newUpdater() + table.merge(item,data) + return item + elseif t=="loop" then -- GOOD + local item=self:newLoop() + table.merge(item,data) + return item + end +end +function multi:Important(varname) + table.insert(important,varname) +end +function multi:ToFile(path) + bin.new(self:ToString()):tofile(path) +end +function multi:fromFile(path) + self:newFromString(bin.load(path)) +end +function multi:SetStateFlag(opt) + -- +end +function multi:quickStateSave(b) + -- +end +function multi:saveState(path,opt) + -- +end +function multi:loadState(path) + -- +end +function multi:setDefualtStateFlag(opt) + -- +end +return multi diff --git a/Visual Novel/multi/integration/lanesManager.lua b/Visual Novel/multi/integration/lanesManager.lua new file mode 100644 index 0000000..2172f7c --- /dev/null +++ b/Visual Novel/multi/integration/lanesManager.lua @@ -0,0 +1,193 @@ +--[[ +MIT License + +Copyright (c) 2019 Ryan Ward + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] +package.path="?/init.lua;?.lua;"..package.path +function os.getOS() + if package.config:sub(1,1)=='\\' then + return 'windows' + else + return 'unix' + end +end +-- Step 1 get lanes +lanes=require("lanes").configure() +local multi = require("multi") -- get it all and have it on all lanes +multi.SystemThreads = {} +local thread = thread +multi.isMainThread=true +function multi:canSystemThread() + return true +end +function multi:getPlatform() + return "lanes" +end +-- Step 2 set up the Linda objects +local __GlobalLinda = lanes.linda() -- handles global stuff +local __SleepingLinda = lanes.linda() -- handles sleeping stuff +-- For convenience a GLOBAL table will be constructed to handle requests +local GLOBAL={} +setmetatable(GLOBAL,{ + __index=function(t,k) + return __GlobalLinda:get(k) + end, + __newindex=function(t,k,v) + __GlobalLinda:set(k,v) + end, +}) +-- Step 3 rewrite the thread methods to use Lindas +local THREAD={} +function THREAD.set(name,val) + __GlobalLinda:set(name,val) +end +function THREAD.get(name) + __GlobalLinda:get(name) +end +local function randomString(n) + local str = '' + local 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 + str = str..''..strings[math.random(1,#strings)] + end + return str +end +function THREAD.waitFor(name) + local function wait() + math.randomseed(os.time()) + __SleepingLinda:receive(.001,randomString(12)) + end + repeat wait() until __GlobalLinda:get(name) + return __GlobalLinda:get(name) +end +function THREAD.testFor(name,val,sym) + -- +end +function THREAD.getCores() + return THREAD.__CORES +end +function THREAD.getThreads() + return GLOBAL.__THREADS__ +end +if os.getOS()=="windows" then + THREAD.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) +else + THREAD.__CORES=tonumber(io.popen("nproc --all"):read("*n")) +end +function THREAD.kill() -- trigger the lane destruction + error("Thread was killed!") +end +function THREAD.getName() + return THREAD_NAME +end +function THREAD.getID() + return THREAD_ID +end +_G.THREAD_ID = 0 +--[[ Step 4 We need to get sleeping working to handle timing... We want idle wait, not busy wait +Idle wait keeps the CPU running better where busy wait wastes CPU cycles... Lanes does not have a sleep method +however, a linda recieve will in fact be a idle wait! So we use that and wrap it in a nice package]] +function THREAD.sleep(n) + math.randomseed(os.time()) + __SleepingLinda:receive(n,randomString(12)) +end +function THREAD.hold(n) + local function wait() + math.randomseed(os.time()) + __SleepingLinda:receive(.001,randomString(12)) + end + repeat wait() until n() +end +local rand = math.random(1,10000000) +-- Step 5 Basic Threads! +local threads = {} +local count = 1 +local started = false +local livingThreads = {} +function multi:newSystemThread(name,func,...) + multi.InitSystemThreadErrorHandler() + rand = math.random(1,10000000) + local c={} + local __self=c + c.name=name + c.Name = name + c.Id = count + livingThreads[count] = {true,name} + local THREAD_ID = count + count = count + 1 + c.Type="sthread" + c.creationTime = os.clock() + local THREAD_NAME=name + local function func2(...) + local multi = require("multi") + _G["THREAD_NAME"]=THREAD_NAME + _G["THREAD_ID"]=THREAD_ID + math.randomseed(rand) + func(...) + if _G.__Needs_Multi then + multi:mainloop() + end + THREAD.kill() + end + c.thread=lanes.gen("*", func2)(...) + function c:kill() + self.thread:cancel() + multi.print("Thread: '"..self.name.."' has been stopped!") + end + table.insert(multi.SystemThreads,c) + c.OnError = multi:newConnection() + GLOBAL["__THREADS__"]=livingThreads + return c +end +multi.OnSystemThreadDied = multi:newConnection() +function multi.InitSystemThreadErrorHandler() + if started==true then return end + started = true + multi:newThread("ThreadErrorHandler",function() + local threads = multi.SystemThreads + while true do + thread.sleep(.5) -- switching states often takes a huge hit on performance. half a second to tell me there is an error is good enough. + for i=#threads,1,-1 do + local v,err,t=threads[i].thread:join(.001) + if err then + if err:find("Thread was killed!") then + livingThreads[threads[i].Id] = {false,threads[i].Name} + multi.OnSystemThreadDied:Fire(threads[i].Id) + GLOBAL["__THREADS__"]=livingThreads + table.remove(threads,i) + else + threads[i].OnError:Fire(threads[i],err,"Error in systemThread: '"..threads[i].name.."' <"..err..">") + livingThreads[threads[i].Id] = {false,threads[i].Name} + multi.OnSystemThreadDied:Fire(threads[i].Id) + GLOBAL["__THREADS__"]=livingThreads + table.remove(threads,i) + end + end + end + end + end) +end +multi.print("Integrated Lanes!") +multi.integration={} -- for module creators +multi.integration.GLOBAL=GLOBAL +multi.integration.THREAD=THREAD +require("multi.integration.shared") +return {init=function() return GLOBAL, THREAD end} diff --git a/Visual Novel/multi/integration/loveManager.lua b/Visual Novel/multi/integration/loveManager.lua new file mode 100644 index 0000000..02f2f9e --- /dev/null +++ b/Visual Novel/multi/integration/loveManager.lua @@ -0,0 +1,428 @@ +--[[ +MIT License + +Copyright (c) 2019 Ryan Ward + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] +local multi = require("multi.compat.love2d") +function multi:canSystemThread() + return true +end +function multi:getPlatform() + return "love2d" +end +multi.integration={} +multi.integration.love2d={} +multi.integration.love2d.ThreadBase=[[ +tab={...} +__THREADID__=table.remove(tab,1) +__THREADNAME__=table.remove(tab,1) +THREAD_ID=table.remove(tab,1) +require("love.filesystem") +require("love.system") +require("love.timer") +require("love.image") +local multi = require("multi") +GLOBAL={} +isMainThread=false +setmetatable(GLOBAL,{ + __index=function(t,k) + __sync__() + return __proxy__[k] + end, + __newindex=function(t,k,v) + __sync__() + __proxy__[k]=v + if type(v)=="userdata" then + __MainChan__:push(v) + else + __MainChan__:push("SYNC "..type(v).." "..k.." "..resolveData(v)) + end + end, +}) +function __sync__() + local data=__mythread__:pop() + while data do + love.timer.sleep(.01) + if type(data)=="string" then + local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") + if name=="__DIEPLZ"..__THREADID__.."__" then + error("Thread: "..__THREADID__.." has been stopped!") + end + if cmd=="SYNC" then + __proxy__[name]=resolveType(tp,d) + end + else + __proxy__[name]=data + end + data=__mythread__:pop() + end +end +function 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 .. 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") + elseif type(val) == "function" then + tmp = tmp .. "loadDump([===["..dump(val).."]===])" + else + tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\"" + end + return tmp +end +function resolveType(tp,d) + if tp=="number" then + return tonumber(d) + elseif tp=="bool" then + return (d=="true") + elseif tp=="function" then + return loadDump("[==["..d.."]==]") + elseif tp=="table" then + return loadstring("return "..d)() + elseif tp=="nil" then + return nil + else + return d + end +end +function resolveData(v) + local data="" + if type(v)=="table" then + return ToStr(v) + elseif type(v)=="function" then + return dump(v) + elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then + return tostring(v) + end + return data +end +sThread={} +local function randomString(n) + local c=os.clock() + local a=0 + while os.clock()" + c.Id=count + count = count + 1 + livingThreads[count] = {true,name} + c.thread=love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func))) + c.thread:start(c.ID,c.name,THREAD_ID,...) + function c:kill() + multi.integration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__" + end + return c +end +function love.threaderror( thread, errorstr ) + multi.OnError:Fire(thread,errorstr) + multi.print("Error in systemThread: "..tostring(thread)..": "..errorstr) +end +local THREAD={} +function THREAD.set(name,val) + GLOBAL[name]=val +end +function THREAD.get(name) + return GLOBAL[name] +end +function THREAD.waitFor(name) + repeat multi:uManager() until GLOBAL[name] + return GLOBAL[name] +end +function THREAD.getCores() + return love.system.getProcessorCount() +end +function THREAD.sleep(n) + love.timer.sleep(n) +end +function THREAD.hold(n) + repeat multi:uManager() until n() +end +__channels__={} +multi.integration.GLOBAL=GLOBAL +multi.integration.THREAD=THREAD +updater=multi:newLoop(function(self) + local data=multi.integration.love2d.mainChannel:pop() + while data do + if type(data)=="string" then + local cmd,tp,name,d=data:match("(%S-) (%S-) (%S-) (.+)") + if cmd=="SYNC" then + __proxy__[name]=resolveType(tp,d) + for i=1,#__channels__ do + -- send data to other threads + if type(v)=="userdata" then + __channels__[i]:push(v) + else + __channels__[i]:push("SYNC "..tp.." "..name.." "..d) + end + end + elseif cmd=="NEWTHREAD" then + __channels__[#__channels__+1]=love.thread.getChannel(tp) + for k,v in pairs(__proxy__) do -- sync the global with each new thread + if type(v)=="userdata" then + __channels__[#__channels__]:push(v) + else + __channels__[#__channels__]:push("SYNC "..type(v).." "..k.." "..resolveData(v)) + end + end + end + else + __proxy__[name]=data + end + data=multi.integration.love2d.mainChannel:pop() + end +end) +multi.OnSystemThreadDied = multi:newConnection() +local started = false +function multi.InitSystemThreadErrorHandler() + if started==true then return end + started = true + multi:newThread("ThreadErrorHandler",function() + local threads = multi.SystemThreads + while true do + thread.sleep(.5) -- switching states often takes a huge hit on performance. half a second to tell me there is an error is good enough. + for i=#threads,1,-1 do + local v,err,t=threads[i].thread:join(.001) + if err then + if err:find("Thread was killed!") then + livingThreads[threads[i].Id] = {false,threads[i].Name} + multi.OnSystemThreadDied:Fire(threads[i].Id) + GLOBAL["__THREADS__"]=livingThreads + table.remove(threads,i) + else + threads[i].OnError:Fire(threads[i],err,"Error in systemThread: '"..threads[i].name.."' <"..err..">") + livingThreads[threads[i].Id] = {false,threads[i].Name} + multi.OnSystemThreadDied:Fire(threads[i].Id) + GLOBAL["__THREADS__"]=livingThreads + table.remove(threads,i) + end + end + end + end + end) +end +require("multi.integration.shared") +multi.print("Integrated Love2d!") +return { + init=function(t) + if t then + if t.threadNamespace then + multi.integration.THREADNAME=t.threadNamespace + multi.integration.love2d.ThreadBase:gsub("sThread",t.threadNamespace) + end + if t.globalNamespace then + multi.integration.GLOBALNAME=t.globalNamespace + multi.integration.love2d.ThreadBase:gsub("GLOBAL",t.globalNamespace) + end + end + return GLOBAL,THREAD + end +} diff --git a/Visual Novel/multi/integration/luvitManager.lua b/Visual Novel/multi/integration/luvitManager.lua new file mode 100644 index 0000000..862783d --- /dev/null +++ b/Visual Novel/multi/integration/luvitManager.lua @@ -0,0 +1,128 @@ +--[[ +MIT License + +Copyright (c) 2019 Ryan Ward + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] + +-- I DEMAND USAGE FOR LUVIT +-- Cannot use discordia without my multitasking library (Which I love more that the luvit platform... then again i'm partial :P) +package.path="?/init.lua;?.lua;"..package.path +local function _INIT(luvitThread,timer) + -- lots of this stuff should be able to stay the same + function os.getOS() + if package.config:sub(1,1)=='\\' then + return 'windows' + else + return 'unix' + end + end + -- Step 1 get setup threads on luvit... Sigh how do i even... + local multi = require("multi") + isMainThread=true + function multi:canSystemThread() + return true + end + function multi:getPlatform() + return "luvit" + end + local multi=multi + -- Step 2 set up the Global table... is this possible? + local GLOBAL={} + setmetatable(GLOBAL,{ + __index=function(t,k) + --print("No Global table when using luvit integration!") + return nil + end, + __newindex=function(t,k,v) + --print("No Global table when using luvit integration!") + end, + }) + local THREAD={} + function THREAD.set(name,val) + --print("No Global table when using luvit integration!") + end + function THREAD.get(name) + --print("No Global table when using luvit integration!") + end + local function randomString(n) + local str = '' + local 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 + str = str..''..strings[math.random(1,#strings)] + end + return str + end + function THREAD.waitFor(name) + --print("No Global table when using luvit integration!") + end + function THREAD.testFor(name,val,sym) + --print("No Global table when using luvit integration!") + end + function THREAD.getCores() + return THREAD.__CORES + end + if os.getOS()=="windows" then + THREAD.__CORES=tonumber(os.getenv("NUMBER_OF_PROCESSORS")) + else + THREAD.__CORES=tonumber(io.popen("nproc --all"):read("*n")) + end + function THREAD.kill() -- trigger the thread destruction + error("Thread was Killed!") + end + -- hmmm if im cleaver I can get this to work... but since data passing isn't going to be a thing its probably not important + function THREAD.sleep(n) + --print("No Global table when using luvit integration!") + end + function THREAD.hold(n) + --print("No Global table when using luvit integration!") + end + -- Step 5 Basic Threads! + local function entry(path,name,func,...) + local timer = require'timer' + local luvitThread = require'thread' + package.path=path + loadstring(func)(...) + end + function multi:newSystemThread(name,func,...) + local c={} + local __self=c + c.name=name + c.Type="sthread" + c.thread={} + c.func=string.dump(func) + function c:kill() + -- print("No Global table when using luvit integration!") + end + luvitThread.start(entry,package.path,name,c.func,...) + return c + end + multi.print("Integrated Luvit!") + multi.integration={} -- for module creators + multi.integration.GLOBAL=GLOBAL + multi.integration.THREAD=THREAD + require("multi.integration.shared") + -- Start the main mainloop... This allows you to process your multi objects, but the engine on the main thread will be limited to .001 or 1 millisecond sigh... + local interval = timer.setInterval(1, function () + multi:uManager() + end) + return multi +end +return {init=function(threadHandle,timerHandle) local multi = _INIT(threadHandle,timerHandle) return GLOBAL, THREAD end} diff --git a/Visual Novel/multi/integration/networkManager.lua b/Visual Novel/multi/integration/networkManager.lua new file mode 100644 index 0000000..7102b7d --- /dev/null +++ b/Visual Novel/multi/integration/networkManager.lua @@ -0,0 +1,556 @@ +--[[ +MIT License + +Copyright (c) 2019 Ryan Ward + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sub-license, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +]] +local multi = require("multi") +local net = require("net") +local bin = require("bin") +bin.setBitsInterface(infinabits) -- the bits interface does not work so well, another bug to fix + +-- Commands that the master and node will respect, max of 256 commands +local CMD_ERROR = 0x00 +local CMD_PING = 0x01 +local CMD_PONG = 0x02 +local CMD_QUEUE = 0x03 +local CMD_TASK = 0x04 +local CMD_INITNODE = 0x05 +local CMD_INITMASTER = 0x06 +local CMD_GLOBAL = 0x07 +local CMD_LOAD = 0x08 +local CMD_CALL = 0x09 +local CMD_REG = 0x0A +local CMD_CONSOLE = 0x0B + +local char = string.char +local byte = string.byte +-- Process to hold all of the networkManager's muilt objects + +-- Helper for piecing commands +local function pieceCommand(cmd,...) + local tab = {...} + table.insert(tab,1,cmd) + return table.concat(tab) +end + +-- Internal queue system for network queues +local Queue = {} +Queue.__index = Queue +function Queue:newQueue() + local c = {} + setmetatable(c,self) + return c +end +function Queue:push(data) + table.insert(self,data) +end +function Queue:raw_push(data) -- Internal usage only + table.insert(self,data) +end +function Queue:pop() + return table.remove(self,1) +end +function Queue:peek() + return self[1] +end +local queues = {} +multi.OnNetQueue = multi:newConnection() +multi.OnGUpdate = multi:newConnection() + +-- Managing the data that goes through the system +local function packData(data) + -- returns the data that was sterilized + local dat = bin.new() + dat:addBlock(#type(data),1) + dat:addBlock(type(data)) -- The type is first + if type(data)=="table" then + dat:addBlock(data,nil,"t") + elseif type(data) == "userdata" then + error("Cannot sterilize userdata!") + elseif type(data) == "number" then + dat:addBlock(data,nil,"d") + elseif type(data) == "string" then + dat:addBlock(#data,4) + dat:addBlock(data,nil,"s") + elseif type(data) == "boolean" then + dat:addBlock(data,1) + elseif type(data) == "function" then + dat:addBlock(data,nil,"f") + end + return dat.data +end +local function resolveData(data) + -- returns the data that was sterilized + local dat = bin.new(data) + local tlen = dat:getBlock("n",1) + local tp = dat:getBlock("s",tlen) + if tp=="table" then + return dat:getBlock("t") + elseif tp=="number" then + return dat:getBlock("d") + elseif tp=="string" then + local num = dat:getBlock("n",4) + return dat:getBlock("s",num) + elseif tp=="boolean" then + return dat:getBlock("b",1) + elseif tp=="function" then + return dat:getBlock("f") + end +end + +-- internal global system +local GLOBAL = {} +local PROXY = {} +setmetatable(GLOBAL,{ + __index = function(t,k) + return PROXY[k] + end, + __newindex = function(t,k,v) + local v = v + PROXY[k] = v + multi.OnGUpdate:Fire(k,packData(v)) + end +}) + +-- In case you are unable to use broadcasting this can be used to help connect to nodes +function multi:nodeManager(port) + if not port then + error("You must provide a port in order to host the node manager!") + end + local server = net:newTCPServer(port) + server.nodes = {} + server.timeouts = {} + server.OnNodeAdded = multi:newConnection() + server.OnNodeRemoved = multi:newConnection() + server.OnDataRecieved(function(server,data,cid,ip,port) + local cmd = data:sub(1,1) + if cmd == "R" then + multi:newThread("Node Client Manager",function(loop) + while true do + if server.timeouts[cid]==true then + server.OnNodeRemoved:Fire(server.nodes[cid]) + server.nodes[cid] = nil + server.timeouts[cid] = nil + thread.kill() + else + server.timeouts[cid] = true + server:send(cid,"ping") + end + thread.sleep(1) + end + end) + server.nodes[cid]=data:sub(2,-1) + server.OnNodeAdded:Fire(server.nodes[cid]) + elseif cmd == "G" then + server.OnNodeAdded(function(node) + server:send(cid,node) + end) + server.OnNodeRemoved(function(node) + server:send(cid,"R"..node:match("(.-)|")) + end) + for i,v in pairs(server.nodes) do + server:send(cid,v) + end + elseif cmd == "P" then + server.timeouts[cid] = nil + end + end) +end +-- The main driving force of the network manager: Nodes +function multi:newNode(settings) + multi:enableLoadDetection() + settings = settings or {} + -- Here we have to use the net library to broadcast our node across the network + math.randomseed(os.time()) + local name = settings.name or multi.randomString(8) + local node = {} + node.name = name + multi.OnError(function(i,error) + node.OnError:Fire(node,error,node.server) + end) + node.server = net:newUDPServer(0) -- hosts the node using the default port + _, node.port = node.server.udp:getsockname() + node.connections = net.ClientCache + node.queue = Queue:newQueue() + node.functions = bin.stream("RegisteredFunctions.dat",false) + node.hasFuncs = {} + node.OnError = multi:newConnection() + node.OnError(function(node,err,master) + multi.print("ERROR",err,node.name) + local temp = bin.new() + temp:addBlock(#node.name,2) + temp:addBlock(node.name) + temp:addBlock(#err,2) + temp:addBlock(err) + for i,v in pairs(node.connections) do + multi.print(i) + v[1]:send(v[2],char(CMD_ERROR)..temp.data,v[3]) + end + end) + if settings.managerDetails then + local c = net:newTCPClient(settings.managerDetails[1],settings.managerDetails[2]) + if not c then + multi.print("Cannot connect to the node manager! Ensuring broadcast is enabled!") settings.noBroadCast = false + else + c.OnDataRecieved(function(self,data) + if data == "ping" then + self:send("P") + end + end) + c:send("RNODE_"..name.."|"..net.getLocalIP().."|"..node.port) + end + end + if not settings.preload then + if node.functions:getSize()~=0 then + multi.print("We have function(s) to preload!") + local len = node.functions:getBlock("n",1) + local name,func + while len do + name = node.functions:getBlock("s",len) + len = node.functions:getBlock("n",2) + func = node.functions:getBlock("s",len) + len = node.functions:read(1) + _G[name]=resolveData(func) + node.hasFuncs[name]=true + if not len then break end + len = byte(len) + end + end + end + function node:pushTo(name,data) + node:sendTo(name,char(CMD_QUEUE)..packData(data)) + end + function node:peek() + return node.queue:peek() + end + function node:pop() + return node.queue:pop() + end + function node:getConsole() + local c = {} + local conn = node.connections + function c.print(...) + local data = char(CMD_CONSOLE)..packData({...}) + for i,v in pairs(conn) do + --print(i) + v[1]:send(v[2],data,v[3]) + end + end + -- function c:printTo() + + -- end + return c + end + node.loadRate=1 + -- Lets tell the network we are alive! + node.server.OnDataRecieved(function(server,data,cid,ip,port) + local cmd = byte(data:sub(1,1)) -- the first byte is the command + local dat = data:sub(2,-1) -- the data that you want to read + if cmd == CMD_PING then + server:send(ip,char(CMD_PONG),port) + elseif cmd == CMD_QUEUE then + node.queue:push(resolveData(dat)) + elseif cmd == CMD_REG then + if not settings.allowRemoteRegistering then + multi.print(ip..": has attempted to register a function when it is currently not allowed!") + return + end + local temp = bin.new(dat) + local len = temp:getBlock("n",1) + local name = temp:getBlock("s",len) + if node.hasFuncs[name] then + multi.print("Function already preloaded onto the node!") + return + end + len = temp:getBlock("n",2) + local func = temp:getBlock("s",len) + _G[name]=resolveData(func) + node.functions:addBlock(dat) + elseif cmd == CMD_CALL then + local temp = bin.new(dat) + local len = temp:getBlock("n",1) + local name = temp:getBlock("s",len) + len = temp:getBlock("n",4) + local args = temp:getBlock("s",len) + _G[name](unpack(resolveData(args))) + elseif cmd == CMD_TASK then + local holder = bin.new(dat) + local len = holder:getBlock("n",4) + local args = holder:getBlock("s",len) + local len2 = holder:getBlock("n",4) + local func = holder:getBlock("s",len2) + args = resolveData(args) + func = resolveData(func) + status, err = pcall(func,node,unpack(args)) + if not status then + node.OnError:Fire(node,err,server) + end + elseif cmd == CMD_INITNODE then + multi.print("Connected with another node!") + node.connections[dat]={server,ip,port} + multi.OnGUpdate(function(k,v) + server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port) + end)-- set this up + elseif cmd == CMD_INITMASTER then + multi.print("Connected to the master!",dat) + node.connections[dat]={server,ip,port} + multi.OnGUpdate(function(k,v) + server:send(ip,table.concat{char(CMD_GLOBAL),k,"|",v},port) + end)-- set this up + multi:newTLoop(function() + server:send(ip,char(CMD_LOAD)..node.name.."|"..multi:getLoad(),port) + end,node.loadRate) + server:send(ip,char(CMD_LOAD)..node.name.."|"..multi:getLoad(),port) + server:send(ip,char(CMD_INITNODE)..node.name,port) + elseif cmd == CMD_GLOBAL then + local k,v = dat:match("(.-)|(.+)") + PROXY[k]=resolveData(v) + end + end) + function node:sendTo(name,data) + local conn = node.connections[name] + conn[1]:send(conn[2],data,conn[3]) + end + if not settings.noBroadCast then + node.server:broadcast("NODE_"..name) + end + return node +end + +-- Masters +function multi:newMaster(settings) -- You will be able to have more than one master connecting to node(s) if that is what you want to do. I want you to be able to have the freedom to code any way that you want to code. + local master = {} + local settings = settings or {} + master.name = settings.name or multi.randomString(8) + local name = master.name + master.conn = multi:newConnection() + master.conn2 = multi:newConnection() + master.OnFirstNodeConnected = multi:newConnection() + master.OnNodeConnected = multi:newConnection() + master.OnError = multi:newConnection() + master.queue = Queue:newQueue() + master.connections = net.ClientCache -- Link to the client cache that is created on the net interface + master.loads = {} + master.timeouts = {} + master.trigger = multi:newFunction(function(self,node) + master.OnFirstNodeConnected:Fire(node) + self:Pause() + end) + if settings.managerDetails then + local client = net:newTCPClient(settings.managerDetails[1],settings.managerDetails[2]) + if not client then + multi.print("Warning: Cannot connect to the node manager! Ensuring broadcast listening is enabled!") settings.noBroadCast = false + else + client.OnDataRecieved(function(client,data) + local cmd = data:sub(1,1) + if cmd == "N" then + print(data) + local name,ip,port = data:match("(.-)|(.-)|(.+)") + local c = net:newUDPClient(ip,port) + net.OnCastedClientInfo:Fire(c,name,ip,port)master.connections[name]=c + elseif cmd == "R" then + local name = data:sub(2,-1) + master.connections[name]=nil + end + end) + client:send("G") -- init your connection as a master + end + end + function master:doToAll(func) + for i,v in pairs(master.connections) do + func(i,v) + end + end + function master:register(name,node,func) + if not node then + error("You must specify a node to execute a command on!") + end + local temp = bin.new() + local fData = packData(func) + temp:addBlock(CMD_REG,1) + temp:addBlock(#name,1) + temp:addBlock(name,#name) + temp:addBlock(#fData,2) + temp:addBlock(fData,#fData) + master:sendTo(node,temp.data) + end + function master:execute(name,node,...) + if not node then + error("You must specify a node to execute a command on!") + end + if not name then + error("You must specify a function name to call on the node!") + end + local args = packData{...} + local name = name + local node = node + local temp, len, data + temp = bin.new() + temp:addBlock(CMD_CALL,1) + temp:addBlock(#name,1) + temp:addBlock(name,#name) + temp:addBlock(#args,4) + temp:addBlock(args,#args) + master:sendTo(node,temp.data) + end + function master:pushTo(name,data) + master:sendTo(name,char(CMD_QUEUE)..packData(data)) + end + function master:peek() + return self.queue:peek() + end + function master:pop() + return self.queue:pop() + end + function master:newNetworkThread(tname,func,name,...) -- If name specified then it will be sent to the specified node! Otherwise the least worked node will get the job + local fData = packData(func) + local tab = {...} + local aData = "" + if #tab~=o then + aData = (packData{...}) + else + aData = (packData{"NO","ARGS"}) + end + local temp = bin.new() + temp:addBlock(#aData,4) + local len = temp.data + local temp2 = bin.new() + temp2:addBlock(#fData,4) + local len2 = temp2.data + if not name then + local name = self:getFreeNode() + if not name then + name = self:getRandomNode() + end + if name==nil then + multi:newEvent(function() return name~=nil end):OnEvent(function(evnt) + self:sendTo(name,char(CMD_TASK)..len..aData..len2..fData) + evnt:Destroy() + end):SetName("DelayedSendTask"):SetName("DelayedSendTask"):SetTime(8):OnTimedOut(function(self) + self:Destroy() + end) + else + self:sendTo(name,char(CMD_TASK)..len..aData..len2..fData) + end + else + local name = "NODE_"..name + self:sendTo(name,char(CMD_TASK)..len..aData..len2..fData) + end + end + function master:sendTo(name,data) + if name:sub(1,5)~="NODE_" then + name = "NODE_"..name + end + if self.connections[name]==nil then + multi:newEvent(function() return self.connections[name]~=nil end):OnEvent(function(evnt) + self.connections[name]:send(data) + evnt:Destroy() + end):SetName("DelayedSendTask"):SetTime(8):OnTimedOut(function(self) + self:Destroy() + end) + else + self.connections[name]:send(data) + end + end + function master:getFreeNode() + local count = 0 + local min = math.huge + local refO + for i,v in pairs(master.loads) do + if v= 15 then + c.idle = nil + end + thread.skip() + end + data = connSync:peek() + if data~= nil and data[1]=="INIT" then + connSync:pop() + c.idle = clock() + table.insert(syncs,data[2]) + for i=1,#syncs do + connSync:push{"SYNCA",syncs[i],data[2]} + end + end + data = connFire:peek() + if data~=nil and cleanUp[data[1]] then + local meh = data[1] + connFire:pop() -- lets remove dead thread stuff + multi:newAlarm(15):OnRing(function(a) + cleanUp[meh] = nil + end) + end + end + end) + GLOBAL[c.name]=c + return c +end + +function multi:SystemThreadedBenchmark(n) + n=n or 1 + local cores=multi.integration.THREAD.getCores() + local queue=multi:newSystemThreadedQueue("THREAD_BENCH_QUEUE"):init() + local sThread=multi.integration.THREAD + local GLOBAL=multi.integration.GLOBAL + local c = {} + for i=1,cores do + multi:newSystemThread("STHREAD_BENCH",function(n) + local multi = require("multi") + if multi:getPlatform()=="love2d" then + GLOBAL=_G.GLOBAL + sThread=_G.sThread + end -- we cannot have upvalues... in love2d globals, not locals must be used + queue=sThread.waitFor("THREAD_BENCH_QUEUE"):init() -- always wait for when looking for a variable at the start of the thread! + multi:benchMark(n):OnBench(function(self,count) + queue:push(count) + sThread.kill() + error("Thread was killed!") + end) + multi:mainloop() + end,n) + end + multi:newThread("THREAD_BENCH",function() + local count = 0 + local cc = 0 + while true do + thread.skip(1) + local dat = queue:pop() + if dat then + cc=cc+1 + count = count + dat + if cc == cores then + c.OnBench:Fire(count) + thread.kill() + end + end + end + end) + c.OnBench = multi:newConnection() + return c +end +function multi:newSystemThreadedConsole(name) + local c={} + c.name = name + local sThread=multi.integration.THREAD + local GLOBAL=multi.integration.GLOBAL + function c:init() + _G.__Needs_Multi = true + local multi = require("multi") + if multi:getPlatform()=="love2d" then + GLOBAL=_G.GLOBAL + sThread=_G.sThread + end + local cc={} + if multi.isMainThread then + if GLOBAL["__SYSTEM_CONSOLE__"] then + cc.stream = sThread.waitFor("__SYSTEM_CONSOLE__"):init() + else + cc.stream = multi:newSystemThreadedQueue("__SYSTEM_CONSOLE__"):init() + multi:newLoop(function() + local data = cc.stream:pop() + if data then + local dat = table.remove(data,1) + if dat=="w" then + io.write(unpack(data)) + elseif dat=="p" then + print(unpack(data)) + end + end + end):setName("ST.consoleSyncer") + end + else + cc.stream = sThread.waitFor("__SYSTEM_CONSOLE__"):init() + end + function cc:write(msg) + self.stream:push({"w",tostring(msg)}) + end + function cc:print(...) + local tab = {...} + for i=1,#tab do + tab[i]=tostring(tab[i]) + end + self.stream:push({"p",unpack(tab)}) + end + return cc + end + GLOBAL[c.name]=c + return c +end +-- NEEDS WORK +function multi:newSystemThreadedTable(name) + local c={} + c.name=name -- set the name this is important for identifying what is what + local sThread=multi.integration.THREAD + local GLOBAL=multi.integration.GLOBAL + function c:init() -- create an init function so we can mimic on both love2d and lanes + _G.__Needs_Multi = true + local multi = require("multi") + if multi:getPlatform()=="love2d" then + GLOBAL=_G.GLOBAL + sThread=_G.sThread + end + local cc={} + cc.tab={} + if multi.isMainThread then + if not GLOBAL[self.name.."_Tabled_Connection"] then + cc.conn = multi:newSystemThreadedConnection(self.name.."_Tabled_Connection"):init() + end + else + cc.conn = sThread.waitFor(self.name.."_Tabled_Connection"):init() + end + function cc:waitFor(name) + repeat multi:uManager() until tab[name]~=nil + return tab[name] + end + local link = cc + cc.conn(function(k,v) + link.tab[k]=v + end) + setmetatable(cc,{ + __index=function(t,k) + return t.tab[k] + end, + __newindex=function(t,k,v) + t.tab[k]=v + t.conn:Fire(k,v) + end + }) + return cc + end + GLOBAL[c.name]=c + return c +end +local jobqueuecount = 0 +local jqueues = {} +function multi:newSystemThreadedJobQueue(a,b) + jobqueuecount=jobqueuecount+1 + local GLOBAL=multi.integration.GLOBAL + local sThread=multi.integration.THREAD + local c = {} + c.numberofcores = 4 + c.idle = nil + c.name = "SYSTEM_THREADED_JOBQUEUE_"..jobqueuecount + -- This is done to keep backwards compatibility for older code + if type(a)=="string" and not(b) then + c.name = a + elseif type(a)=="number" and not (b) then + c.numberofcores = a + elseif type(a)=="string" and type(b)=="number" then + c.name = a + c.numberofcores = b + elseif type(a)=="number" and type(b)=="string" then + c.name = b + c.numberofcores = a + end + if jqueues[c.name] then + error("A job queue by the name: "..c.name.." already exists!") + end + jqueues[c.name] = true + c.isReady = false + c.jobnum=1 + c.OnJobCompleted = multi:newConnection() + local queueIN = self:newSystemThreadedQueue("QUEUE_IN_"..c.name):init() + local queueCC = self:newSystemThreadedQueue("QUEUE_CC_"..c.name):init() + local queueREG = self:newSystemThreadedQueue("QUEUE_REG_"..c.name):init() + local queueJD = self:newSystemThreadedQueue("QUEUE_JD_"..c.name):init() + local queueDA = self:newSystemThreadedQueue("QUEUE_DA_"..c.name):init() + c.OnReady = multi:newConnection() + function c:registerJob(name,func) + for i = 1, self.numberofcores do + queueREG:push({name,func}) + end + end + c.tempQueue = {} + function c:pushJob(name,...) + c.idle = os.clock() + if not self.isReady then + table.insert(c.tempQueue,{self.jobnum,name,...}) + self.jobnum=self.jobnum+1 + return self.jobnum-1 + else + queueIN:push{self.jobnum,name,...} + self.jobnum=self.jobnum+1 + return self.jobnum-1 + end + end + function c:doToAll(func) + local r = multi.randomString(12) + for i = 1, self.numberofcores do + queueDA:push{r,func} + end + end + for i=1,c.numberofcores do + multi:newSystemThread(c.name.." Worker Thread #"..i,function(name) + local multi = require("multi") + if love then -- lets make sure we don't reference up-values if using love2d + GLOBAL=_G.GLOBAL + sThread=_G.sThread + end + local CC = sThread.waitFor("QUEUE_CC_"..name):init() + CC:push("ready") + local FUNCS={} + local ids = {} + local JQI = sThread.waitFor("QUEUE_IN_"..name):init() + local JD = sThread.waitFor("QUEUE_JD_"..name):init() + local REG = sThread.waitFor("QUEUE_REG_"..name):init() + local DA = sThread.waitFor("QUEUE_DA_"..name):init() + local lastjob = os.clock() + multi:newLoop(function() + local job=JQI:pop() + local rd=REG:peek() + local da=DA:peek() + if rd then + if not FUNCS[rd[1]] then + FUNCS[rd[1]]=rd[2] + rd=nil + REG:pop() + end + end + if da then + if not ids[da[1]] then + local meh = da[1] + ids[da[1]]=true + da[2](multi) + da=nil + DA:pop() + multi:newAlarm(60):OnRing(function(a) + ids[meh] = nil + a:Destroy() + end) + end + end + if job then + lastjob = os.clock() + local ID=table.remove(job,1) -- return and remove + local _name=table.remove(job,1) -- return and remove + if FUNCS[_name] then + JD:push({ID,FUNCS[_name](unpack(job))}) + else -- making use of that new holding feature + JD:push({ID,FUNCS:waitFor(_name)(unpack(job))}) + end + end + end) + multi:newLoop(function() + if os.clock()-lastjob>1 then + sThread.sleep(.1) + end + end) + setmetatable(_G,{ + __index=function(t,k) + return FUNCS[k] + end + }) + if not love then + multi:mainloop() + end + end,c.name) + end + local clock = os.clock + multi:newThread("JQ-"..c.name.." Manager",function() + local _count = 0 + while _count= 15 then + c.idle = nil + end + thread.skip() + end + dat = queueJD:pop() + if dat then + c.idle = clock() + c.OnJobCompleted:Fire(unpack(dat)) + end + end + end) + return c +end +function multi:newSystemThreadedExecute(cmd) + local c={} + local GLOBAL=multi.integration.GLOBAL -- set up locals incase we are using lanes + local sThread=multi.integration.THREAD -- set up locals incase we are using lanes + local name="Execute_Thread"..multi.randomString(16) + c.name=name + GLOBAL[name.."CMD"]=cmd + multi:newSystemThread(name,function() + if love then -- lets make sure we don't reference upvalues if using love2d + GLOBAL=_G.GLOBAL + sThread=_G.sThread + name=__THREADNAME__ -- global data same as the name we used in this functions creation + end -- Lanes should take the local upvalues ^^^ + cmd=sThread.waitFor(name.."CMD") + local ret=os.execute(cmd) + GLOBAL[name.."R"]=ret + end) + c.OnCMDFinished=multi:newConnection() + c.looper=multi:newLoop(function(self) + local ret=GLOBAL[self.link.name.."R"] + if ret then + self.link.OnCMDFinished:Fire(ret) + self:Destroy() + end + end) + c.looper.link=c + return c +end diff --git a/Visual Novel/net/init.lua b/Visual Novel/net/init.lua new file mode 100644 index 0000000..5932311 --- /dev/null +++ b/Visual Novel/net/init.lua @@ -0,0 +1,890 @@ +--[[ + UPCOMMING ADDITIONS + AUDP - advance udp. Ensures packets arrive and handles late packets. + P2P - peer to peer (Server to set up initial connection) + Relay - offput server load (locally) + Threading - Simple threading ~~(UDP/AUDP Only)~~ Thanks to an updated multi library we can thread with ease + Priority handling +]] +--[[ + TODO: Finish stuff for Priority handling +]] +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 string.trim(s) + local from = s:match"^%s*()" + return from > #s and "" or s:match(".*%S", from) +end +local guid = {} +local char = {} +for i = 48,57 do + char[#char+1]=string.char(i) +end +for i = 65,90 do + char[#char+1]=string.char(i) +end +for i = 97,122 do + char[#char+1]=string.char(i) +end +local isHyphen = {[9]=1,[14]=1,[19]=1,[24]=1} +math.randomseed(os.time()) +local multi = require("multi") +local socket=require("socket") +local http=require("socket.http") +local mime=require("mime") +--ssl=require("ssl") +--https=require("ssl.https") +local net={} +net.Version={3,0,0} -- This will probably stay this version for quite a while... The modules on the otherhand will be more inconsistant +net._VERSION="3.0.0" +net.ClientCache = {} +net.OnServerCreated=multi:newConnection() +net.OnClientCreated=multi:newConnection() +net.loadedModules={} +net.OnCastedClientInfo=multi:newConnection() +net.autoInit=true +net.ConnectionDriver = {} +net.BroadcastDriver = {} +net.generateGUID = function(t) + local pass = {} + local a=0 + local x="" + for z = 1,36 do + if isHyphen[z] then + x='-' + else + a = math.random(1,#char) + x = char[a] + end + table.insert(pass, x) + if t == z then break end + end + z = nil + return tostring(table.concat(pass)) +end +function net.normalize(input) + local enc=mime.b64(input) + return enc +end +function net.denormalize(input) + local unenc=mime.unb64(input) + return unenc +end +function net.getLocalIP() + local someRandomIP = "192.168.1.122" + local someRandomPort = "3102" + local mySocket = socket.udp() + mySocket:setpeername(someRandomIP,someRandomPort) + local dat = (mySocket:getsockname()) + mySocket:close() + return dat +end +function net.getExternalIP() + local data=http.request("http://whatismyip.host") + return data:match("(%d+.%d+.%d+.%d+)") +end +function net:registerModule(mod,version) + if net[mod] then + error("Module by the name: "..mod.." has already been registered! Remember some modules are internal and use certain names!") + end + table.insert(self.loadedModules,mod) + net[mod]={} + if version then + net[mod].Version=version + net[mod]._VERSION=version[1].."."..version[2].."."..version[3] + else + net[mod].Version={1,0,0} + net[mod]._VERSION={1,0,0} + end + return {Version=version,_VERSION=version[1].."."..version[2].."."..version[3]} +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 +net:registerModule("net",net.Version) +-- Client broadcast +function net:newCastedClient(name) -- connects to the broadcasted server + local listen = socket.udp() -- make a new socket + listen:setsockname(net.getLocalIP(), 11111) + listen:settimeout(0) + local timer=multi:newTimer() + while true do + local data, ip, port = listen:receivefrom() + if timer:Get()>3 then + error("Timeout! Server by the name: "..name.." has not been found!") + end + if data then + print("found!",data) + local n,tp,ip,port=data:match("(%S-)|(%S-)|(%S-):(%d+)") + if n:match(name) then + print("Found Server!",n,tp,ip,port) + if tp=="tcp" then + return net:newTCPClient(ip,tonumber(port)) + else + return net:newClient(ip,tonumber(port)) + end + end + end + end +end +function net:newCastedClients(name) -- connects to the broadcasted server + local listen = socket.udp() -- make a new socket + listen:setsockname(net.getLocalIP(), 11111) + listen:settimeout(0) + multi:newTLoop(function(self) + local data, ip, port = listen:receivefrom() + if data then + local n,tp,ip,port=data:match("(%S-)|(%S-)|(%S-):(%d+)") + if n:match(name) and not net.ClientCache[n] then + local capture = n:match(name) + local client = {} + if tp=="tcp" then + client=net:newTCPClient(ip,tonumber(port)) + else + client=net:newUDPClient(ip,tonumber(port)) + end + net.ClientCache[n]=client + net.OnCastedClientInfo:Fire(client,n,ip,port) + end + end + end,.1):setName("net.castedTask") +end +-- UDP Stuff +function net:newUDPServer(port,servercode,nonluaServer) + local c={} + c.udp=assert(socket.udp()) + c.udp:settimeout(0) + c.udp:setsockname("*", port) + c.ips={} + c.Type="udp" + if port == 0 then + _, c.port = c.udp:getsockname() + end + c.ids={} + c.servercode=servercode + c.bannedIPs={} + c.bannedCIDs={} + c.autoNormalization=false + 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 + c.broad=socket.udp() + c.hostip=net.getLocalIP() + function c:broadcast(name) + table.insert(net.BroadcastDriver,function(loop,dt) + self.broad:setoption('broadcast',true) + self.broad:sendto(name.."|"..self.Type.."|"..self.hostip..":"..self.port, "255.255.255.255", 11111) + self.broad:setoption('broadcast',false) + end) + end + function c:send(ip,data,port,cid) + if self.autoNormalization then + data=net.normalize(data) + end + 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 ignore data from a banned client!") + return + end + if data then + if self.autoNormalization then + data=net.denormalize(data) + end + 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 + local hook=(data:sub(11,-1)):match("!(.-)!") + self.OnDataRecieved:getConnection(hook):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 + self.OnClientConnected:Fire(self,cid,ip,port) + 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.OnClientClosed=multi:newConnection() + c.OnClientConnected=multi:newConnection() + c.connectiontest=multi:newAlarm(30):setName("net.pingOutTask") + c.connectiontest.link=c + c.connectiontest:OnRing(function(alarm) + alarm.link:sendAll("ping") + alarm:Reset() + end) + table.insert(net.ConnectionDriver,c) + net.OnServerCreated:Fire(c) + return c +end +local pingManager = {} +function net:newUDPClient(host,port,servercode,nonluaServer) + local c={} + c.ip=assert(socket.dns.toip(host)) + c.udp=assert(socket.udp()) + c.udp:settimeout(0) + c.udp:setpeername(c.ip, port) + c.cid="NIL" + c.lastPing=0 + c.Type="udp" + c.servercode=servercode + c.autoReconnect=true + c.autoNormalization=false + function c:pollPing(n) + return not((os.clock()-self.lastPing)<(n or 60)) + end + function c:send(data) + if self.autoNormalization then + data=net.normalize(data) + end + self.udp:send("C!"..self.cid..data) + end + function c:sendRaw(data) + if self.autoNormalization then + data=net.normalize(data) + end + 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 self.autoNormalization then + data=net.denormalize(data) + end + 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 + local hook=data:match("!(.-)!") + self.OnDataRecieved:getConnection(hook):Fire(self,data) + end + end + end + function c:reconnect() + if not nonluaServer then + self.cid="NIL" + c.udp:send("I!") + end + self.pingEvent:Resume() + self.OnConnectionRegained:Fire(self) + 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.OnClientDisconnected:Fire(self,"closed") + self.link:reconnect() + else + self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout!") + self.link.OnClientDisconnected:Fire(self,"closed") + end + self:Pause() + end):setName("net.pingInTask") + c.pingEvent.link=c + c.OnPingRecieved=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + c.OnServerNotAvailable=multi:newConnection() + c.OnClientReady=multi:newConnection() + c.OnClientDisconnected=multi:newConnection() + c.OnConnectionRegained=multi:newConnection() + c.notConnected=multi:newFunction(function(self) + multi:newAlarm(3):OnRing(function(alarm) + if self.link:IDAssigned()==false then + self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server") + end + alarm:Destroy() + end):setName("net.clientTimeout") + end) + c.notConnected.link=c + if not nonluaServer then + c.udp:send("I!") + end + table.insert(net.ConnectionDriver,c) + multi.nextStep(function() c.notConnected() end) + net.OnClientCreated:Fire(c) + return c +end +--TCP Stuff +function net:newTCPClientObject(fd) + local c = {} + local client + c.Type="tcp-ClientObj" + c.rMode="*l" + c.sMode="*l" + function c:packMsg(data) + local temp = bin.new() + temp:addBlock(#data,self.numspace,"n") + temp:addBlock(data) + return temp:getData() + end + function c:enableBinaryMode() + self.rMode = "b" + self.sMode = "b" + end + if fd then + client=socket.tcp() + client:setfd(fd) + _,port = client:getsockname() + c.handle = client + else + error("You need to enter a fd in order to be able to create a tcp client object like this!") + end + 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:send(data) + if self.autoNormalization then + data=net.normalize(data) + end + if self.sMode=="*l" then + self.handle:send(data.."\n") + elseif self.sMode=="b" then + self.handle:send(self:packMsg(data)) + else + self.handle:send(data) + end + end + multi:newThread("ServerClientHandler",function() + while true do + thread.skip(1) + local data, err, dat, len + if self.rMode == "b" then + thread.hold(function() + dat = client:receive(self.numspace) + return dat + end) + len = bin.new(dat):getBlock("n",self.numspace) + data, err = client:receive(len) + else + data, err = client:receive(self.rMode) + end + if err=="closed" then + for i=1,#self.ips do + if self.ips[i]==client then + table.remove(self.ips,i) + end + end + self.OnClientClosed:Fire(self,"Client Closed Connection!",client,client,ip) + self.links[client]=nil -- lets clean up + self:Destroy() + end + if data then + if self.autoNormalization then + data=net.denormalize(data) + end + if net.inList(self.bannedIPs,ip) then + print("We will ingore data from a banned client!") + return + end + local hook=data:match("!(.-)!") + self.OnDataRecieved:getConnection(hook):Fire(self,data,client,client,ip,self) + 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.OnClientsModulesList:Fire(list,client,client,ip) + end + end + end + end) + c.OnClientsModulesList=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + c.OnClientClosed=multi:newConnection() + c.OnClientConnected=multi:newConnection() + return c +end +function net:newTCPServer(port) + local c={} + local port = port or 0 + c.tcp=assert(socket.bind("*", port)) + c.tcp:settimeout(0) + c.ip,c.port=c.tcp:getsockname() + c.ips={} + if port == 0 then + _, c.port = c.tcp:getsockname() + end + c.ids={} + c.bannedIPs={} + c.Type="tcp" + c.rMode="*l" + c.sMode="*l" + c.updaterRate=1 + c.autoNormalization=false + c.updates={} + c.links={} + c.numspace = 4 + c.broad=socket.udp() + c.hostip=net.getLocalIP() + function c:packMsg(data) + local temp = bin.new() + temp:addBlock(#data,self.numspace,"n") + temp:addBlock(data) + return temp:getData() + end + function c:enableBinaryMode() + self.rMode = "b" + self.sMode = "b" + end + function c:broadcast(name) + table.insert(net.BroadcastDriver,function(loop,dt) + self.broad:setoption('broadcast',true) + self.broad:sendto(name.."|"..self.Type.."|"..self.hostip..":"..self.port, "255.255.255.255", 11111) + self.broad:setoption('broadcast',false) + end) + end + 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.autoNormalization then + data=net.normalize(data) + end + if self.sMode=="*l" then + handle:send(data.."\n") + elseif self.sMode=="b" then + handle:send(self:packMsg(data)) + else + handle:send(data) + end + end + function c:sendAllData(handle,data) + if self.autoNormalization then + data=net.normalize(data) + end + handle:send(data) + 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:getUpdater(cid) + return self.updates[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):setName("net.tcpClientObj") + -- self.updates[client]=updater + self.OnClientConnected:Fire(self,client,client,ip) + --updater:OnUpdate(function(self) + multi:newThread("ServerClientHandler",function() + while true do + thread.skip(1) + local data, err, dat, len + if self.rMode == "b" then + thread.hold(function() + dat = client:receive(self.numspace) + return dat + end) + len = bin.new(dat):getBlock("n",self.numspace) + data, err = client:receive(len) + else + data, err = client:receive(self.rMode) + end + if err=="closed" then + for i=1,#self.ips do + if self.ips[i]==client then + table.remove(self.ips,i) + end + end + self.OnClientClosed:Fire(self,"Client Closed Connection!",client,client,ip) + self.links[client]=nil -- lets clean up + self:Destroy() + thread.kill() + end + if data then + if self.autoNormalization then + data=net.denormalize(data) + end + if net.inList(self.bannedIPs,ip) then + print("We will ingore data from a banned client!") + return + end + local hook=data:match("!(.-)!") + self.OnDataRecieved:getConnection(hook):Fire(self,data,client,client,ip,self) + 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.OnClientsModulesList:Fire(list,client,client,ip) + end + end + end + end) + -- updater:SetSkip(self.updaterRate) + -- updater.client=client + -- updater.Link=self + -- function updater:setReceiveMode(mode) + -- self.rMode=mode + -- end + -- self.links[client]=updater + end + end + c.OnClientsModulesList=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + c.OnClientClosed=multi:newConnection() + c.OnClientConnected=multi:newConnection() + table.insert(net.ConnectionDriver,c) + net.OnServerCreated:Fire(c) + return c +end +function net:newTCPClient(host,port) + local c={} + c.ip=assert(socket.dns.toip(host)) + 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" + c.autoNormalization=false + c.numspace = 4 + function c:enableBinaryMode() + self.rMode = "b" + self.sMode = "b" + end + function c:setReceiveMode(mode) + self.rMode=mode + end + function c:setSendMode(mode) + self.sMode=mode + end + function c:packMsg(data) + local temp = bin.new() + temp:addBlock(#data,self.numspace) + temp:addBlock(data) + return temp:getData() + end + function c:send(data) + if self.autoNormalization then + data=net.normalize(data) + end + if self.sMode=="*l" then + ind,err=self.tcp:send(data.."\n") + elseif self.sMode=="b" then + ind,err=self.tcp:send(self:packMsg(data)) + else + ind,err=self.tcp:send(data) + end + if err=="closed" then + self.OnClientDisconnected:Fire(self,err) + elseif err=="timeout" then + self.OnClientDisconnected:Fire(self,err) + elseif err then + print(err) + end + end + function c:sendRaw(data) + if self.autoNormalization then + data=net.normalize(data) + end + 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() + if not self.tcp then return end + local data,err,dat + if self.rMode == "b" then + thread.hold(function() + dat = self.tcp:receive(self.numspace) + return dat + end) + len = bin.new(dat):getBlock("n",self.numspace) + data, err = self.tcp:receive(len) + else + data, err = self.tcp:receive() + end + if err=="closed" then + self.OnClientDisconnected:Fire(self,err) + elseif err=="timeout" then + self.OnClientDisconnected:Fire(self,err) + elseif err then + print(err) + end + if data then + if self.autoNormalization then + data=net.denormalize(data) + end + local hook=data:match("!(.-)!") + self.OnDataRecieved:getConnection(hook):Fire(self,data) + end + end + function c:reconnect() + multi:newFunction(function(func) + self.tcp=socket.connect(self.ip,self.port) + if self.tcp==nil then + print("Can't connect to the server: No response from server!") + multi:newAlarm(3):OnRing(function(alarm) + self:reconnect() + alarm:Destroy() + return + end):setName("net.timeoutTask") + end + self.OnConnectionRegained:Fire(self) + self.tcp:settimeout(0) + --self.tcp:setoption('tcp-nodelay', true) + self.tcp:setoption('keepalive', true) + end) + end + c.event=multi:newEvent(function(event) + return event.link:IDAssigned() + end):OnEvent(function(event) + event.link.OnClientReady:Fire(event.link) + event:Destroy() + end) + c.event:setName("net.handshakeTask") + c.event.link=c + c.OnClientReady=multi:newConnection() + c.OnClientDisconnected=multi:newConnection() + c.OnDataRecieved=multi:newConnection() + c.OnConnectionRegained=multi:newConnection() + table.insert(net.ConnectionDriver,c) + net.OnClientCreated:Fire(c) + return c +end +net.timer = multi:newTimer():Start() +multi:newThread("ClientServerHandler",function() + while true do + thread.skip() + for i=1,#net.ConnectionDriver do + thread.skip() + net.ConnectionDriver[i]:update() + end + if net.timer:Get()>=1 then + for i=1,#net.BroadcastDriver do + net.BroadcastDriver[i]() + end + net.timer:Reset() + end + end +end) +return net diff --git a/Visual Novel/parseManager/audio.lua b/Visual Novel/parseManager/audio.lua new file mode 100644 index 0000000..44ff064 --- /dev/null +++ b/Visual Novel/parseManager/audio.lua @@ -0,0 +1,29 @@ +require("proAudioRt") +proAudio.create() +local audio = {} +audio.__index = audio +function audio:new(path) + local c = {} + c.path = path + c.handle = proAudio.sampleFromFile(path) + setmetatable(c,audio) + return c +end +function audio:play(volume,loop) + local volume = volume or 1 + if loop then + proAudio.soundLoop(self.handle, volume, volume, 0, 1) + else + proAudio.soundPlay(self.handle, volume, volume, 0, 1) + end +end +function audio:stop() + if not self then proAudio.soundStop() return end + proAudio.soundStop(self.handle) +end +function audio:setVolume(volume) + proAudio.soundUpdate(self.handle,volume,volume) +end +function parseManager:audio() + return audio +end diff --git a/Visual Novel/parseManager/filesystem.lua b/Visual Novel/parseManager/filesystem.lua new file mode 100644 index 0000000..3a7b4b1 --- /dev/null +++ b/Visual Novel/parseManager/filesystem.lua @@ -0,0 +1,3 @@ +function parseManager:filesystem() + return bin +end diff --git a/Visual Novel/parseManager/init.lua b/Visual Novel/parseManager/init.lua new file mode 100644 index 0000000..37ca0aa --- /dev/null +++ b/Visual Novel/parseManager/init.lua @@ -0,0 +1,1438 @@ +local noprint +local bin = require("bin") +parseManager={} +parseManager.VERSION = 6 +parseManager.__index=parseManager +parseManager.chunks={} +parseManager.stats={warnings = true} +parseManager.stack={} +parseManager.cFuncs={} +parseManager.mainENV={_VERSION = parseManager.VERSION} +parseManager.__INTERNAL = {} +parseManager.currentENV=parseManager.mainENV +parseManager.entry="START" +parseManager.methods={} +parseManager.lastCall=nil +parseManager.currentHandle=nil +parseManager.currentHandleName=nil +parseManager.state = {} +parseManager.active = true +parseManager.usings = {} +function parseManager.print(...) + if not noprint then + print(...) + end +end +function readonlytable(tab) + return setmetatable({},{ + __index=tab, + __newindex=function() + error("Attempt to modify read-only table!") + end, + __metatable=false + }) +end +function parseManager:debug(...) + if self.stats.debugging then + parseManager.print("",...) + end +end +function parseManager:newENV() + local env={} + function env:getParent() + return getmetatable(self).__index + end + setmetatable(env,{__index=self.currentENV}) + return env +end +function parseManager:setENV(env) + self.currentENV=env +end +function parseManager:defualtENV() + self:setENV(self.mainENV) +end +function parseManager:exposeNamespace(name,ref) + self.mainENV[name]=ref +end +function factorial(n) + if (n == 0) then + return 1 + else + return n * factorial(n - 1) + end +end +function parseManager:ENABLE(fn) + if fn == "hostmsg" then + noparseManager.print = false + end + self.stats[string.lower(fn)]=true +end +function parseManager:DISABLE(fn) + if fn == "hostmsg" then + noprint = true + end + self.stats[string.lower(fn)]=false +end +function parseManager:USING(fn,name) + local m = require("parseManager."..fn) + self.usings[#self.usings]={fn,name} + if not m then + self:pushError(fn.." was not found as an import that can be used!") + else + local ret = self[fn](self) + if ret then + self.mainENV[name or fn]=ret + end + end +end +--[[ +self.VERSION = 5 +self.chunks={} +self.stats={warnings = true} +self.stack={} +self.cFuncs={} +self.mainENV={_VERSION = self.VERSION} +self.__INTERNAL = {} +self.currentENV=self.mainENV +self.entry="START" +self.methods={} +self.lastCall=nil +self.currentHandle=nil +self.currentHandleName=nil +self.state = {} +self.active = true +self.usings = {} +]] +function parseManager:compileToFile(path,topath) + local file = bin.new() + local state = self:load(path) + file:addBlock(state.VERSION) + file:addBlock(state.chunks) + file:addBlock(state.stats) + -- file:addBlock(state.cFuncs) + -- file:addBlock(state.__INTERNAL) + file:addBlock(#state.entry,1) + file:addBlock(state.entry) + file:addBlock(state.usings) + file:tofile(topath) + return state +end +function parseManager:loadCompiled(path) + local file = bin.load(path) + local c = {} + setmetatable(c,parseManager) + c.VERSION = file:getBlock("n",4) + c.chunks = file:getBlock("t") + c.stats = file:getBlock("t") + -- c.cFuncs = file:getBlock("t") + -- c.__INTERNAL = file:getBlock("t") + local size = file:getBlock("n",1) + c.entry = file:getBlock("s",size) + c.usings = file:getBlock("t") + return c +end +function parseManager:load(path,c,noload) + local c = c + if not c then + c = {} + setmetatable(c,parseManager) + end + if not c.path then + c.path = path + end + local file + if type(path)=="table" then + if path.Type=="bin" then + file = path + else + error("Currently unsupported path type!") + end + elseif type(path)=="string" then + if bin.fileExists(path) then + file=bin.load(path) + else + error("File: "..path.." does not exist!") + end + end + -- process the data + file.data=file.data:gsub("/%*.-%*/","") + file.data=file.data:gsub('%b""',function(a) a=a:gsub("//","\2") return a end) + file.data=file.data:gsub("%b''",function(a) a=a:gsub("//","\2") return a end) + file.data=file.data:gsub("//.-\n","\n") + file.data=file.data:gsub('%b""',function(a) a=a:gsub(";","\1") return a end) + file.data=file.data:gsub("%b''",function(a) a=a:gsub(";","\1") return a end) + file.data=file.data:gsub(";\n","\n") + file.data=file.data:gsub(";\r","\r") + file.data=file.data:gsub(";","\n") + file.data=file.data:gsub("\r\n","\n") + file.data=file.data:gsub("\n\n","\n") + file.data=file.data:gsub("\1",";") + file.data=file.data:gsub("\2","//") + file.data=file.data:gsub("\t","") + file:trim() + local header = file:match("(.-)%[") + for fn in header:gmatch("ENABLE (.-)\n") do + self:debug("E",fn) + c:ENABLE(fn) + end + for fn in header:gmatch("LOADFILE (.-)\n") do + self:debug("L",fn) + c:load(fn,c) + end + for fn in header:gmatch("DISABLE (.-)\n") do + self:debug("D",fn) + c:DISABLE(fn) + end + for fn in header:gmatch("ENTRY (.-)\n") do + self:debug("E",fn) + c.entry=fn + end + for fn in header:gmatch("USING (.-)\n") do + self:debug("U",fn) + if fn:find("as") then + local use,name = fn:match("(.-) as (.+)") + c:USING(use,name) + else + c:USING(fn) + end + end + for fn in header:gmatch("VERSION (.-)\n") do + self:debug("V",fn) + local num = tonumber(fn) + local int = tonumber(c.VERSION) + if not num then + c:pushWarning("VERSION: "..fn.." is not valid! Assuming "..c.VERSION) + else + if num>int then + c:pushWarning("This script was written for a later version! Some features may not work properly!") + end + end + end + for name,data in file:gmatch("%[(.-)[:.-]?%].-{(.-)}") do + local ctype="BLOCK" + if name:find(":") then + ctype=name:match(":(.+)") + name=name:match("(.-):") + end + c.chunks[name]={} + c.chunks[name].type=ctype + c.chunks[name].pos=1 + c.chunks[name].labels={} + c.chunks[name].path=path + c.chunks[name].name=name + parseManager.currentHandleName=name + parseManager.currentHandle=c + c:compile(name,ctype,data) + c.runtime = true + end + --c.chunks=readonlytable(c.chunks) + c.mainENV["False"]=false + c.mainENV["True"]=true + return c +end +function push(s,n) + table.insert(s,n) +end +function pop(s) + return table.remove(s) +end +function peek(s) + return s[#s] +end +function parseManager:extractState() + return {name=self.currentChunk.name,pos = self.currentChunk.pos,variables = self.mainENV,cc = self.currentENV} +end +function parseManager:injectState(tbl) + self.chunks[tbl.name].pos=tbl.pos + self.currentChunk=self.chunks[tbl.name] + self.mainENV = tbl.variables + self.currentENV = tbl.cc +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 + elseif c == "(" then + state = 1 + elem = elem .. '(' + 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 = 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 +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 +local universalSymbol = {} +local function getSymbol(s) + if not universalSymbol[(s or "$")] then + universalSymbol[(s or "$")] = 0 + end + local char=(s or "$")..string.char((universalSymbol[(s or "$")]%26)+65) + universalSymbol[(s or "$")] = universalSymbol[(s or "$")] + 1 + return char +end +local function concat(tab,sep) + if not tab then return "" end + for g=1,#tab do + if type(tab[g])=="table" then + tab[g]="<"..(tab[g][1] or "!NEW!").."["..(tab[g][2] or "").."]>" + end + if type(tab[g])=="string" then + tab[g]=tab[g]:gsub("\1","") + end + tab[g]=tostring(tab[g]) + end + return table.concat(tab,sep) +end +function parseManager:dump() + local bytecode = deepcopy(self.chunks) + local str="" + for i,v in pairs(bytecode) do + str=str.."BLOCK: ["..i.."]\n" + for k=1,#v do + if type(v[k].Func)=="table" and v[k].Func.IsALookup==true then + if v[k].Type=="fwor" then + str=str.."\t"..v[k].Func[2].." "..concat(v[k].args,", ").."\n" + elseif v[k].Type=="fwr" then + str=str.."\t"..concat(v[k].vars,", ").." <- "..v[k].Func[2].." "..concat(v[k].args,", ").."\n" + end + elseif v[k].Type=="fwor" then + str=str.."\t"..v[k].Func.." "..concat(v[k].args,", ").."\n" + elseif v[k].Type=="funcblock" then + str=str.."\tFUNCTION: args("..concat(v[k].args,", ")..")\n" + elseif v[k].Type=="return" then + str=str.."\tRETURN: rets("..concat(v[k].RETArgs,", ")..")\n" + elseif v[k].Type=="label" then + str=str.."\t::"..v[k].label.."::\n" + elseif v[k].Type=="fwr" then + str=str.."\t"..concat(v[k].vars,", ").." <- "..v[k].Func.." "..concat(v[k].args,", ").."\n" + elseif v[k].Type=="choice" then + local opt={} + local met={} + local args={} + for i=1,#v[k] do + opt[#opt+1]=v[k][i][1] + met[#met+1]=v[k][i][2].Func + args[#args+1]=concat(v[k][i][2].args," ") + end + str=str.."\tCHOICE["..v[k].prompt.."]$C<"..concat(opt,", ")..">$F<"..concat(met,", ")..">$A<"..concat(args,", ")..">\n" + elseif v[k].Type=="text" then + str=str.."\tDISP_MSG \""..v[k].text.."\"\n" + elseif v[k].Type=="assign" then + str=str.."\t"..concat(v[k].vars,", ").." <- "..concat(v[k].vals,", ").."\n" + elseif v[k].Type=="toggle" then + str = str.."\t"..v[k].Flags.." "..v[k].Target.."\n" + else + str=str.."\tUnknown Code!: "..tostring(v[k].data).."\n" + end + end + end + return str +end +function table.print(tbl, indent) + if type(tbl)~="table" then return end + if not indent then indent = 0 end + for k, v in pairs(tbl) do + formatting = string.rep(' ', indent) .. k .. ': ' + if type(v) == 'table' then + parseManager.print(formatting) + table.print(v, indent+1) + else + parseManager.print(formatting .. tostring(v)) + end + end +end +function parseManager:pushError(err,sym) + local run = "Compile Time Error! " + if self.runtime then + run = "Run Time Error! " + end + if not self.currentChunk then parseManager.print("ERROR compiling: ",err,sym) os.exit() end + local lines = bin.load(self.currentChunk.path):lines() + local chunk = self.currentChunk[self.currentChunk.pos-1] + for i=1,#lines do + if sym then + if lines[i]:find(sym) then + parseManager.print(run..err.." <"..sym.."> At line: "..i.." "..(lines[i]:gsub("^\t+",""))) + break + end + elseif chunk.Type=="fwor" or chunk.Type=="fwr" then + if lines[i]:match(chunk.Func.."%(") then + parseManager.print(run..err.." At line: "..i.." "..(lines[i]:gsub("^\t+","")).." ("..tostring(sym)..")") + break + end + else + parseManager.print(run..err.." Line: ?") + break + end + end + os.exit() +end +function parseManager:pushWarning(warn) + if not self.stats["warnings"] then return end + parseManager.print("WARNING: "..warn) +end +local function pieceList(list,self,name) + if #list==0 then + return {} + end + local list=parseManager.split(list) + local L={} + for i=1,#list do + if list[i]:match("[%w_]-%[.-%]") and list[i]:sub(1,1)~='"' then + local dict,sym=list[i]:match("([%w_]-)%[(.-)%]") + if tonumber(sym) then + L[#L+1]={"\1"..dict,tonumber(sym),IsALookup=true} + elseif sym:sub(1,1)=="\"" and sym:sub(-1,-1)=="\"" then + L[#L+1]={"\1"..dict,sym:sub(2,-2),IsALookup=true} + else + local sym = getSymbol("`") + self:compileFWR("__PUSHPARSE",sym,'"$'..list[i]..'$"',name) + L[#L+1]="\1"..sym + end + elseif list[i]:sub(1,1)=="\"" and list[i]:sub(-1,-1)=="\"" then + L[#L+1]=list[i]:sub(2,-2) + elseif list[i]:sub(1,1)=="[" and list[i]:sub(-1,-1)=="]" then + L[#L+1]=pieceList(list[i]:sub(2,-2),self,name) + elseif tonumber(list[i]) then + L[#L+1]=tonumber(list[i]) + elseif list[i]=="true" then + L[#L+1]=true + elseif list[i]=="false" then + L[#L+1]=false + elseif list[i]:match("[%w_]+")==list[i] then + L[#L+1]="\1"..list[i] + elseif list[i]:match("[%w_]-%..-") then + local dict,sym=list[i]:match("([%w_]-)%.(.+)") + L[#L+1]={"\1"..dict,sym,IsALookup=true} + elseif list[i]:match("^([%w_]+)%s*%((.*)%)$") then + local func,args = list[i]:match("^([%w_]+)%s*%((.*)%)$") + local sym = getSymbol("`") + self:compileFWR(func,sym,args,name) + L[#L+1]="\1"..sym + elseif list[i]:match("[_%w%+%-/%*%^%(%)%%]+") and list[i]:match("[%+%-/%*%^%%]+") then + local char=getSymbol("$") + self:compileExpr(char,list[i],name) + L[#L+1]="\1"..char + else + self:pushError("Invalid Syntax!",list[i]) + end + end + return L +end +local function pieceAssign(a,self,name) + local dict,ind=a:match("(.-)%[(.+)%]") + local var + if dict and ind then + if ind:sub(1,1)=="\"" and ind:sub(-1,-1)=="\"" then + var={dict,ind:sub(2,-2)} + elseif tonumber(ind) then + var={dict,tonumber(ind)} + elseif ind:match("[%w_`]+")==ind then + var={dict,"\1"..ind} + elseif ind:match("[_%w%+%-`/%*%^%(%)%%]+") then + local sym="@A" + self:compileExpr(sym,ind,name) + var={dict,"\1"..sym} + else + self:pushError("Invalid way to index a dictonary/array!",ind) + end + elseif a:match("[%$%w_`]+")==a then + var="\1"..a + elseif a:match("[%$%w_`]-%..-") then + local dict,sym=a:match("([%w_]-)%.(.+)") + var={dict,sym,IsALookup=true} + elseif a:find(",") then + local list = parseManager.split(a) + var={} + for i=1,#list do + table.insert(var,pieceAssign(list[i],self,name)) + end + else + self:pushError("Invalid Syntax, Assignment is invalid!",a) + end + return var +end +function parseManager:compileFuncInExpr(list,name) + str = list:gsub("([%S]+)%s*%((.-)%)",function(a,b) + if a and b then + local d = getSymbol("`") + self:compileFWR(a,d,b,name) + return d + end + end) + return str +end +function parseManager:compileAssign(assignA,assignB,name) + local listA=parseManager.split(assignA) + local listB=parseManager.split(assignB) + local assign={ + Type="assign", + vars={}, + vals={} + } + for k=1,#listA do + local mathTest=false + local parsetest=false + self:debug("VAL: "..listB[k]) + self:debug("NAME: "..listA[k]) + if tonumber(listB[k]) then + assign.vals[#assign.vals+1]=tonumber(listB[k]) + elseif listB[k]:match("%w-%.%w+")==listB[k] then + local dict,sym=listB[k]:match("(%w-)%.(%w+)") + assign.vals[#assign.vals+1]={"\1"..dict,sym,IsALookup=true} + elseif listB[k]:sub(1,1)=="[" and listB[k]:sub(-1,-1)=="]" then + if listB[k]:match("%[%]") then + assign.vals[#assign.vals+1]={} + else + assign.vals[#assign.vals+1]=pieceList(listB[k]:sub(2,-2),self,name) + end + elseif listB[k]:sub(1,1)=="$" and listB[k]:sub(-1,-1)=="$" then + parsetest = true + self:compileFWR("__PUSHPARSE",listA[k],'"'..listB[k]..'"',name) + elseif listB[k]:match("[%w_]-%[.-%]") then + local dict,sym=listB[k]:match("([%w_]-)%[(.-)%]") + if tonumber(sym) then + assign.vals[#assign.vals+1]={"\1"..dict,tonumber(sym),IsALookup=true} + elseif sym:sub(1,1)=="\"" and sym:sub(-1,-1)=="\"" then + assign.vals[#assign.vals+1]={"\1"..dict,sym:sub(2,-2),IsALookup=true} + else + assign.vals[#assign.vals+1]={"\1"..dict,"\1"..sym,IsALookup=true} + end + elseif listB[k]:match("[%w_]-%..-") and not listB[k]:match("(%d-)%.(%d-)") then + local dict,sym=listB[k]:match("([%w_]-)%.(.+)") + assign.vals[#assign.vals+1]={"\1"..dict,sym,IsALookup=true} + elseif listB[k]:sub(1,1)=="\"" and listB[k]:sub(-1,-1)=="\"" then + assign.vals[#assign.vals+1]=listB[k]:sub(2,-2) + elseif listB[k]=="true" then + assign.vals[#assign.vals+1]=true + elseif listB[k]=="false" then + assign.vals[#assign.vals+1]=false + elseif listB[k]:match("[%w_]+")==listB[k] then + assign.vals[#assign.vals+1]="\1"..listB[k] + elseif listB[k]:match("[_%$%w%+%-/%*%^%(%)%.%%%s]+")==listB[k] and not(listB[k]:match("%w-%.%w+")==listB[k]) then + mathTest=true + workit = self:compileFuncInExpr(listB[k],name) + self:compileExpr(listA[k],workit,name) + else + self:pushError("Invalid Systax:",listB[k]) + end + if not mathTest and not parsetest then + assign.vars[#assign.vars+1]=pieceAssign(listA[k],self,name) + else + self:debug(assignA,assignB,name) + end + end + if #assign.vars~=0 then + table.insert(self.chunks[name],assign) + end +end +function parseManager:compileCondition(condition,iff,elsee,name) + self:compileLogic(condition,iff,elsee,name) +end +function parseManager:compileExpr(eql,expr,name) + local cmds={} + expr=expr:gsub("([%W])(%-%d)",function(b,a) + return b.."(0-"..a:match("%d+")..")" + end) + local mathAss=1 + function packFunc(l,o,r) + local l=tonumber(l) or l + local o=tonumber(o) or o + local r=tonumber(r) or r + if type(l)=="string" and l:match("[%w_]") then + l="\1"..l + end + if type(r)=="string" and r:match("[%w_]") then + r="\1"..r + end + if type(o)=="string" and o:match("[%w_]") then + o="\1"..o + end + if l=="@" then + l=r + r="" + end + if type(l)=="string" then + if l:find("\3") then + if type(o)=="number" then + cmds[#cmds+1]={Func=l:match("\3(.+)"),args={o}} + else + if o=="@" then o="" end + if o=="" then o=nil end + cmds[#cmds+1]={Func=l:match("\3(.+)"),o} + end + return + end + end + if l=="@" then -- Fancy movement of math + local n=#cmds + cmds[n]["vars"]={"\1%"..string.char(mathAss+64)} + l="\1%"..string.char(mathAss+64) + mathAss=mathAss+1 + cmds[n+1]["vars"]={"\1%"..string.char(mathAss+64)} + r="\1%"..string.char(mathAss+64) + mathAss=mathAss+1 + end + if r=="@" then -- Fancy movement of math + local n=#cmds + cmds[n]["vars"]={"\1%"..string.char(mathAss+64)} + r="\1%"..string.char(mathAss+64) + mathAss=mathAss+1 + -- cmds[n]["vars"]={"\1%"..string.char(mathAss+64)} + -- l="\1%"..string.char(mathAss+64) + -- mathAss=mathAss+1 + end + if r=="" then + local n=#cmds + cmds[n]["vars"]={"\1%"..string.char(mathAss+64)} + r=l + l="\1%"..string.char(mathAss+64) + mathAss=mathAss+1 + end + if o=="+" then + cmds[#cmds+1]={Func="ADD",args={l,(r or "")}} + elseif o=="-" then + cmds[#cmds+1]={Func="SUB",args={l,(r or "")}} + elseif o=="/" then + cmds[#cmds+1]={Func="DIV",args={l,(r or "")}} + elseif o=="*" then + cmds[#cmds+1]={Func="MUL",args={l,(r or "")}} + elseif o=="^" then + cmds[#cmds+1]={Func="POW",args={l,(r or "")}} + elseif o=="%" then + cmds[#cmds+1]={Func="MOD",args={l,(r or "")}} + else + self:pushError("Something went wrong!",tostring(l)..","..tostring(o)..","..tostring(r)) + end + end + function parseManager:pieceExpr(expr) + local count=0 + for i,v in pairs(self.methods) do + expr=expr:gsub(i.."(%b())",function(a) + a=a:sub(2,-2) + if a:sub(1,1)=="-" then + a="0"..a + end + packFunc("\3"..i,self:pieceExpr(a)) + return "@" + end) + end + for i,v in pairs(self.cFuncs) do + expr=expr:gsub(i.."(%b())",function(a) + a=a:sub(2,-2) + if a:sub(1,1)=="-" then + a="0"..a + end + packFunc("\3"..i,self:pieceExpr(a)) + return "@" + end) + end + expr=expr:gsub("%b()",function(a) + return self:pieceExpr(a:sub(2,-2)) + end) + local loop + for l,o,r in expr:gmatch("(.*)([%+%^%-%*/%%])(.*)") do + loop=true + if l:match("[%+%^%-%*/%%]") then + packFunc(self:pieceExpr(l),o,r) + else + packFunc(l,o,r) + end + end + if loop then + return "@" + else + return expr + end + end + if expr:match("[!%$%s&_%w%+%-,/%*%.%^%(%)%%]+")==expr then + expr = expr:gsub("%s","") + parseManager:pieceExpr(expr) + cmds[#cmds]["vars"]={"\1"..eql} + for i=1,#cmds do + if cmds[i].vars then + cmds[i].Type="fwr" + else + cmds[i].Type="fwor" + end + if not name then + --self:pushError("Unknown Error:",name) + else + table.insert(self.chunks[name],cmds[i]) + end + end + else + --self:pushError("Invalid math Expression!",expr) + end +end +function parseManager:compileFWR(FWR,vars,args,name) + vars=pieceAssign(vars,self,name) + if type(vars)=="string" then + vars={vars} + end + table.insert(self.chunks[name],{ + Type="fwr", + Func=FWR, + vars=vars, + args=pieceList(args,self,name), + }) +end +function parseManager:compileFWOR(FWOR,args,name) + table.insert(self.chunks[name],{ + Type="fwor", + Func=FWOR, + args=pieceList(args,self,name), + }) +end +function parseManager:compileLabel(label,name) + self.chunks[name].labels[label]=#self.chunks[name]+1 -- store this inside the chunk + table.insert(self.chunks[name],{ + Type="label", + pos=#self.chunks[name]+1, + label=label, + }) +end +function parseManager:compileLine(line,name) + table.insert(self.chunks[name],{ + Type="text", + text=line + }) +end +function parseManager:compileLogic(condition,iff,elsee,name) + local cmds={} + local function pieceLogic(conds) + conds=conds.." or 1==0" + conds=conds:gsub(" and ","\4") + conds=conds:gsub(" or ","\5") + local count=0 + local mathass=0 + _conds=conds:gsub("%s*\5".."1==0","") + local cmds={} + for l,eq,r in conds:gmatch("(.-)%s*([=~!><][=]*)(.-)%s*[\4\5]") do + charL=string.char(count+65) + charM=string.char(mathass+65) + count=count+1 + cmds={ + Type="fwr", + Func="COMPARE", + args={[3]=eq}, + vars={"\1!"..charL}, + } + local l,r=(l:gsub("[\4\5\6]*%(","")),(r:gsub("%)","")) + if l=="true" then + cmds.args[1]=true + elseif l=="false" then + cmds.args[1]=false + elseif tonumber(l) then + cmds.args[1]=tonumber(l) + elseif l:match("[%w_]+")==l then + cmds.args[1]="\1"..l + elseif l:match("[%._%w%+%-/%*%^%(%)%%]+")==l then + self:compileExpr("&"..charM,l,name) + cmds.args[1]="\1&"..charM + mathass=mathass+1 + elseif l:sub(1,1)=="\"" and l:sub(-1,-1) then + cmds.args[1]=l:sub(2,-2) + else + self:pushError("Invalid Syntax in logical expression!",l) + end + r=r:gsub("%s*\5".."1==0","") + charM=string.char(mathass+65) + if r=="true" then + cmds.args[2]=true + elseif r=="false" then + cmds.args[2]=false + elseif tonumber(r) then + cmds.args[2]=tonumber(r) + elseif r:match("[%w_]+")==r then + cmds.args[2]="\1"..r + elseif r:match("[_%w%+%-/%*%^%(%)%%]+")==r then + self:compileExpr("&"..charM,r,name) + cmds.args[2]="\1&"..charM + mathass=mathass+1 + elseif r:sub(1,1)=="\"" and r:sub(-1,-1) then + cmds.args[2]=r:sub(2,-2) + else + self:pushError("Invalid Syntax in logical expression!",r) + end + l=l:gsub("%%","%%%%");r=r:gsub("%%","%%%%");l=l:gsub("%+","%%%+");r=r:gsub("%+","%%%+");l=l:gsub("%*","%%%*");r=r:gsub("%*","%%%*");l=l:gsub("%-","%%%-");r=r:gsub("%-","%%%-");l=l:gsub("%^","%%%^");r=r:gsub("%^","%%%^");l=l:gsub("%$","%%%$");r=r:gsub("%$","%%%$");l=l:gsub("%.","%%%.");r=r:gsub("%.","%%%.");l=l:gsub("%[","%%%[");r=r:gsub("%[","%%%[");l=l:gsub("%]","%%%]");r=r:gsub("%]","%%%]");l=l:gsub("%?","%%%?");r=r:gsub("%?","%%%?");l=l:gsub("%(","%%%(");r=r:gsub("%(","%%%(");l=l:gsub("%)","%%%)");r=r:gsub("%)","%%%)") + _conds=_conds:gsub(l.."%s*"..eq.."%s*"..r,"!"..charL) + table.insert(self.chunks[name],cmds) + end + _conds=_conds:gsub("\4","*") + _conds=_conds:gsub("\5","+") + if not _conds:find("%*") and not _conds:find("%+") then + if not cmds.vars then + self:pushError("Invalid condition passed!",condition) + end + cmds.vars[1]="\1L$" + else + self:compileExpr("L$",_conds,name) + end + table.insert(self.chunks[name],{ + Type="fwor", + Func="CSIM", + args={"\1L$"}, + }) + FWORi,argsi=iff:match("^([%w_]+)%s*%((.*)%)") + FWORe,argse=elsee:match("^([%w_]+)%s*%((.*)%)") + if FWORi=="SKIP" then + self:compileFWOR(FWORi,tostring(tonumber(argsi)+1),name) + else + self:compileFWOR(FWORi,argsi,name) + end + self:compileFWOR(FWORe,argse,name) + end + pieceLogic(condition) +end +local function trim1(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end +local function extract(dat,name) + if type(dat)=="string" and dat:sub(1,1)=="\1" then + return dat:sub(2,-1) + elseif tonumber(dat)~=nil then + return tonumber(dat) + else + return dat + end +end +function parseManager:compile(name,ctype,data) + local isFBlock,FBArgs=ctype:match("(f)unction%((.*)%)") + --Check if we are dealing with a FBlock + if isFBlock=="f" then + if not self.isInternal then + self.isInternal = {} + end + self.cFuncs[name]=true + -- if self.methods[name] then + -- self:pushError("You cannot create a method with the same name as a standard method or duplicate method names!",name) + -- end + self.methods[name]=function(...) + --self:Invoke(name,...) + return self:Call(name,...) + end + self.isInternal[name]=self.methods[name] + -- self.__INTERNAL[name] = true + -- if not self.variables.__internal then + -- self.variables.__internal = {} + -- end + -- self.variables.__internal[name] = true + self.mainENV[name]=self.methods[name] + table.insert(self.chunks[name],{ + Type="funcblock", + args=pieceList(FBArgs,self,name) + }) + end + self:debug("COMPILING Block: "..name) + local data=bin.new(data):lines() + local choiceBlock=false + local stack = {} + local choiceBlockLOOP=false + local choice={} + for i=1,#data do + data[i]=trim1(data[i]) + if data[i]~="" then + if data[i]:match("for[%s%w=%-]-[%d%-%w%(%),%s]-<") then + choiceBlockFor=true + local sym = getSymbol("FOR") + local var,a,b,c = data[i]:match("for%s*([%w_]+)%s*=%s*(%-*[%d%w%(%)]+),%s*(%-*[%d%w%(%)]+)%s*,*%s*(%-*[%d%w%(%)]*)") + local s = getSymbol(getSymbol("LOOPEND")) + push(stack,{sym,var,a,b,s,1,c}) -- 1 for loop, 2 while loop + data[i] = "::"..sym.."::" + self:compileAssign(var,a,name) + elseif data[i]:match("while ([_%w=><~!%-%s]+)<$") then + -- WHILE LOOP + local sym = getSymbol("WHILE") + local s = getSymbol(getSymbol("LOOPEND")) + self:compileLabel(sym,name) + local cond = data[i]:match("while ([_%w=><~!%-%s]-)%s*<$") + data[i]="if "..cond.." then SKIP(0)|GOTO(\""..s.."\")" + push(stack,{sym,0,0,0,s,2}) -- 1 for loop, 2 while loop + elseif data[i]:match(".-\"%s*<%s*") then + choiceBlock=true + choice={} + j=0 + end + if (choiceBlockLOOP or #stack~=0) and not choiceBlock then + if data[i]==">" then + choiceBlockLOOP=false + local dat = pop(stack) + local s = dat[5] + local cmd = dat[6] + if cmd==1 then + local t = extract(dat[7],name) + if type(t)=="string" then + t="+"..t + end + -- parseManager.print(dat[2] .. (t or "+1")) + self:compileAssign(dat[2],dat[2] .. (t or "+1"),name) + self:compileCondition(dat[2].."=="..tonumber(dat[4])+(tonumber(dat[7]) or 1),"GOTO(\""..s.."\")","GOTO(\""..dat[1].."\")",name) + data[i] = "::"..s.."::" + elseif cmd == 2 then + self:compileFWOR("GOTO","\""..dat[1].."\"",name) + data[i]="::"..s.."::" + end + end + end + if choiceBlock then + if data[i]==">" then + choiceBlock=false + table.insert(self.chunks[name],choice) + else + dat=data[i]:gsub("%s*<","") + if j==0 then + choice.Type="choice" + choice.prompt=dat:sub(2,-2) + j=1 + else + local a,b=dat:match("\"(.-)\"%s*(.+)") + if b then + local f,ag=b:match("^([%w_]+)%s*(%b())") + if ag~="" then + choice[#choice+1]={a,{ + Type="fwor", + Func=f, + args=pieceList(ag:sub(2,-2),self,name), + }} + else + choice[#choice+1]={a,{ + Type="fwor", + Func=f, + args={}, + }} + end + end + end + end + else + local cmd={} + local Return,RETArgs=data[i]:match("(return)%s*(.*)$") + local line=data[i]:match("^\"(.+)\"") + local assignA,assignB=data[i]:match("^([%w,%[%]\"_%(%)%+%-%*%%%./]+)%s*=%s*(.+)") + local vars,FWR,args=data[i]:match("([\"%[%]%w_,]+)%s*=%s*([%w_]+)%s*%((.*)%)$") + local FWOR + if not args then + FWOR,args=data[i]:match("^([%w_]+)%s*%((.*)%)$") + end + local label=data[i]:match("::(.*)::") + local condition,iff,elsee=data[i]:match("if%s*(.+)%s*then%s*(.-%))%s*|%s*(.+%))") + ------ + local vars2,FWR2,args2=data[i]:match("([%[%]\"%w_,]+)%s*=%s*([%.:%w_]+)%s*%((.*)%)$") + if not args2 then + FWOR2,args2=data[i]:match("^([%.:%w_]+)%s*%((.*)%)$") + end + local flags,target = data[i]:match("(%u+)%s([%w%s]+)") + ------ + if line then + self:compileLine(line,name) + elseif condition then + self:compileCondition(condition,iff,elsee,name) + elseif FWR then + self:compileFWR(FWR,vars,args,name) + elseif FWOR then + self:compileFWOR(FWOR,args,name) + elseif FWR2 then + local dict,dot,sym=FWR2:match("([%w_]-)([%.:])(.+)") + if dot==":" then + args2=dict..","..args2 + if args2:sub(-1,-1)=="," then + args2 = args2:sub(1,-2) + end + end + self:compileFWR({dict,sym,IsALookup=true},vars2,args2,name) + elseif FWOR2 then + local dict,dot,sym=FWOR2:match("([%w_]-)([%.:])(.+)") + if dot==":" then + args2=dict..","..args2 + if args2:sub(-1,-1)=="," then + args2 = args2:sub(1,-2) + end + end + self:compileFWOR({dict,sym,IsALookup=true},args2,name) + elseif assignA then + self:compileAssign(assignA,assignB,name) + elseif label then + self:compileLabel(label,name) + elseif Return and isFBlock then + table.insert(self.chunks[name],{ + Type="return", + RETArgs=pieceList(RETArgs,self,name) + }) + elseif Return and not(isFBlock) then + self:pushError("Attempt to call return in a non function block!",data[i]) + elseif flags and target then + table.insert(self.chunks[name],{ + Type = "toggle", + Flags = flags, + Target = target + }) + else + table.insert(self.chunks[name],{ + Type="customdata", + data=data[i], + }) + end + end + end + end +end +function parseManager:testDict(dict) + if type(dict[1])=="string" then + if dict[1]:sub(1,1)=="\1" and dict.IsALookup then + return true + end + else + return + end +end +function parseManager:dataToEnv(values) + local env = {} + if values then + for i,v in pairs(values) do + env[#env+1] = test:dataToValue(v) + end + end + return env +end +function parseManager:dataToValue(name,envF,b) -- includes \1\ + envF=envF or self.currentENV + local tab=name + if type(name)=="string" then + if tonumber(name) then return tonumber(name) end + local ret + if name:sub(1,1)=="\1" then + return self:parseHeader(envF[name:sub(2)]) + elseif b then + return self:parseHeader2(name) + else + return self:parseHeader(name) + end + elseif type(name)=="table" then + if name.__index then + return name + end + if self:testDict(name) then + return envF[name[1]:sub(2,-1)][self:dataToValue(name[2],envF)] + else + tab={} + for i=1,#name do + tab[i]=self:dataToValue(name[i],envF) + end + end + end + if tab~= nil then + return tab + else + return {} + end +end +function parseManager:define(t) + for i,v in pairs(t) do + self.methods[i]=v + end +end +function parseManager:handleChoice(func) + self.choiceManager = func +end +function round(num, numDecimalPlaces) + local mult = 10^(numDecimalPlaces or 0) + return math.floor(num * mult + 0.5) / mult +end +function parseManager:parseHeader2(data) + dat = data:sub(2,-2) + if dat:find(":") and not dat:find("%[") then + local var,num = dat:match("(.-):(.+)") + local num = tonumber(num) + if type(self.currentENV[var])=="number" then + return round(self.currentENV[var],num) + else + self:pushError("Attempt to round a non number!") + end + elseif dat:find("%[") then + if not type(self.currentENV[dat])=="table" then + self:pushError("Attempt to index a non table object!") + return + else + if dat:find(":") then + local var,inwards = dat:match("(.-)%[(.+)%]") + local ind = parseManager.split(inwards,":") + if #ind==2 then + local a,b = tonumber(ind[1]),tonumber(ind[2]) + if b <= #self.currentENV[var] then + local str={} + for i=1,b do + table.insert(str,self.currentENV[var][i]) + end + return str + else + self:pushError("Attempt to index a table at a non existing location!") + end + end + else + local var,inwards = dat:match("(.-)%[(.+)%]") + local num = tonumber(inwards) + local ind = self.currentENV[inwards] + local sind = self.currentENV[var][inwards] + if num then + return self.currentENV[var][num] + elseif ind then + return self.currentENV[var][ind] + elseif sind then + return sind + else + self:pushError("Invalid index: "..inwards.."!") + end + end + end + else + -- regular strings + self:debug("PARSE DATA: "..tostring(self.currentENV[dat])) + if self.currentENV[dat]~=nil then + if type(self.currentENV[dat])=="table" then + local str={} + for i=1,#self.currentENV[dat] do + table.insert(str,self.currentENV[dat][i]) + end + return str + else + return self.currentENV[dat] + end + else + return nil + end + end +end +function parseManager:parseHeader(data) + if type(data)=="string" then + data=data:gsub("%$([%w_,:%.%[%]%-\"']+)%$",function(dat) + self:debug("PARSE: "..dat) + if dat:find(":") and not dat:find("%[") then + local var,num = dat:match("(.-):(.+)") + local num = tonumber(num) + if type(self.currentENV[var])=="number" then + local str = "" + local n = num + num = round(self.currentENV[var],num) + if n>0 and math.floor(num)==num then -- This only for string version + str = "."..string.rep("0",n) + elseif n>0 then + local s = tostring(num) + str = string.rep("0",n-(#s-s:find("%."))) + end + return num..str + else + self:pushError("Attempt to round a non number!") + end + elseif dat:find("%[") then + if type(self.currentENV[dat:match("(.-)%[")])=="string" then + if dat:find(":") then + local var,inwards = dat:match("(.-)%[(.+)%]") + local ind = parseManager.split(inwards,":") + if #ind==2 then + local str = self.currentENV[dat:match("(.-)%[")] + if tonumber(ind[1])<0 and tonumber(ind[2])>0 then + return str:reverse():sub(math.abs(tonumber(ind[1])),-math.abs(tonumber(ind[2]))) + else + return str:sub(ind[1],ind[2]) + end + end + end + elseif not type(self.currentENV[dat])=="table" then + self:pushError("Attempt to index a non table object!") + return + else + if dat:find(":") then + local var,inwards = dat:match("(.-)%[(.+)%]") + local ind = parseManager.split(inwards,":") + if #ind==2 then + local a,b = tonumber(ind[1]),tonumber(ind[2]) + if b <= #self.currentENV[var] then + local str="" + for i=1,b do + str=str..tostring(self.currentENV[var][i]).."," + end + str=str:sub(1,-2) + return "["..str.."]" + else + self:pushError("Attempt to index a table at a non existing location!") + end + end + else + local var,inwards = dat:match("(.-)%[(.+)%]") + local num = tonumber(inwards) + local ind = self.currentENV[inwards] + local sind = self.currentENV[var][inwards] + if num then + return tostring(self.currentENV[var][num]) + elseif ind then + return tostring(self.currentENV[var][ind]) + elseif sind then + return tostring(sind) + else + self:pushError("Invalid index: "..inwards.."!") + end + end + end + else + -- regular strings + self:debug("PARSE DATA: "..tostring(self.currentENV[dat])) + if self.currentENV[dat]~=nil then + if type(self.currentENV[dat])=="table" then + local str="" + for i=1,#self.currentENV[dat] do + str=str..tostring(self.currentENV[dat][i]).."," + end + str=str:sub(1,-2) + return "["..str.."]" + else + return tostring(self.currentENV[dat]) + end + else + return "nil" + end + end + end) + end + return data +end +function parseManager:pairAssign(vars,vals,envF) + for i=1,#vars do + self:debug("ASSIGN NAME: "..tostring(vars[i])) + self:debug("ASSIGN DATA: "..tostring(self:dataToValue(vals[i],envF))) + if type(vars[i])=="table" then + if type(self.currentENV[vars[i][1]])~="table" then + self:pushError("Attempt to index a non table object:",vars[i][1].."[\""..vars[i][2].."\"]") + end + self.currentENV[vars[i][1]][self:dataToValue(vars[i][2])]=self:dataToValue(vals[i],envF) + else + self.currentENV[vars[i]:sub(2,-1)]=self:dataToValue(vals[i],envF) + end + end +end +function parseManager:next(block,choice) + if self.entry then + self.isrunning = true + block = block or self.entry + self.entry = nil + end + if block then + self.isrunning = true + end + local chunk = self.currentChunk or self.chunks[block] or self.chunks["START"] + self.currentChunk=chunk + local ret + local data + if not choice then + data=chunk[chunk.pos] + else + data = self.choiceData[choice][2] + end + if not data then self.isrunning = false return end + local IRET + if data.Type=="label" then + chunk.pos=chunk.pos+1 + data=chunk[chunk.pos] + IRET = self.__LABEL(data.label,data.pos) + end + if not data then self.isrunning = false return end + chunk.pos=chunk.pos+1 + self:debug("TYPE: "..data.Type) + if data.Type=="text" then + self.lastCall=nil + IRET = self.__TEXT(self:parseHeader(data.text)) + elseif data.Type=="funcblock" then + for i,v in ipairs(data.args) do + self.currentENV[v:sub(2,-1)]=self.fArgs[i] + end + IRET = self.__FBLOCK(args) + elseif data.Type=="return" then + IRET = self.__RETURN(vars, data.RETArgs) + elseif data.Type=="fwr" then + local args=self:dataToValue(data.args,nil,data.Func == "__PUSHPARSE") + local rets={} + local Func + if type(data.Func)=="table" then + Ext=true + Func=self.currentENV[data.Func[1]][data.Func[2]] + else + Func=self.methods[data.Func] + end + if self.isInternal[data.Func] then + rets={Func(unpack(args))} + else + rets={Func(self,unpack(args))} + end + if #rets~=0 then + self:pairAssign(data.vars,rets) + end + self.lastCall=nil + IRET = self.__METHOD(data.Func,args) + elseif data.Type=="fwor" then + local args=self:dataToValue(data.args) + local Func + local Ext=false + if type(data.Func)=="table" then + Ext=true + Func=self.currentENV[data.Func[1]][data.Func[2]] + else + Func=self.methods[data.Func] + end + if Func == nil then + self:pushError("Attempt to call a non existing function!",data.Func) + end + if Ext then + self.lastCall=Func(unpack(args)) + else + self.lastCall=Func(self,unpack(args)) + end + IRET = self.__METHOD(data.Func,args) + elseif data.Type=="choice" then + self.choiceData=data + local CList={} + for i=1,#data do + CList[#CList+1]=self:parseHeader(data[i][1]) + end + self.lastCall=nil + local cm = self.__CHOICE(self:parseHeader(data.prompt),CList) + self:next(nil,cm) + return true + elseif data.Type=="assign" then + self:pairAssign(data.vars,data.vals) + self.lastCall=nil + IRET = self.__ASSIGN(vars,vals) + elseif data.Type=="toggle" then + local flags,target = data.Flags,data.Target + if flags == "USING" then + if target:find("as") then + local use,name = target:match("(.-) as (.+)") + self:USING(use,name) + else + self:USING(target) + end + elseif flags == "ENABLE" then + self:ENABLE(target) + elseif flags == "DISABLE" then + self:DISABLE(target) + else + self:pushWarning("Invalid flag: "..flag.."!") + end + IRET = self.__TOGGLE(target,use,name) + else + self.lastCall=nil + IRET = self.__CS(data.data) + end + if IRET=="KILL" then + return false + end + return true +end +parseManager.__TEXT = function(text) + io.write(text) + io.read() +end +parseManager.__METHOD = function() + -- +end +parseManager.__CHOICE = function(prompt,list) + print(prompt) + for i=1,#list do + print(i..". "..list[i]) + end + io.write("Choose#: ") + cm=tonumber(io.read()) + return cm +end +parseManager.__LABEL = function() + -- +end +parseManager.__TOGGLE = function() + -- +end +parseManager.__ASSIGN = function() + -- +end +parseManager.__FBLOCK = function() + -- +end +parseManager.__CS = function() + -- +end +parseManager.__RETURN = function() + -- +end +function parseManager:Call(func,...) + local env = {} + local temp + temp = parseManager:load(self.path,nil,true) + temp.fArgs = {...} + temp.__RETURN = function(vars,retargs) + env = temp:dataToEnv(retargs) + return "KILL" + end + temp.entry = func + local active = true + while active do + active = temp:think() + end + return unpack(env) +end +function parseManager:think() + return self:next() +end +require("parseManager.standardDefine") diff --git a/Visual Novel/parseManager/standardDefine.lua b/Visual Novel/parseManager/standardDefine.lua new file mode 100644 index 0000000..bc78fe1 --- /dev/null +++ b/Visual Novel/parseManager/standardDefine.lua @@ -0,0 +1,391 @@ +local bin = require("bin") +local clock = os.clock +parseManager:define{ + __PUSHPARSE = function(self,dat) + return dat + end, + getInput = function(self,prompt) + if prompt then + io.write(prompt) + end + return io.read() + end, + print=function(self,...) + print(...) + end, + WATCH=function(self,...) + if self.watchvars then return end + self.watchvars = {...} + end, + SAVE=function(self,fn) + local file = bin.new() + local data = {} + for i=1,#self.watchvars do + data[self.watchvars[i]] = self.currentENV[self.watchvars[i]] + end + data["__CHUNK"] = self.methods.getCurrentChunk(self) + data["__POSITION"] = self.methods.getCurrentPosition(self) + file:addBlock(data) + file:tofile(fn or "save.dat") + end, + LOAD=function(self,fn) + if not bin.fileExists(fn or "save.dat") then return false end + local file = bin.load(fn or "save.dat") + t = file:getBlock("t") + local c,p = t.__CHUNK,t.__POSITION + t.__CHUNK,t.__POSITION = nil,nil + for i,v in pairs(t) do + self.mainENV[i] = v + end + if self.stats.statesave then + self.methods.JUMP(self,c, p) + end + return true,c,p + end, + EXECUTE = function(self,cmd) + os.execute(cmd) + end, + error=function(self,msg) + self:pushError(msg,"\2") + end, + setGlobalVar=function(self,var,val) + self.mainENV[var]=val + end, + getGlobalVar=function(self,var,val) + self.mainENV[var]=val + end, + len=function(self,t) + return #t + end, + QUIT=function() + os.exit() + end, + getCurrentChunk = function(self) + for i,v in pairs(self.chunks) do + if self.currentChunk == v then + return i + end + end + end, + getCurrentPosition = function(self) + return self.currentChunk.pos-1 + end, + sleep=function(self,n) + local t0 = clock() + while clock() - t0 <= n do end + end, + JUMP=function(self,block,pos) + if self.chunks[block] then + self.chunks[block].pos=pos or 1 + self.currentChunk=self.chunks[block] + else + self:pushError("Attempt to jump to a non existing block:","\2") + end + end, + SKIP=function(self,n) + if type(n)~="number" then self:pushError("Number expected got: "..type(n),"SKIP( ? )") end + self.currentChunk.pos=self.currentChunk.pos+n + end, + GOTO=function(self,label) + if self.currentChunk.labels[label] then + self.currentChunk.pos=self.currentChunk.labels[label] + else + self:pushError("Attempt to goto a non existing label:","\2") + end + end, + GOTOE=function(self,label) + local chunks=self.chunks + for i,v in pairs(chunks) do + if chunks[i].labels[label] then + self.currentChunk=chunks[i] + self.currentChunk.pos=chunks[i].labels[label] + return + end + end + self:pushError("Attempt to goto a non existing label:","\2") + end, + ADD=function(self,a,b) + if type(self.lastCall)=="number" and type(a)=="number" then + return self.lastCall+a + elseif type(a)=="number" and type(b)=="number" then + return a+b + else + self:pushError("Invalid Arguments!","ADD("..tostring(a)..","..tostring(b)..")") + end + end, + SUB=function(self,a,b) + if type(self.lastCall)=="number" and type(a)=="number" then + return self.lastCall-a + elseif type(a)=="number" and type(b)=="number" then + return a-b + else + self:pushError("Invalid Arguments!","SUB("..tostring(a)..","..tostring(b)..")") + end + end, + MUL=function(self,a,b) + if type(self.lastCall)=="number" and type(a)=="number" then + return self.lastCall*a + elseif type(a)=="number" and type(b)=="number" then + return a*b + else + self:pushError("Invalid Arguments!","MUL("..tostring(a)..","..tostring(b)..")") + end + end, + DIV=function(self,a,b) + if type(self.lastCall)=="number" and type(a)=="number" then + return self.lastCall/a + elseif type(a)=="number" and type(b)=="number" then + return a/b + else + self:pushError("Invalid Arguments!","DIV("..tostring(a)..","..tostring(b)..")") + end + end, + POW=function(self,a,b) + if type(self.lastCall)=="number" and type(a)=="number" then + return self.lastCall^a + elseif type(a)=="number" and type(b)=="number" then + return a^b + else + self:pushError("Invalid Arguments!","POW("..tostring(a)..","..tostring(b)..")") + end + end, + sqrt=function(self,a) + if type(self.lastCall)=="number" then + return math.sqrt(self.lastCall) + elseif type(a)=="number" then + return math.sqrt(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + cos=function(self,a) + if type(self.lastCall)=="number" then + return math.cos(self.lastCall) + elseif type(a)=="number" then + return math.cos(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + sin=function(self,a) + if type(self.lastCall)=="number" then + return math.sin(self.lastCall) + elseif type(a)=="number" then + return math.sin(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + tan=function(self,a) + if type(self.lastCall)=="number" then + return math.tan(self.lastCall) + elseif type(a)=="number" then + return math.tan(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + log=function(self,a) + if type(self.lastCall)=="number" then + return math.log(self.lastCall) + elseif type(a)=="number" then + return math.log(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + acos=function(self,a) + if type(self.lastCall)=="number" then + return math.acos(self.lastCall) + elseif type(a)=="number" then + return math.acos(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + tanh=function(self,a) + if type(self.lastCall)=="number" then + return math.tanh(self.lastCall) + elseif type(a)=="number" then + return math.tanh(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + deg=function(self,a) + if type(self.lastCall)=="number" then + return math.deg(self.lastCall) + elseif type(a)=="number" then + return math.deg(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + cosh=function(self,a) + if type(self.lastCall)=="number" then + return math.cosh(self.lastCall) + elseif type(a)=="number" then + return math.cosh(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + sinh=function(self,a) + if type(self.lastCall)=="number" then + return math.sinh(self.lastCall) + elseif type(a)=="number" then + return math.sinh(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + randomseed=function(self,a) + if type(self.lastCall)=="number" then + return math.randomseed(self.lastCall) + elseif type(a)=="number" then + return math.randomseed(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + random = function(self,a,b) + return math.random(a,b) + end, + ceil=function(self,a) + if type(self.lastCall)=="number" then + return math.ceil(self.lastCall) + elseif type(a)=="number" then + return math.ceil(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + floor=function(self,a) + if type(self.lastCall)=="number" then + return math.floor(self.lastCall) + elseif type(a)=="number" then + return math.floor(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + rad=function(self,a) + if type(self.lastCall)=="number" then + return math.rad(self.lastCall) + elseif type(a)=="number" then + return math.rad(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + abs=function(self,a) + if type(self.lastCall)=="number" then + return math.abs(self.lastCall) + elseif type(a)=="number" then + return math.abs(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + asin=function(self,a) + if type(self.lastCall)=="number" then + return math.asin(self.lastCall) + elseif type(a)=="number" then + return math.asin(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + log10=function(self,a) + if type(self.lastCall)=="number" then + return math.log10(self.lastCall) + elseif type(a)=="number" then + return math.log10(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + atan2=function(self,a) + if type(self.lastCall)=="number" then + return math.atan2(self.lastCall) + elseif type(a)=="number" then + return math.atan2(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + exp=function(self,a) + if type(self.lastCall)=="number" then + return math.exp(self.lastCall) + elseif type(a)=="number" then + return math.exp(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + atan=function(self,a) + if type(self.lastCall)=="number" then + return math.atan(self.lastCall) + elseif type(a)=="number" then + return math.atan(a) + else + self:pushError("Invalid Arguments!","\2") + end + end, + max=function(self,a,b) + if type(self.lastCall)=="number" and type(a)=="number" then + return max(self.lastCall,a) + elseif type(a)=="number" and type(b)=="number" then + return max(a,b) + else + self:pushError("Invalid Arguments!","\2") + end + end, + mod=function(self,a,b) + if type(self.lastCall)=="number" and type(a)=="number" then + return mod(self.lastCall,a) + elseif type(a)=="number" and type(b)=="number" then + return mod(a,b) + else + self:pushError("Invalid Arguments!","\2") + end + end, + COMPARE=function(self,v1,v2,sym) + if sym==nil then self:pushError("Unexpected Error has occurred!","non-existing variable!") end + if sym=="==" then + if v1==v2 then return 1 else return 0 end + elseif sym==">=" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end + if v1>=v2 then return 1 else return 0 end + elseif sym=="<=" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end + if v1<=v2 then return 1 else return 0 end + elseif sym==">" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end + if v1>v2 then return 1 else return 0 end + elseif sym=="<" then + if v1 == nil or v2 == nil then + self:pushError("Conditional mathematical args are non-existing!") + end + if v1 -} -[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 deleted file mode 100644 index 68ed33d..0000000 --- a/adventures/home.dat +++ /dev/null @@ -1,3 +0,0 @@ -[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 deleted file mode 100644 index a503127..0000000 --- a/adventures/livingroom.dat +++ /dev/null @@ -1,75 +0,0 @@ -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 deleted file mode 100644 index 8343cc4..0000000 --- a/adventures/resources.dat +++ /dev/null @@ -1,40 +0,0 @@ -[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 deleted file mode 100644 index c07c8a8..0000000 --- a/adventures/store.dat +++ /dev/null @@ -1,221 +0,0 @@ -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 deleted file mode 100644 index 78ad96d..0000000 Binary files a/arrow.png and /dev/null differ diff --git a/config.txt b/config.txt deleted file mode 100644 index e23d85d..0000000 --- a/config.txt +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 529c437..0000000 Binary files a/fire.jpg and /dev/null differ diff --git a/init.dat b/init.dat deleted file mode 100644 index e5c4c53..0000000 --- a/init.dat +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index 70ba3c0..0000000 Binary files a/loading/Thumbs.db and /dev/null differ diff --git a/loading/image-0000001.png b/loading/image-0000001.png deleted file mode 100644 index 15dc437..0000000 Binary files a/loading/image-0000001.png and /dev/null differ diff --git a/loading/image-0000002.png b/loading/image-0000002.png deleted file mode 100644 index 5a35f62..0000000 Binary files a/loading/image-0000002.png and /dev/null differ diff --git a/loading/image-0000003.png b/loading/image-0000003.png deleted file mode 100644 index e32309f..0000000 Binary files a/loading/image-0000003.png and /dev/null differ diff --git a/loading/image-0000004.png b/loading/image-0000004.png deleted file mode 100644 index 62eef36..0000000 Binary files a/loading/image-0000004.png and /dev/null differ diff --git a/loading/image-0000005.png b/loading/image-0000005.png deleted file mode 100644 index e0eaea1..0000000 Binary files a/loading/image-0000005.png and /dev/null differ diff --git a/loading/image-0000006.png b/loading/image-0000006.png deleted file mode 100644 index 500db7b..0000000 Binary files a/loading/image-0000006.png and /dev/null differ diff --git a/loading/image-0000007.png b/loading/image-0000007.png deleted file mode 100644 index b9238b3..0000000 Binary files a/loading/image-0000007.png and /dev/null differ diff --git a/loading/image-0000008.png b/loading/image-0000008.png deleted file mode 100644 index d87356f..0000000 Binary files a/loading/image-0000008.png and /dev/null differ diff --git a/loading/image-0000009.png b/loading/image-0000009.png deleted file mode 100644 index 054d32d..0000000 Binary files a/loading/image-0000009.png and /dev/null differ diff --git a/loading/image-0000010.png b/loading/image-0000010.png deleted file mode 100644 index 72750cd..0000000 Binary files a/loading/image-0000010.png and /dev/null differ diff --git a/loading/image-0000011.png b/loading/image-0000011.png deleted file mode 100644 index 40362ae..0000000 Binary files a/loading/image-0000011.png and /dev/null differ diff --git a/loading/image-0000012.png b/loading/image-0000012.png deleted file mode 100644 index ddf4cae..0000000 Binary files a/loading/image-0000012.png and /dev/null differ diff --git a/loading/image-0000013.png b/loading/image-0000013.png deleted file mode 100644 index d80c93e..0000000 Binary files a/loading/image-0000013.png and /dev/null differ diff --git a/loading/image-0000014.png b/loading/image-0000014.png deleted file mode 100644 index e458aa6..0000000 Binary files a/loading/image-0000014.png and /dev/null differ diff --git a/loading/image-0000015.png b/loading/image-0000015.png deleted file mode 100644 index a7d34b0..0000000 Binary files a/loading/image-0000015.png and /dev/null differ diff --git a/loading/image-0000016.png b/loading/image-0000016.png deleted file mode 100644 index 14c4979..0000000 Binary files a/loading/image-0000016.png and /dev/null differ diff --git a/loading/image-0000017.png b/loading/image-0000017.png deleted file mode 100644 index d22c69c..0000000 Binary files a/loading/image-0000017.png and /dev/null differ diff --git a/loading/image-0000018.png b/loading/image-0000018.png deleted file mode 100644 index 2efdbc0..0000000 Binary files a/loading/image-0000018.png and /dev/null differ diff --git a/loading/image-0000019.png b/loading/image-0000019.png deleted file mode 100644 index 3572b5e..0000000 Binary files a/loading/image-0000019.png and /dev/null differ diff --git a/loading/image-0000020.png b/loading/image-0000020.png deleted file mode 100644 index 4a60bc6..0000000 Binary files a/loading/image-0000020.png and /dev/null differ diff --git a/main.lua b/main.lua deleted file mode 100644 index c49e61a..0000000 --- a/main.lua +++ /dev/null @@ -1,380 +0,0 @@ ---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 deleted file mode 100644 index fe2cb70..0000000 --- a/net/chatting.lua +++ /dev/null @@ -1,51 +0,0 @@ -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 deleted file mode 100644 index dbea43a..0000000 --- a/net/email.lua +++ /dev/null @@ -1,53 +0,0 @@ -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 deleted file mode 100644 index 21c7e5e..0000000 --- a/net/identity.lua +++ /dev/null @@ -1,192 +0,0 @@ -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 deleted file mode 100644 index cd4ef7a..0000000 --- a/net/init.lua +++ /dev/null @@ -1,483 +0,0 @@ -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 deleted file mode 100644 index d1a2018..0000000 --- a/net/sft.lua +++ /dev/null @@ -1,179 +0,0 @@ -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 deleted file mode 100644 index 23496fa..0000000 --- a/parseManager/AICM.lua +++ /dev/null @@ -1,37 +0,0 @@ -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 deleted file mode 100644 index 08ac193..0000000 --- a/parseManager/EBIM.lua +++ /dev/null @@ -1,71 +0,0 @@ -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 deleted file mode 100644 index 26fb46f..0000000 --- a/parseManager/bytecode.lua +++ /dev/null @@ -1,44 +0,0 @@ --- 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 deleted file mode 100644 index af90212..0000000 --- a/parseManager/init.lua +++ /dev/null @@ -1,1277 +0,0 @@ -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 deleted file mode 100644 index e4a5b84..0000000 --- a/parseManager/interpreter.lua +++ /dev/null @@ -1,10 +0,0 @@ -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 deleted file mode 100644 index f19efec..0000000 --- a/structure.dat +++ /dev/null @@ -1,233 +0,0 @@ -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 deleted file mode 100644 index 18836ce..0000000 Binary files a/test.aac and /dev/null differ diff --git a/test.jpg b/test.jpg deleted file mode 100644 index 6951cc4..0000000 Binary files a/test.jpg and /dev/null differ diff --git a/test.lua b/test.lua deleted file mode 100644 index 8f760f8..0000000 --- a/test.lua +++ /dev/null @@ -1,58 +0,0 @@ -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 deleted file mode 100644 index 6b6f022..0000000 Binary files a/test.mp3 and /dev/null differ