diff --git a/client/GuiManager.lua b/client/GuiManager.lua new file mode 100644 index 0000000..eeb83f3 --- /dev/null +++ b/client/GuiManager.lua @@ -0,0 +1,4027 @@ +utf8 = require("utf8") +_defaultfont = love.graphics.getFont() +gui = {} +gui.__index = gui +gui.TB={} +gui.Version="8.0.0" -- Is it really ready for release? +_GuiPro={GBoost=true,hasDrag=false,DragItem={},Children={},Visible=true,count=0,x=0,y=0,height=0,width=0,update=function(self) local things=GetAllChildren2(self) UpdateThings(things) end,draw=function(self) local things=GetAllChildren(self) DrawThings(things) end,getChildren=function(self) return self.Children end} +_GuiPro.Clips={} +_GuiPro.rotate=0 +setmetatable(_GuiPro, gui) +function gui:LoadInterface(file) + local add=".int" + if string.find(file,".",1,true) then add="" end + if love.filesystem.exists(file..add) then + a,b=pcall(love.filesystem.load(file..add)) + if a then + print("Loaded: "..file) + else + print("Error loading file: "..file) + print(a,b) + end + else + print("File does not exist!") + return false + end +end +function gui.LoadAll(dir) + files=love.filesystem.getDirectoryItems(dir) + for i=1,#files do + if string.sub(files[i],-4)==".int" then + gui:LoadInterface(dir.."/"..files[i]) + end + end +end + +function gui:Clickable() + local x,y,w,h=love.graphics.getScissor() + local mx=love.mouse.getX() + local my=love.mouse.getY() + if _GuiPro.HasStencel then + local obj=_GuiPro.StencelHolder + if self:isDescendant(obj) then + return math.sqrt((mx-obj.x)^2+(my-obj.y)^2)<=(obj.offset.size.x or 0) + end + end + if not(x) then + return true + end + return not(mx>x+w or mxy+h or myx+w or mxy+h or my self.x and x < self.x+self.width and y > self.y and y < self.y+self.height and self:TClickable(x,y) and self:eventable()) + end + end + self.id=-1 +end +multi:newTask(function() -- A bit of post-loading haha + gui.touchpressed=multi:newConnection() + gui.touchreleased=multi:newConnection() + gui.touchmoved=multi:newConnection() + love.touchpressed=Library.convert(love.touchpressed or function() end) + love.touchreleased=Library.convert(love.touchreleased or function() end) + love.touchmoved=Library.convert(love.touchmoved or function() end) + love.touchpressed:inject(function(id, x, y, dx, dy, pressure) gui.touchpressed:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) + love.touchreleased:inject(function(id, x, y, dx, dy, pressure) gui.touchreleased:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) + love.touchmoved:inject(function(id, x, y, dx, dy, pressure) gui.touchmoved:Fire(id, x, y, dx, dy, pressure) return {id, x, y, dx, dy, pressure} end,1) + _GuiPro.TouchReady=true + _GuiPro.TouchRegister={} + gui.touchpressed:connect(function(id, x, y, dx, dy, pressure) + for i,v in pairs(_GuiPro.TouchRegister) do + if #v.tid==0 then + if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then + v:addTID(id) + v.touchcount=1 + for i=1,#v.ToFuncP do + v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + elseif not(v:hasTID(id)) then + if (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then + v:addTID(id) + v.touchcount=v.touchcount+1 + for i=1,#v.ToFuncP do + v.ToFuncP[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + end + end + end) + gui.touchreleased:connect(function(id, x, y, dx, dy, pressure) + for i,v in pairs(_GuiPro.TouchRegister) do + if v:hasTID(id) then + v:removeTID(id) + for i=1,#v.ToFuncR do + v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + end + end) + gui.touchmoved:connect(function(id, x, y, dx, dy, pressure) + for i,v in pairs(_GuiPro.TouchRegister) do + if v:hasTID(id) and (x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable()) then + for i=1,#v.ToFuncM do + v.ToFuncM[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + elseif v:hasTID(id) and not((x > v.x and x < v.x+v.width and y > v.y and y < v.y+v.height and v:TClickable(x,y) and v:eventable())) then + v:removeTID(id) + for i=1,#v.ToFuncR do + v.ToFuncR[i](v,id, x-v.x, y-v.y, dx, dy or 0, pressure or 1) + end + end + end + end) +end) +-- now that that is done lets set up some more post loading checks +_GuiPro.int=multi:newProcess() +_GuiPro.int:Start() +_GuiPro.int:setJobSpeed(.001) +_GuiPro.EXACT=0 +_GuiPro.LAX=.01 +_GuiPro.LAZY=.05 +-- now lets define the reg function +function gui.Compare(a,b,v,tp) + if tp==">" then + if (a+v>b or a-v>b) then + return true + end + elseif tp=="<" then + if (a+v=" then + if (a+v>=b or a-v>=b) then + return true + end + elseif tp=="==" then -- this one is gonna be tricky + if (a>=b-v and a<=b+v) or (b>=a-v and b<=a+v) then + return true + end + end + return false +end +function gui:regesterTouch() + local obj=self + obj.ToFuncP={} + obj.ToFuncM={} + obj.ToFuncR={} + obj.To2Func={} + obj.ToDTFunc={} + obj.touchRendering =_GuiPro.EXACT -- exact(0), lax(), # + function obj:removeTID(id) + for i=1,#self.tid do + if self.tid[i]==id then + table.remove(self.tid,i) + self.touchcount=self.touchcount-1 + return + end + end + end + function obj:hasTID(id) + for i=1,#self.tid do + if self.tid[i]==id then + return true + end + end + return false + end + obj.txl1=0 + obj.tyl1=0 + obj.txl2=0 + obj.tyl2=0 + obj.LS=0 + obj:OnUpdate(function(self) + if self.touchcount==2 then + local x1,y1=love.touch.getPosition( self.tid[1] ) + local x2,y2=love.touch.getPosition( self.tid[2] ) + local CS=math.sqrt((x2-x1)^2+(y2-y1)^2) + if gui.Compare(CS,self.LS,self.touchRendering,">") then + for i=1,#self.To2Func do + self.To2Func[i](self,CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + end + elseif gui.Compare(CS,self.LS,self.touchRendering,"<") then + for i=1,#self.To2Func do + self.To2Func[i](self,-CS,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + end + elseif gui.Compare(CS,self.LS,self.touchRendering,"==") then + for i=1,#self.To2Func do + self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + end + end + -- if self.txl1~=x1 or self.txl2~=x2 or self.tyl1~=y1 or self.tyl2~=y2 then + -- for i=1,#self.To2Func do + -- self.To2Func[i](self,0,x1-self.x,y1-self.y,x2-self.x,y2-self.y) + -- end + -- end + self.LS=CS + self.txl1=x1 + self.txl2=x2 + self.tyl1=y1 + self.tyl2=y2 + end + end) + function obj:OnDoubleTap(func) + table.insert(self.ToDTFunc,func) + end + function obj:On2TouchMoved(func) + table.insert(self.To2Func,func) + end + function obj:addTID(id) + table.insert(self.tid,id) + end + function obj:OnTouchPressed(func) + table.insert(self.ToFuncP,func) -- event for touches + end + function obj:OnTouchReleased(func) -- event for touches + table.insert(self.ToFuncR,func) + end + function obj:OnTouchMoved(func) -- event for touches + table.insert(self.ToFuncM,func) + end + if _GuiPro.TouchReady then -- my sneaky test + print("Registred: "..tostring(obj)) + table.insert(_GuiPro.TouchRegister,obj) + else + print("Attempting to register: "..tostring(obj)) + _GuiPro.int:newJob(function() table.insert(_GuiPro.TouchRegister,obj) end) -- a sneaky way to ensure that your object gets registered eventually, even if you call the method before the touch patch was activated. + end +end + +function UpdateThings(items) + for i=#items,1,-1 do + if items[i]:LClicked() then + for g=1,#items[i].funcs do + items[i].funcs[g]("l",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + elseif items[i]:RClicked() then + for g=1,#items[i].funcs do + items[i].funcs[g]("r",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + elseif items[i]:MClicked() then + for g=1,#items[i].funcs do + items[i].funcs[g]("m",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + end + if not(items[i]:LClicked()) and items[i].LRE then + for g=1,#items[i].funcs2 do + items[i].funcs2[g]("l",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + elseif not(items[i]:RClicked()) and items[i].RRE then + for g=1,#items[i].funcs2 do + items[i].funcs2[g]("r",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + elseif not(items[i]:MClicked()) and items[i].MRE then + for g=1,#items[i].funcs2 do + items[i].funcs2[g]("m",items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + end + if items[i]:Hovering() and items[i].HE==false then + for g=1,#items[i].funcs3 do + items[i].funcs3[g](items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + elseif not(items[i]:Hovering()) and items[i].HE==true then + for g=1,#items[i].funcs4 do + items[i].funcs4[g](items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + elseif items[i]:Hovering() then + for g=1,#items[i].func9 do + items[i].func9[g](items[i],love.mouse.getX()-items[i].x,love.mouse.getY()-items[i].y) + end + end + for g=1,#items[i].funcs5 do + items[i].funcs5[g](items[i]) + end + end +end +function GetAllChildren(Object) + local Stuff = {} + function Seek(Items) + for i=1,#Items do + if Items[i].Visible==true then + table.insert(Stuff,Items[i]) + local NItems = Items[i]:getChildren() + if NItems ~= nil then + Seek(NItems) + end + end + end + end + local Objs = Object:getChildren() + for i=1,#Objs do + if Objs[i].Visible==true then + table.insert(Stuff,Objs[i]) + local Items = Objs[i]:getChildren() + if Items ~= nil then + Seek(Items) + end + end + end + return Stuff +end +function GetAllChildren2(Object) + local Stuff = {} + function Seek(Items) + for i=1,#Items do + table.insert(Stuff,Items[i]) + 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]) + local Items = Objs[i]:getChildren() + if Items ~= nil then + Seek(Items) + end + end + return Stuff +end +function gui:getTile(i,x,y,w,h)-- returns imagedata + if type(i)=="string" then + i=love.graphics.newImage(i) + elseif type(i)=="userdata" then + -- do nothing + elseif string.find(self.Type,"Image",1,true) then + local i,x,y,w,h=self.Image,i,x,y,w + else + error("getTile invalid args!!! Usage: ImageElement:getTile(x,y,w,h) or gui:getTile(imagedata,x,y,w,h)") + end + local iw,ih=i:getDimensions() + local id,_id=i:getData(),love.image.newImageData(w,h) + for _x=x,w+x-1 do + for _y=y,h+y-1 do + -- + _id:setPixel(_x-x,_y-y,id:getPixel(_x,_y)) + end + end + return love.graphics.newImage(_id) +end +function gui:newAnim(file,delay, x, y, w, h, sx ,sy ,sw ,sh) + local x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) + c.Visibility=0 + c.ImageVisibility=1 + c.delay=delay or .05 + c.files={} + c.AnimStart={} + c.AnimEnd={} + local _files=alphanumsort(love.filesystem.getDirectoryItems(file)) + for i=1,#_files do + if string.sub(_files[i],-1,-1)~="b" then + table.insert(c.files,love.graphics.newImage(file.."/".._files[i])) + end + end + c.step=multi:newTStep(1,#c.files,1,c.delay) + c.step.parent=c + c.rotation=0 + c.step:OnStart(function(step) + for i=1,#step.parent.AnimStart do + step.parent.AnimStart[i](step.parent) + end + end) + c.step:OnStep(function(pos,step) + step.parent:SetImage(step.parent.files[pos]) + end) + c.step:OnEnd(function(step) + for i=1,#step.parent.AnimEnd do + step.parent.AnimEnd[i](step.parent) + end + end) + function c:OnAnimStart(func) + table.insert(self.AnimStart,func) + end + function c:OnAnimEnd(func) + table.insert(self.AnimEnd,func) + end + function c:Pause() + self.step:Pause() + end + function c:Resume() + self.step:Resume() + end + function c:Reset() + self.step.pos=1 + end + function c:getFrames() + return #self.files + end + function c:getFrame() + return self.step.pos + end + function c:setFrame(n) + return self:SetImage(self.files[n]) + end + return c +end +function gui:newAnimFromData(data,delay, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageAnimation","FromFile", x, y, w, h, sx ,sy ,sw ,sh) + c.Visibility=0 + c.ImageVisibility=1 + c.delay=delay or .05 + c.files=data + c.AnimStart={} + c.AnimEnd={} + c:SetImage(c.files[1]) + c.step=multi:newTStep(1,#c.files,1,c.delay) + c.step.parent=c + c.rotation=0 + c.step:OnStart(function(step) + for i=1,#step.parent.AnimStart do + step.parent.AnimStart[i](step.parent) + end + end) + c.step:OnStep(function(pos,step) + step.parent:SetImage(step.parent.files[pos]) + end) + c.step:OnEnd(function(step) + for i=1,#step.parent.AnimEnd do + step.parent.AnimEnd[i](step.parent) + end + end) + function c:OnAnimStart(func) + table.insert(self.AnimStart,func) + end + function c:OnAnimEnd(func) + table.insert(self.AnimEnd,func) + end + function c:Pause() + self.step:Pause() + end + function c:Resume() + self.step:Resume() + end + function c:Reset() + self.step.pos=1 + end + function c:getFrames() + return #self.files + end + function c:getFrame() + return self.step.pos + end + function c:setFrame(n) + return self:SetImage(self.files[n]) + end + return c +end +function gui:newAnimFromTiles(file,xd,yd,delay, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(file, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageAnimation",file, x, y, w, h, sx ,sy ,sw ,sh) + local im=love.graphics.newImage(file) + local _x,_y=im:getDimensions() + c.Visibility=0 + c.ImageVisibility=1 + c.delay=delay or .05 + c.files={} + c.AnimStart={} + c.AnimEnd={} + for i=0,_y/yd-1 do + for j=0,_x/xd-1 do + table.insert(c.files,gui:getTile(im,j*xd,i*yd,xd,yd)) + end + end + c:SetImage(c.files[1]) + c.step=multi:newTStep(1,#c.files,1,c.delay) + c.step.parent=c + c.rotation=0 + c.step:OnStart(function(step) + for i=1,#step.parent.AnimStart do + step.parent.AnimStart[i](step.parent) + end + end) + c.step:OnStep(function(pos,step) + step.parent:SetImage(step.parent.files[pos]) + end) + c.step:OnEnd(function(step) + for i=1,#step.parent.AnimEnd do + step.parent.AnimEnd[i](step.parent) + end + end) + function c:OnAnimStart(func) + table.insert(self.AnimStart,func) + end + function c:OnAnimEnd(func) + table.insert(self.AnimEnd,func) + end + function c:Pause() + self.step:Pause() + end + function c:Resume() + self.step:Resume() + end + function c:Reset() + self.step.pos=1 + end + function c:getFrames() + return #self.files + end + function c:getFrame() + return self.step.pos + end + function c:setFrame(n) + return self:SetImage(self.files[n]) + end + return c +end +function gui:newFullImageLabel(i,name) + return self:newImageLabel(i,name,0,0,0,0,0,0,1,1) +end +function gui:newImageButton(i,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("ImageButton",name, x, y, w, h, sx ,sy ,sw ,sh) + if type(i)=="string" then + c.Image=love.graphics.newImage(i) + else + c.Image=i + end + c.Visibility=0 + c.ImageVisibility=1 + c.rotation=0 + if c.Image~=nil then + c.ImageHeigth=c.Image:getHeight() + c.ImageHeight=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + end + c:OnEnter(function() + love.mouse.setCursor(_GuiPro.CursorH) + end) + c:OnExit(function() + love.mouse.setCursor(_GuiPro.CursorN) + end) + return c +end +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 +function gui:newVideo(name,i,x,y,w,h,sx,sy,sw,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("Video",name, x, y, w, h, sx ,sy ,sw ,sh) + if type(i)=="string" then + c.Video=love.graphics.newVideo(i) + else + c.Video=i + end + c.Visibility=0 + c.VideoVisibility=1 + c.rotation=0 + if c.Video~=nil then + c.VideoHeigth=c.Video:getHeight() + c.VideoWidth=c.Video:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.VideoWidth,c.VideoHeigth) + end + c.funcV={} + function c:Play() + self.handStart=true + self.Video:play() + end + function c:Pause() + self.Video:pause() + end + c.Resume=c.Play + function c:Stop() + self.handStart=false + self:Pause() + self:Rewind() + for i=1,# self.funcV do + self.funcV[i](self) + end + end + function c:OnVideoStopped(func) + table.insert(self.funcV,func) + end + function c:Rewind() + self.Video:rewind() + end + function c:Restart() + self:Rewind() + self:Play() + end + function c:Seek(o) + self.Video:seek(o) + end + function c:Tell() + self.Video:tell() + end + function c:SetFilter(min, mag, anisotropy) + self.Video:setFilter(min, mag, anisotropy) + end + function c:IsPlaying() + return self.Video:isPlaying() + end + c:OnUpdate(function(self) + if self.Video:isPlaying()==false and self.handStart == true then + self:Stop() + end + end) + return c +end +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 +function gui:UpdateImage() + self.ImageHeigth=self.Image:getHeight() + self.ImageWidth=self.Image:getWidth() + self.Quad=love.graphics.newQuad(0,0,self.width,self.height,self.ImageWidth,self.ImageHeigth) +end +function gui:newDropFrame(name,x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("DropFrame",name, x, y, w, h, sx ,sy ,sw ,sh) + c.WasBeingDragged=false + c.IsBeingDragged=false + c.Draggable=false + c.funcD={} + function c:GetDroppedItems() + local t=self:getChildren() + local tab={} + for i=1,#t do + if t[i].Type=="TextImageButtonFrameDrag" then + table.insert(tab,t[i]) + end + end + return tab + end + function c:OnDropped(func) + table.insert(self.funcD,func) + end + c:OnUpdate(function(self) + if _GuiPro.DragItem then + if _GuiPro.DragItem.Type=="TextImageButtonFrameDrag" and love.mouse.isDown(_GuiPro.DragItem.dragbut or "m")==false and self:IsHovering() then + local t=_GuiPro.DragItem + _GuiPro.DragItem={} + for i=1,#t.funcD do + t.funcD[i](self,t) + end + for i=1,#self.funcD do + self.funcD[i](self,t) + end + _GuiPro.hasDrag=false + end + end + end) + return c +end +function gui:newFrame(name,x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("Frame",name, x, y, w, h, sx ,sy ,sw ,sh) + c.WasBeingDragged=false + c.IsBeingDragged=false + c.Draggable=false + return c +end +function gui:newFullFrame(name) + name=name or "" + return self:newFrame(name,0,0,0,0,0,0,1,1) +end + +function gui:newTabFrame(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=gui:newFrame(name, x, y, w, h, sx ,sy ,sw ,sh) + c.tabheight=20 + c.Holder=c:newFrame("Holder",0,c.tabheight,0,0,0,0,1,1) + c.TabHolder=c:newFrame("TabHolder",0,0,0,c.tabheight,0,0,1) + function c:setTabHeight(n) + self.tabheight=n + self.Holder:SetDualDim(0,-self.tabheight,0,0,0,0,1,1) + end + function c:addTab(name,colorT,colorH) + if colorT and not(colorH) then + colorH=colorT + end + local tab=self.TabHolder:newTextButton(name,name,0,0,0,0,0,0,0,1) + tab.Tween=-3 + if colorT then + tab.Color=colorT + end + local holder=self.Holder:newFrame(name,0,0,0,0,0,0,1,1) + if colorH then + holder.Color=colorH + end + tab.frame=holder + tab:OnReleased(function(b,self) + if b=="l" then + local tt=self.Parent:getChildren() + local th=self.Parent.Parent.Holder:getChildren() + for i=1,#th do + th[i].Visible=false + end + for i=1,#tt do + tt[i].frame.Visible=false + tt[i].BorderSize=1 + end + self.BorderSize=0 + self.frame.Visible=true + end + end) + local tt=self.TabHolder:getChildren() + for i=1,#tt do + tt[i].frame.Visible=false + tt[i].BorderSize=1 + end + tab.frame.Visible=true + tab.BorderSize=0 + return tab,holder + end + c:OnUpdate(function(self) + local th=self.TabHolder:getChildren() + local l=self.width/#th + for i=1,#th do + th[i]:SetDualDim(l*(i-1),0,l) + end + if #th==0 then + self:Destroy() + end + end) + return c +end +function gui:newDragItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextImageButtonFrameDrag",name, x, y, w, h, sx ,sy ,sw ,sh) + c.WasBeingDragged=false + c.IsBeingDragged=false + c.Draggable=true + c.funcD={} + if type(i)=="string" then + c.Image=love.graphics.newImage(i) + c.ImageVisibility=1 + c.ImageHeigth=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + elseif type(i)=="image" then + c.Image=i + c.ImageVisibility=1 + c.ImageHeigth=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + end + c:OnDragStart(function(self,x,y) + if _GuiPro.hasDrag==false then + self:setParent(_GuiPro) + self:SetDualDim(x,y) + self:TopStack() + end + end) + c.rotation=0 + c.Tween=0 + c.XTween=0 + c.text = t + c.AutoScaleText=false + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.TextVisibility=1 + c.TextColor = {0, 0, 0} + function c:OnDropped(func) + table.insert(self.funcD,func) + end + c:OnUpdate(function(self) + if love.mouse.isDown("m" or self.dragbut)==false and self==_GuiPro.DragItem and self.hovering==false then + _GuiPro.DragItem={} + for i=1,#self.func7 do + self.func7[i](self,(love.mouse.getX())-self.width/2,(love.mouse.getY())-self.height/2) + end + end + end) + return c +end +function gui:newItem(t,i,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextImageButtonFrame",name, x, y, w, h, sx ,sy ,sw ,sh) + if type(i)=="string" then + c.Image=love.graphics.newImage(i) + else + c.Image=i + end + c.rotation=0 + c.ImageVisibility=1 + c.Draggable=false + if c.Image~=nil then + c.ImageHeigth=c.Image:getHeight() + c.ImageWidth=c.Image:getWidth() + c.Quad=love.graphics.newQuad(0,0,w,h,c.ImageWidth,c.ImageHeigth) + end + c.Tween=0 + c.XTween=0 + c.text = t + c.AutoScaleText=false + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) + c.TextColor = {0, 0, 0} + return c +end +function gui:addDominance() + _GuiPro.TopHovered=self +end +function gui:addHotKey(key) + local temp=self:newFrame(0,0,0,0) + temp.Visible=false + temp:setHotKey(key) + return temp +end +function gui:AdvTextBox(txt,x,y,w,h,sx,sy,sw,sh) + name="AdvTextBox" + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("AdvTextBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) + c.Draggable=true + c.dragbut="r" + c.BorderSize=0 + c:ApplyGradient{Color.Blue,Color.sexy_purple} + c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple + c.funcO={} + c.funcX={} + c:OnDragStart(function(self) + self:TopStack() + end) + --local temp = c:newTextButton("X","Close",-25,5,20,20,1) + --temp.Tween=-5 + --temp.XTween=-2 + --temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) + --temp.Color=Color.Red + c.tLink=c:newTextBox("puttext","TextBox",5,h-95,-40,30,0,1,1,1) + c.tLink.Color=Color.light_gray + c.tLink.ClearOnFocus=true + c.tLink:OnFocus(function(self) self.ClearOnFocus=false end) + local temp=c:newTextButton("OK","Ok",-35,h-65,30,30,1,1) + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent,self.Parent.tLink.text) end end) + temp.Color=Color.Green + temp.XTween=-2 + local temp=c:newTextButton("X","Cancel",-35,h-95,30,30,1,1) + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent,self.Parent.tLink.text) end end) + temp.Color=Color.Red + temp.XTween=-2 + function c:Close() + self.Visible=false + end + function c:Open() + self.Visible=true + end + function c:OnOk(func) + table.insert(self.funcO,func) + end + function c:OnX(func) + table.insert(self.funcX,func) + end + return c +end +function alphanumsort(o) + local function padnum(d) local dec, n = string.match(d, "(%.?)0*(.+)") + return #dec > 0 and ("%.12f"):format(d) or ("%s%03d%s"):format(dec, #n, n) + end + table.sort(o, function(a,b) return tostring(a):gsub("%.?%d+",padnum)..("%3d"):format(#b)< tostring(b):gsub("%.?%d+",padnum)..("%3d"):format(#a) end) + return o +end +function gui:anchorRight(n) + self:SetDualDim(-(self.width+n),nil,nil,nil,1) +end +function _GuiPro.gradient(colors) + local direction = colors.direction or "horizontal" + colors.direction=nil + trans = colors.trans or 255 + trans=math.floor(trans) + if direction == "horizontal" then + direction = true + elseif direction == "vertical" then + direction = false + else + error("Invalid direction '" .. tostring(direction) "' for gradient. Horizontal or vertical expected.") + end + local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1) + for __i, color in ipairs(colors) do + local x, y + if direction then + x, y = 0, __i - 1 + else + x, y = __i - 1, 0 + end + result:setPixel(x, y, color[1], color[2], color[3], trans) + end + result = love.graphics.newImage(result) + result:setFilter('linear', 'linear') + return result +end +function _GuiPro.drawinrect(img, x, y, w, h, r, ox, oy, kx, ky) + love.graphics.draw(img, x, y, r, w / img:getWidth(), h / img:getHeight(), ox, oy, kx, ky) +end +function gui:ApplyGradient(rules) + self.Image=nil + self.Type=self.Type.."w/GradImage" + self.rotation=0 + self.ImageVisibility=rules.visibility or 1 + self:SetImage(_GuiPro.gradient(rules)) +end +function gui:BottomStack() + childs=self.Parent:getChildren() + for i=1,#childs do + if childs[i]==self then + table.remove(self.Parent.Children,i) + table.insert(self.Parent.Children,1,self) + break + end + end +end +function gui:Center() + local x,y=self:getFullSize() + self:SetDualDim(-math.floor(x/2),-math.floor(y/2),nil,nil,.5,.5) +end +function gui:centerX() + self:SetDualDim(-(self.width/2),nil,nil,nil,.5) +end +function gui:centerY() + self:SetDualDim(nil,-(self.height/2),nil,nil,nil,.5) +end +function gui:Destroy() + check=self.Parent:getChildren() + local cc=0 + for cc=1,#check do + if check[cc]==self then + table.remove(self.Parent.Children,cc) + end + end +end +function gui:disrespectHierarchy() + _GuiPro.Hierarchy=false +end +function gui:GetAllChildren() + local Stuff = {} + function Seek(Items) + for i=1,#Items do + if Items[i].Visible==true then + table.insert(Stuff,Items[i]) + local NItems = Items[i]:getChildren() + if NItems ~= nil then + Seek(NItems) + end + end + end + end + local Objs = self:getChildren() + for i=1,#Objs do + if Objs[i].Visible==true then + table.insert(Stuff,Objs[i]) + local Items = Objs[i]:getChildren() + if Items ~= nil then + Seek(Items) + end + end + end + return Stuff +end +function gui:GetChild(name) + return self.Children[name] or self +end +function gui:getChildren() + return self.Children +end +function gui:getColor(cindex) + return Color[cindex] +end +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 +function gui:getHighest() + if self.Children[#self.Children]~=nil then + return self.Children[#self.Children] + end +end +function gui:getLowest() + if self.Children[1]~=nil then + return self.Children[1] + end +end +function InGrid(i,x,y,s) + return math.floor((i-1)/x)*s,(i-1)*s-(math.floor((i-1)/y)*(s*x)) +end +function InGridX(i,w,h,xs,ys) + local xc,yc=math.floor(w/xs),math.floor(h/ys) + local xi,yi=(i-1)%xc,math.floor((i-1)/xc) + return xi*xs,yi*ys +end +function InGridY(i,w,h,xs,ys) + local xc,yc=math.floor(w/xs),math.floor(h/ys) + local xi,yi=math.floor((i-1)/yc),(i-1)%yc + return xi*xs,yi*ys +end +function gui:isDescendant(obj) + local things=obj:GetAllChildren() + for i=1,#things do + if things[i]==self then + return true + end + end + return false +end +function gui:isHighest() + return (self==self.Parent:getHighest()) +end +function gui:IsHovering() + return (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height) +end +function gui:isLowest() + return (self==self.Parent:getLowest()) +end +function gui.massMutate(t,...) + local mut={...} + for i=1,#mut do + mut[i]:Mutate(t) + end +end +function gui:Move(x,y) + self.offset.pos.x=self.offset.pos.x+x + self.offset.pos.y=self.offset.pos.y+y +end +if love.filesystem.exists("CheckBoxes.png") then + _GuiPro.UC=gui:getTile("CheckBoxes.png",0,0,16,16) + _GuiPro.C=gui:getTile("CheckBoxes.png",16,0,16,16) + _GuiPro.UCH=gui:getTile("CheckBoxes.png",0,16,16,16) + _GuiPro.CH=gui:getTile("CheckBoxes.png",16,16,16,16) +end +function gui:newCheckBox(name,x,y) + if not(_GuiPro.UC) then error("CheckBoxes.png not found! Cannot currently use checkbox without the data") end + if type(name)~="String" then + x,y,name=name,x,"CheckBox" + end + local c=self:newImageLabel(_GuiPro.UC,name, x, y, 16,16) + c.Visibility=0 + c.check=false + c:OnEnter(function(self) + if self.check then + self:SetImage(_GuiPro.CH) + else + self:SetImage(_GuiPro.UCH) + end + end) + function c:isChecked() + return self.check + end + c:OnExit(function(self) + if self.check then + self:SetImage(_GuiPro.C) + else + self:SetImage(_GuiPro.UC) + end + end) + c:OnReleased(function(b,self) + self.check=not(self.check) + if self.check then + self:SetImage(_GuiPro.CH) + else + self:SetImage(_GuiPro.UCH) + end + end) + return c +end +function gui:newMessageBox(txt,x,y,w,h,sx,sy,sw,sh) + name="MessageBox" + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("MessageBoxFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) + c.Draggable=true + c.dragbut="r" + c:ApplyGradient{Color.Blue,Color.sexy_purple} + c.BorderSize=0 + c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple + c.funcO={} + c.funcX={} + c:OnDragStart(function(self) + self:TopStack() + end) + local temp = c:newTextButton("X","Close",-25,5,20,20,1) + temp.Tween=-5 + temp.XTween=-2 + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) + temp.Color=Color.Red + local temp=c:newTextButton("OK","Ok",0,h-65,0,30,.25,1,.5) + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcO do self.Parent.funcO[i](self.Parent) end end) + temp.Color=Color.Green + function c:Close() + self.Visible=false + end + function c:Open() + self.Visible=true + end + function c:OnOk(func) + table.insert(self.funcO,func) + end + function c:OnX(func) + table.insert(self.funcX,func) + end + return c +end +function gui:newPart(x, y,w ,h , sx ,sy ,sw ,sh) + local c = {} + setmetatable(c, gui) + if self==gui then + c.Parent=_GuiPro + else + c.Parent=self + end + c.funcs={} + c.funcs2={} + c.funcs3={} + c.funcs4={} + c.funcs5={} + c.func6={} + c.func7={} + c.func8={} + c.func9={} + c.func10={} + c.form="rectangle" + c.Color = {255, 255, 255} + c.scale={} + c.scale.size={} + c.scale.size.x=sw or 0 + c.scale.size.y=sh or 0 + c.offset={} + c.offset.size={} + c.offset.size.x=w or 0 + c.offset.size.y=h or 0 + c.scale.pos={} + c.scale.pos.x=sx or 0 + c.scale.pos.y=sy or 0 + c.offset.pos={} + c.offset.pos.x=x or 0 + c.offset.pos.y=y or 0 + c.VIS=true + c.Visible=true + c.Visibility=1 + c.BorderColor={0,0,0} + c.BorderSize=0 + c.Type="Part" + c.Name="GuiPart" + _GuiPro.count=_GuiPro.count+1 + c.x=(c.Parent.width*c.scale.pos.x)+c.offset.pos.x+c.Parent.x + c.y=(c.Parent.height*c.scale.pos.y)+c.offset.pos.y+c.Parent.y + c.width=(c.Parent.width*c.scale.size.x)+c.offset.size.x + c.height=(c.Parent.height*c.scale.size.y)+c.offset.size.y + table.insert(c.Parent.Children,c) + return c +end +function gui:newProgressBar(txt,x,y,w,h,sx,sy,sw,sh) + name="newProgressBar" + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("newProgressBarFrame",name, x, y, w, 30, sx ,sy ,sw ,sh) + c.Draggable=true + c.dragbut="r" + c.BorderSize=0 + c:ApplyGradient{Color.Blue,Color.sexy_purple} + c:newTextLabel(txt,"Holder",0,0,0,h-30,0,1,1,0).Color=Color.sexy_purple + c.funcO={} + c.funcX={} + c:OnDragStart(function(self) + self:TopStack() + end) + local temp = c:newTextButton("X","Close",-25,5,20,20,1) + temp.Tween=-5 + temp.XTween=-2 + temp:OnReleased(function(b,self) for i=1,#self.Parent.funcX do self.Parent.funcX[i](self.Parent) end end) + temp.Color=Color.Red + c.BarBG=c:newTextButton("",5,h-65,-10,30,0,1,1) + c.BarBG:ApplyGradient{Color.Red,Color.light_red} + c.Bar=c.BarBG:newTextLabel("",0,0,0,0,0,0,0,1) + c.Bar:ApplyGradient{Color.Green,Color.light_green} + c.BarDisp=c.BarBG:newTextLabel("0%","0%",0,0,0,0,0,0,1,1) + c.BarDisp.Visibility=0 + c.BarDisp.Link=c.Bar + c.BarDisp:OnUpdate(function(self) + self.text=self.Link.scale.size.x*100 .."%" + end) + c.Func1={} + function c:On100(func) + table.insert(self.Func1,func) + end + c:OnUpdate(function(self) + if self.Bar.scale.size.x*100>=100 then + for P=1,#self.Func1 do + self.Func1[P](self) + end + end + end) + function c:SetPercentage(n) + self.Bar:SetDualDim(0,0,0,0,0,0,n/100,1) + end + return c +end +function gui:newScrollBar(color1,color2) + local scrollbar=self:newFrame(-20,0,20,0,1,0,0,1) + scrollbar.funcS={} + scrollbar.Color=color1 or Color.saddle_brown + scrollbar:OnClicked(function(b,self,x,y) + love.mouse.setX(self.x+10) + if y>=10 and y<=self.height-10 then + self.mover:SetDualDim(0,y-10) + end + if y<10 then + love.mouse.setY(10+self.y) + end + if y>self.height-10 then + love.mouse.setY((self.height-10)+self.y) + end + for i=1,#self.funcS do + self.funcS[i](self,self:getPosition()) + end + end) + scrollbar:OnEnter(function(self) + self:addDominance() + end) + scrollbar:OnExit(function(self) + self:removeDominance() + end) + scrollbar.mover=scrollbar:newTextButton("","",0,0,20,20) + scrollbar.mover.Color=color2 or Color.light_brown + function scrollbar:getPosition() + return ((self.mover.offset.pos.y)/(self.height-20))*100 + end + function scrollbar:setPosition(n) + print((self.height-20),n) + self.mover.offset.pos.y=((self.height-20)/(100/n)) + for i=1,#self.funcS do + self.funcS[i](self,self:getPosition()) + end + end + function scrollbar:OnScroll(func) + table.insert(self.funcS,func) + end + return scrollbar +end +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 +function gui:destroyAllChildren() + local c=self.Children + for i=1,#c do + c[i]:Destroy() + end +end +function gui:removeDominance() + _GuiPro.TopHovered=nil +end +function gui:respectHierarchy() + _GuiPro.Hierarchy=true +end +function gui.round(num, idp) + local mult = 10^(idp or 0) + return math.floor(num * mult + 0.5) / mult +end +function gui.setBG(i) + gui.ff:SetImage(i) +end +function gui:setColor(a,b,c) + if type(a)=="string" then + self.Color=Color[a] + elseif type(a)=="number" then + self.Color=Color.new(a,b,c) + end +end +function gui:setTextColor(a,b,c) + if type(a)=="string" then + self.TextColor=Color[a] + elseif type(a)=="number" then + self.TextColor=Color.new(a,b,c) + end +end +function gui:setDefualtFont(font) + _defaultfont = font +end +function gui:SetDualDim(x, y, w, h, sx ,sy ,sw ,sh) + if _GuiPro.DPI_ENABLED then + if x then + x=self.DPI*x + end + if y then + y=self.DPI*y + end + if w then + w=self.DPI*w + end + if h then + h=self.DPI*h + end + end + if sx then + self.scale.pos.x=sx + end + if sy then + self.scale.pos.y=sy + end + if x then + self.offset.pos.x=x + end + if y then + self.offset.pos.y=y + end + if sw then + self.scale.size.x=sw + end + if sh then + self.scale.size.y=sh + end + if w then + self.offset.size.x=w + end + if h then + self.offset.size.y=h + end + if self.Image then + self:SetImage(self.Image) + end +end +function gui:setDualDim(...) + self:SetDualDim(...) +end +function gui:setText(txt) + self.text=txt +end +function gui:getText(txt) + return self.text +end +_GuiPro.CursorN=love.mouse.getSystemCursor("arrow") +_GuiPro.CursorH=love.mouse.getSystemCursor("hand") +function gui:SetHand(img,x,y) + _GuiPro.CursorN=love.mouse.newCursor(img,x,y) +end +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 +function gui:SetHover(img,x,y) + _GuiPro.CursorH=love.mouse.newCursor(img,x,y) +end +function gui:SetName(name) + self.Parent.Children[name]=self + self.Name=name +end +function gui:setNewFont(FontSize) + self.Font=love.graphics.setNewFont(tonumber(FontSize)) +end +function gui:setParent(parent,name)-- Needs fixing!!! + local temp=self.Parent:getChildren() + for i=1,#temp do + if temp[i]==self then + table.remove(self.Parent.Children,i) + break + end + end + table.insert(parent.Children,self) + self.Parent=parent + if name then + self:SetName(name) + end +end +function gui:setVisiblity(val) + self.Visible=val + self.oV=val + doto=self:GetAllChildren() + if val==false then + for i=1,#doto do + doto[i].Visible=val + end + else + for i=1,#doto do + doto[i].Visible=doto[i].oV + end + end +end +function gui:TopStack() + childs=self.Parent:getChildren() + for i=1,#childs do + if childs[i]==self then + table.remove(self.Parent.Children,i) + table.insert(self.Parent.Children,self) + break + end + end +end +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) + 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 +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 +function gui:newTextLabel(t,name, x, y, w, h, sx ,sy ,sw ,sh) + x,y,w,h,sx,sy,sw,sh=filter(name, x, y, w, h, sx ,sy ,sw ,sh) + local c=self:newBase("TextLabel",name, x, y, w, h, sx ,sy ,sw ,sh) + c.Tween=0 + c.XTween=0 + c.FontHeight=_defaultfont:getHeight() + c.Font=_defaultfont + c.FontSize=15 + c.TextFormat="center" + c.text = t + c.AutoScaleText=false + c.TextVisibility=1 -- 0=invisible,1=solid (self.TextVisibility*254+1) + c.Color = {220, 220, 220} + c.TextColor = {0, 0, 0} + return c +end +function gui:AddDrawRuleB(rule) + if not(self.DrawRulesB) then self.DrawRulesB={} end + table.insert(self.DrawRulesB,rule) +end +function gui:AddDrawRuleE(rule) + if not(self.DrawRulesE) then self.DrawRulesE={} end + table.insert(self.DrawRulesE,rule) +end +function gui:draw() + if _GuiPro.rotate~=0 then + love.graphics.rotate(math.rad(_GuiPro.rotate)) + end + if self.FormFactor:lower()=="rectangle" then + self:drawR() + elseif self.FormFactor:lower()=="circle" then + self:drawC() + else + error("Unsupported FormFactor: "..self.FormFactor.."!") + end +end +function gui:drawC() + if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then + _GuiPro.DragItem={} + _GuiPro.hasDrag=false + end + if self.Visible==true and self.VIS==true then + local b=true + for i,v in pairs(_GuiPro.Clips) do + if self:isDescendant(v)==true then + b=false + end + end + if b then + love.graphics.setStencilTest( ) + _GuiPro.HasStencel=false + _GuiPro.StencelHolder=nil + end + local x,y,r,s=(self.offset.pos.x or 0)+self.Parent.x,(self.offset.pos.y or 0)+self.Parent.y,self.offset.size.x or 0,self.offset.size.y or 360 + if self.CC then + x,y=x+r,y+r + end + self.x,self.y=x,y + _GuiPro.circleStencilFunction = function() + love.graphics.circle("fill",x,y,r,s) + end + if math.sqrt((love.mouse.getX()-x)^2+(love.mouse.getY()-y)^2)<=r and self:eventable() and self:Clickable() and self.Active==true then + self.hovering=true + if love.mouse.isDown("l") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.lclicked=true + elseif love.mouse.isDown("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=true + elseif love.mouse.isDown("m") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.mclicked=true + else + if string.find(self.Type, "Button") and _GuiPro.hasDrag==false then + love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + self.hovering=false + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + if self.ClipDescendants==true then + _GuiPro.Clips[tostring(self)]=self + _GuiPro.HasStencel=true + _GuiPro.StencelHolder=self + love.graphics.stencil(_GuiPro.circleStencilFunction) + love.graphics.setStencilTest("notequal",0) + end + love.graphics.circle("fill",x,y,r,s) + love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.Visibility*254) + for b=0,self.BorderSize-1 do + love.graphics.circle("line",x,y,r+b,s) + end + if string.find(self.Type, "Text") then + if self.text~=nil then + if self.AutoScaleText then + self.FontSize=math.floor(self.height/1.45833) + end + love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) + love.graphics.setFont(self.Font) + love.graphics.printf(self.text, x-(r/2)+(self.XTween), y-(r/2)+self.Tween, r, self.TextFormat) + end + end + end +end +function gui:drawR() + if love.mouse.isDown("l")==false and love.mouse.isDown("m")==false and love.mouse.isDown("r")==false then + _GuiPro.DragItem={} + _GuiPro.hasDrag=false + end + if self.Visible==true and self.VIS==true then + local b=true + for i,v in pairs(_GuiPro.Clips) do + if self:isDescendant(v)==true then + b=false + end + end + if b==true then + love.graphics.setStencilTest() + love.graphics.setScissor() + end + self.x=(self.Parent.width*self.scale.pos.x)+self.offset.pos.x+self.Parent.x + self.y=(self.Parent.height*self.scale.pos.y)+self.offset.pos.y+self.Parent.y + self.width=(self.Parent.width*self.scale.size.x)+self.offset.size.x + self.height=(self.Parent.height*self.scale.size.y)+self.offset.size.y + if self.DrawRulesB then + for dr=1,#self.DrawRulesB do + self.DrawRulesB[dr](self) + end + end + if (love.mouse.getX() > self.x and love.mouse.getX() < self.x+self.width and love.mouse.getY() > self.y and love.mouse.getY() < self.y+self.height and self:Clickable() and self:eventable()) or self:touchable("r") and self.Active==true then + self.hovering=true + if love.mouse.isDown("l") or self:touchable("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.lclicked=true + elseif love.mouse.isDown("r") or self:touchable("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=true + elseif love.mouse.isDown("m") or self:touchable("r") and _GuiPro.hasDrag==false then + if string.find(self.Type, "Button") then + love.graphics.setColor(self.Color[1]-10, self.Color[2]-10, self.Color[3]-10,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.mclicked=true + else + if string.find(self.Type, "Button") or self:touchable("r") and _GuiPro.hasDrag==false then + love.graphics.setColor(self.Color[1]-5, self.Color[2]-5, self.Color[3]-5,self.Visibility*254) + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + end + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + else + love.graphics.setColor(self.Color[1],self.Color[2],self.Color[3],self.Visibility*254) + self.hovering=false + self.rclicked=false + self.lclicked=false + self.mclicked=false + end + if self.ClipDescendants==true then + _GuiPro.Clips[tostring(self)]=self + love.graphics.setScissor(self.x, self.y, self.width, self.height) + end + if self:hasRoundness() then + love.graphics.stencil(self.stfunc, "replace", 1) + love.graphics.setStencilTest("greater", 0) + end + love.graphics.rectangle("fill", self.x, self.y, self.width, self.height,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) + if string.find(self.Type, "Image") then + self:ImageRule() + end + if self.Type=="Video" then + self:VideoRule() + end + if self:hasRoundness() then + love.graphics.setStencilTest() + end + love.graphics.setColor(self.BorderColor[1], self.BorderColor[2], self.BorderColor[3],self.Visibility*254) + for b=0,self.BorderSize-1 do + love.graphics.rectangle("line", self.x-(b/2), self.y-(b/2), self.width+b, self.height+b,(self.rx or 1)*self.DPI,(self.ry or 1)*self.DPI,(self.segments or 1)*self.DPI) + end + if string.find(self.Type, "Text") then + if self.text~=nil then + if self.AutoScaleText then + self.FontSize=math.floor(self.height/1.45833) + end + love.graphics.setColor(self.TextColor[1],self.TextColor[2],self.TextColor[3],self.TextVisibility*254) + if self.Font==_defaultfont then + love.graphics.setFont(self.Font) + love.graphics.printf(self.text, self.x+2+(self.XTween*self.DPI)+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+(self.FontHeight/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) + else + if type(self.Font)=="string" then + self.Font=love.graphics.newFont(self.Font,self.FontSize) + self.FontHeight=self.Font:getHeight() + else + love.graphics.setFont(self.Font) + end + if type(self.FontSize)=="string" then + self.FontSize=tonumber(self.FontSize) + love.graphics.setNewFont(self.FontSize) + end + love.graphics.printf(self.text, self.x+2+((self.marginL or 0)*self.DPI or self.XTween*self.DPI), self.y+math.floor((self.FontHeight-self.FontSize)/2)+self.Tween*self.DPI, self.width+(0 or (self.marginR or 0)*self.DPI), self.TextFormat) + end + end + end + if self.DrawRulesE then + for dr=1,#self.DrawRulesE do + self.DrawRulesE[dr](self) + end + end + end +end + +gui:respectHierarchy() +_GuiPro.width,_GuiPro.height=love.graphics.getDimensions() +multi:newLoop():OnLoop(function() _GuiPro.width,_GuiPro.height=love.graphics.getDimensions() _GuiPro:update() end) +multi:onDraw(function() _GuiPro:draw() end) +gui.ff=gui:newFrame("",0,0,0,0,0,0,1,1) +gui.ff.Color={255,255,255} +gui.ff:OnUpdate(function(self) + self:BottomStack() +end) + diff --git a/client/bg.jpg b/client/bg.jpg new file mode 100644 index 0000000..3e0c2a3 Binary files /dev/null and b/client/bg.jpg differ diff --git a/client/chat.png b/client/chat.png new file mode 100644 index 0000000..a778e70 Binary files /dev/null and b/client/chat.png differ diff --git a/client/conf.lua b/client/conf.lua index 33f07f8..b19cef6 100644 --- a/client/conf.lua +++ b/client/conf.lua @@ -3,7 +3,7 @@ function love.conf(t) t.version = "0.10.1" -- The LOVE version this game was made for (string) t.console = true -- Attach a console (boolean, Windows only) - t.window.title = "game" -- The window title (string) + t.window.title = "Chat Client" -- The window title (string) t.window.icon = nil -- Filepath to an image to use as the window's icon (string) t.window.width = 400 -- The window width (number) t.window.height = 600 -- The window height (number) diff --git a/client/login.lua b/client/login.lua new file mode 100644 index 0000000..9f45ff8 --- /dev/null +++ b/client/login.lua @@ -0,0 +1,128 @@ +gui.LoadAll("Interface") +if not client then + -- handle client not being created! +else + client.OnUserLoggedIn:connect(function(self,data) + lMenu.bar.text="Logged In!" + lMenu.anim.Visible=false + end) + client.OnBadLogin:connect(function(self) + lMenu.bar.text="Pass/User incorrect!" + lMenu.anim.Visible=false + end) + client.OnUserAlreadyRegistered:connect(function(self,nick) + lMenu.bar.text="Username Taken!" + lMenu.anim.Visible=false + end) + client.OnUserAlreadyLoggedIn:connect(function(self) + lMenu.bar.text="Already logged in!" + lMenu.anim.Visible=false + end) + client.OnUserRegistered:connect(function(self,nick) + lMenu.bar.text="Register Success!" + lMenu.anim.Visible=false + end) + client.OnNoUserWithName:connect(function(self,nick) + lMenu.bar.text="No User with that name!" + lMenu.anim.Visible=false + end) + client.OnPasswordRequest:connect(function(self) + lMenu.bar.text="Password request sent!" + lMenu.anim.Visible=false + end) +end +--gui.setBG("fire.jpg") +--Login Windows +lMenu=gui:newFrame(0,0,200,100) +lMenu.ClipDescendants=true +lMenu:ApplyGradient{Color.Lighten(Color.Blue,.40),Color.Lighten(Color.Blue,.25),direction="vertical"} +lMenu.bar=lMenu:newTextLabel("","",0,0,0,20,0,0,1) +lMenu.bar:ApplyGradient{Color.Blue,Color.Darken(Color.Blue,.25)} +lMenu.bar.TextColor=Color.Lighten(Color.Red,.25) +lMenu.user=lMenu:newTextBox("username","username",5,25,190,20) +lMenu.pass=lMenu:newTextBox("password","password",5,50,190,20) +lMenu.email=lMenu:newTextBox("email","email",5,100,190,20) +lMenu.nick=lMenu:newTextBox("nick","nick",5,75,190,20) +lMenu.user.TextFormat="left" +lMenu.pass.TextFormat="left" +lMenu.email.TextFormat="left" +lMenu.nick.TextFormat="left" +lMenu.bar.TextFormat="left" +lMenu.bar.Tween=-3 +lMenu.user.Tween=-3 +lMenu.pass.Tween=-3 +lMenu.email.Tween=-3 +lMenu.nick.Tween=-3 +lMenu.user.ClearOnFocus=true +lMenu.pass.ClearOnFocus=true +lMenu.email.ClearOnFocus=true +lMenu.nick.ClearOnFocus=true +lMenu.user:ApplyGradient{Color.Darken(Color.Blue,.20),Color.Blue,direction="vertical"} +lMenu.pass:ApplyGradient{Color.Darken(Color.Blue,.20),Color.Blue,direction="vertical"} +lMenu.pass.hidden=true +lMenu.email:ApplyGradient{Color.Darken(Color.Blue,.20),Color.Blue,direction="vertical"} +lMenu.nick:ApplyGradient{Color.Darken(Color.Blue,.20),Color.Blue,direction="vertical"} +lMenu.hider=lMenu:newFrame("",1,-29,-2,28,0,1,1) +lMenu.hider.BorderSize=0 +lMenu.hider:ApplyGradient{Color.Lighten(Color.Blue,.40),Color.Lighten(Color.Blue,.25),direction="vertical"} +lMenu.Login=lMenu:newTextButton("Login","Login",5,-25,90,20,0,1) +lMenu.Register=lMenu:newTextButton("Register","Register",105,-25,90,20,0,1) +lMenu.Login.Tween=-3 +lMenu.Register.Tween=-3 +lMenu.Login.Color=Color.Green +lMenu.Register.Color=Color.Red +lMenu.step=multi:newTStep(1,80,1,.01) +lMenu.step:Pause() +lMenu.step.link=lMenu +lMenu.step:OnStep(function(pos,self) + if self.link.height<=150 then + self.link:SetDualDim(nil,nil,nil,self.link.height+1) + lMenu:centerY() + end + print(self.link.height) +end) +lMenu.step2=multi:newTStep(1,80,1,.01) +lMenu.step2:Pause() +lMenu.step2.link=lMenu +lMenu.step2:OnStep(function(pos,self) + if self.link.height>=101 then + self.link:SetDualDim(nil,nil,nil,self.link.height-1) + lMenu:centerY() + end + print(self.link.height) +end) +lMenu.Register:OnReleased(function(b,self) + if self.Parent.Login.text=="Back" then + print(lMenu.pass.ttext) + client:register(lMenu.user.text,lMenu.pass.ttext,lMenu.nick.text,{email=lMenu.email.text}) + lMenu.anim.Visible=true + else + self.Parent.Login.text="Back" + self.Parent.Login.Color=Color.saddle_brown + self.Parent.nick.text="nick" + self.Parent.step:Update() + end +end) +lMenu.Login:OnReleased(function(b,self) + if self.text=="Back" then + self.text="Login" + self.Color=Color.Green + self.Parent.step2:Update() + else + print(lMenu.pass.ttext) + client:logIn(lMenu.user.text,lMenu.pass.ttext) + lMenu.anim.Visible=true + end +end) +lMenu:centerX() +lMenu:centerY() +lMenu.anim=lMenu:newAnim("loading",.01, 0, 0, 41, 39) +lMenu.anim:OnAnimEnd(function(self) + self:Reset() + self:Resume() +end) +lMenu.anim:OnUpdate(function(self) + self:centerX() + self:centerY() +end) +lMenu.anim.Visible=false diff --git a/client/main.lua b/client/main.lua index 0db1de8..8811910 100644 --- a/client/main.lua +++ b/client/main.lua @@ -9,105 +9,415 @@ require("Libs/lovebind") -- binds my libraies to the love2d engine that i am usi require("GuiManager") -- allows the use of graphics in the program. require("net") -- Loads the networking library require("net.chatting") -client=net:newTCPClient("localhost",12345) -- Connects to the server +require("net.settings") -- loads the networking settings module +require("net.identity") -- loads the networking identity module +client=net:newTCPClient("69.113.201.7",12345) if type(client)=="boolean" then error("Please run the server file first!") end +client.OnUserLoggedIn:connect(function(self,data) + anim.Visible=false + login:Destroy() + MY_Name=data.nick + INIT() +end) +client.OnBadLogin:connect(function(self) + header.text="Login/Register (Pass/User incorrect!)" + anim.Visible=false +end) +client.OnUserAlreadyRegistered:connect(function(self,nick) + header.text="Login/Register (Username Taken!)" + anim.Visible=false +end) +client.OnUserRegistered:connect(function(self,nick) + header.text="Login/Register (Register Success!)" + anim.Visible=false +end) +client.OnNoUserWithName:connect(function(self,nick) + header.text="Login/Register (No User with that name!)" + anim.Visible=false +end) +client.OnPasswordRequest:connect(function(self) + header.text="Login/Register (Password request sent!)" + anim.Visible=false +end) +gui.ff.BorderSize=0 +login=gui:newFrame("Login",0,0,0,0,0,0,1,1) +login.Color=Color.Black +header=login:newTextLabel("Login/Register",0,10,0,20,0,0,1) +header.TextColor=Color.White +header:setNewFont(20) +header.Visibility=0 +username=login:newTextBox("","Username",11,52,-22,35,0,0,1) +t1=username:newTextLabel("Username",0,10,0,30,0,-1,1) +password=login:newTextBox("","Password",11,117,-22,35,0,0,1) +password.hidden=true +t2=password:newTextLabel("Password",0,10,0,30,0,-1,1) +Login=password:newTextButton("Login",0,10,100,30,0,1) +Login.Color=Color.Green +Register=Login:newTextButton("Register",10,0,100,30,1) +Register.Color=Color.Blue +nickname=login:newTextBox("","Nick",11,182,-22,35,0,0,1) +nickname.Visible=false +t3=nickname:newTextLabel("Nickname",0,10,0,30,0,-1,1) +email=login:newTextBox("","Email",11,247,-22,35,0,0,1) +email.Visible=false +t4=email:newTextLabel("Email",0,10,0,30,0,-1,1) +Back=email:newTextButton("Back",0,10,100,30,0,1) +Back.Color=Color.Red +DoRegister=Back:newTextButton("Register",10,0,100,30,1) +DoRegister.Color=Color.Blue +Login:OnReleased(function(b,self) + client:logIn(username.text,password.ttext) + anim.Visible=true +end) +Register:OnReleased(function(b,self) + Login.Visible=false + email.Visible=true + nickname.Visible=true +end) +Back:OnReleased(function(b,self) + Login.Visible=true + nickname.Visible=false + email.Visible=false +end) +DoRegister:OnReleased(function(b,self) + client:register(username.text,password.ttext,nickname.text,{email=email.text}) + Login.Visible=true + nickname.Visible=false + email.Visible=false + Register.Visible=false +end) +gui.massMutate({ + "setRoundness(10,10,360)", + Tween=1, + XTween=-3, +},Login,Register,Back,DoRegister) +gui.massMutate({ + Visibility=0, + TextFormat="left", + TextColor=Color.White, +},t1,t2,t3,t4) +gui.massMutate({ + "setRoundness(5,5,360)", + Visibility=1, + TextFormat="left", + Tween=4, + Color=Color.White, + XTween=4, +},username,password,nickname,email) client.OnChatRecieved(function(user,msg,isself) -- hook to grab chat data - Chat:AddChatBubble(user,msg,isself) + AG.holder:AddChatBubble(user,msg,isself) end) ---gui.enableAutoWindowScaling(true) -- allows mobile support. Not needed for PC use -nameframe=gui:newFrame("",0,0,200,100) -nameframe.Color=Color.Lighten(Color.Brown,.15) -nameframe:setRoundness(15,15,360) -nameframe:centerX() -nameframe:centerY() -namer=nameframe:newTextBox("Please enter a name to use!",0,0,180,30) -namer:centerX() -namer:centerY() -namer.Color=Color.tan -namer.ClearOnFocus=true -namer:setRoundness(5,5,360) -namer:OnEnter(function(self,txt) - MY_Name=txt:gsub("%s","_") - InitEngine() - nameframe:Destroy() - gui.ff:Destroy() -end) -gui.ff.C1=45 -gui.ff.C2=193 -gui.ff.C3=92 -gui.ff.C1m=-1 -gui.ff.C2m=1 -gui.ff.C3m=-1 -gui.ff.Color=Color.Blue -func=multi:newFunction(function(l,self) -- not needed just adds color change when chosing a name - l:hold(.05) - self.C1=self.C1+(({1,2,3})[math.random(1,3)]*self.C1m) - self.C2=self.C2+(({1,2,3})[math.random(1,3)]*self.C2m) - self.C3=self.C3+(({1,2,3})[math.random(1,3)]*self.C3m) - if self.C1>255 then self.C1=254 self.C1m=-1 end - if self.C2>255 then self.C2=254 self.C2m=-1 end - if self.C3>255 then self.C3=254 self.C3m=-1 end - if self.C1<0 then self.C1=1 self.C1m=1 end - if self.C2<0 then self.C2=1 self.C2m=1 end - if self.C3<0 then self.C3=1 self.C3m=1 end - self.Color=Color.new(self.C1,self.C2,self.C3) +client.OnPrivateChatRecieved(function(user,msg,USERID) -- hook to grab chat data + print("Matching: ",app[USERID],USERID) + local lastCFrame=CFrame + if app[USERID] then + CFrame=app[USERID] + --local c=AC.holder:getChildren() + --for i=1,#c do + -- c[i].Visible=false + --end + --CFrame.Visible=true + --local c=Chatting:getChildren() + --for i=1,#c do + -- c[i].Color=Color.Yellow + --end + --CFrame.button.Color=Color.Green + end + AC:PopulateChat(user,msg) + CFrame=lastCFrame -- reset cframe after stuff has been done end) function love.wheelmoved(x, y) -- handle scrolling - if mainapp then else return end - if y > 0 then - Chat.bubbles:SetDualDim(nil,Chat.bubbles.y+10) - elseif y < 0 then - Chat.bubbles:SetDualDim(nil,Chat.bubbles.y-50) - end - if Chat.bubbles.offset.pos.y>0 then - Chat.bubbles.offset.pos.y=0 + if CFrame==nil then return end + local c=CFrame.holder:getChildren() + if y > 0 then + CFrame.holder.offset.pos.y=CFrame.holder.offset.pos.y+10 + elseif y < 0 then + CFrame.holder.offset.pos.y=CFrame.holder.offset.pos.y-10 + end + if CFrame.holder.offset.pos.y>0 then + CFrame.holder.offset.pos.y=0 + elseif CFrame.holder.offset.pos.y<-(#c*35) then + CFrame.holder.offset.pos.y=-(#c*35) end - print(Chat.bubbles.offset.pos.y) end -gui.ff:OnUpdate(func) -function InitEngine() - mainapp=gui:newFrame("",0,0,0,0,0,0,1,1) -- creates a frame that takes up the enitre window - mainapp.Color=Color.Lighten(Color.Brown,.25) - mainapp.BorderSize=0 - mainapp.header=mainapp:newTextLabel("Now chatting as: "..MY_Name,1,-10,-2,30,0,0,1) -- creates the header for the app - mainapp.header:setRoundness(15,15,360) - mainapp.header.Tween=7 -- moves the text up by a factor of 3 pixels - mainapp.header.Color=Color.Lighten(Color.Blue,.25) -- Sets the Color of the header object to light blue - mainapp.chatFrame=mainapp:newFrame("",0,21,0,-20,0,0,1,1) -- creates the chat frame where users can see the text that is sent - mainapp.chatFrame.Color=Color.Lighten(Color.Brown,.25) -- Color stuff - mainapp.chatFrame.ClipDescendants=true - mainapp.chatFrame.bubbles=mainapp.chatFrame:newFrame("",0,0,0,0,0,0,1) - mainapp.chatFrame.bubbles.Visibility=0 - Chat=mainapp.chatFrame - Chat.lastBubbleHeight=0 - function Chat:AddChatBubble(user,txt,isself) +function INIT() + love.mouse.setCursor(love.mouse.getSystemCursor("arrow")) + app=gui:newImageLabel("bg.jpg",0,0,0,0,0,0,1,1) + app.PrivateChats={} + app.PrivateChatsRef={} + app.ServerUpdate=multi:newAlarm(30)-- every 30 seconds + app.ServerUpdate:OnRing(function(alarm) + client:getUserList() + alarm:Reset() + end) + header=app:newFrame("Header",0,0,0,60,0,0,1) + header:ApplyGradient{Color.Black,Color.Lighten(Color.Black,.10)} + header.BorderSize=0 + loggedInAs=header:newTextLabel("Logged in as: "..MY_Name,-250,0,250,20,1) + loggedInAs.TextColor=Color.White + loggedInAs.Tween=2 + loggedInAs.Visibility=0 + Options=header:newFrame("OptionHolder",0,0,0,30,0,1,1) + Options.Color=Color.Lighten(Color.Black,.10) + Options.BorderSize=0 + Online=Options:newTextLabel("Online",0,0,0,0,2/3,0,1/3,1) + CChat=Options:newTextLabel("Private Chats",0,0,0,0,0,0,1/3,1) + Global=Options:newTextLabel("Global Chat",0,0,0,0,1/3,0,1/3,1) + app["Online"]=app:newFrame(0,90,0,-150,0,0,1,1) + AO=app["Online"] + --Online.Visible=false + AO.holder=AO:newFrame("Holder",0,0,0,0,0,0,1,1) + AO.holder.Visibility=0 + app["Private Chats"]=app:newFrame(0,90,0,-90,0,0,1,1) + AC=app["Private Chats"] + AC.holder=AC:newFrame("Holder",0,0,0,0,.4,0,.6,1) + AC.holder.Visibility=0 + AC.CurrentUSERID="" + AC.CurrentNick="" + Chatting=AC:newFrame("Chatting",0, 0, 0, 0, 0 ,0 ,.4 ,1) + Chatting.Color=Color.Lighten(Color.Black,.10) + app["Global Chat"]=app:newFrame(0,90,0,-150,0,0,1,1) + AG=app["Global Chat"] + AG.holder=AG:newFrame("Holder",0,0,0,0,0,0,1,1) + AG.holder.Visibility=0 + AC.lastBubbleHeight=0 + AG.holder.lastBubbleHeight=0 + function AC:sendChat(msg) + -- + end + function AG.holder:AddChatBubble(user,txt,USERID) local msg=user..": "..txt - local bubble=self.bubbles:newTextLabel(msg,0,self.lastBubbleHeight+5,math.floor(mainapp.width/2),(math.ceil(#msg/24)*12)+5) - bubble.TextFormat="left" - bubble.XTween=2 - bubble.Tween=-4 + local width, wrappedtext = _defaultfont:getWrap(msg, math.floor(app.width/2)-10) + local height = _defaultfont:getHeight() + local bubble=self:newTextLabel("",0,self.lastBubbleHeight+5,math.floor(app.width/2),#wrappedtext*height+6) + bubble.TFrame=bubble:newTextLabel(msg,8,0,-16,0,0,0,1,1) + bubble.TFrame.Visibility=0 + bubble.TFrame.TextFormat="left" + bubble.TFrame.Tween=-4 + bubble.TFrame.TextColor=Color.White + bubble.Color=Color.White bubble:setRoundness(5,5,360) - if isself then + bubble.Visibility=.5 + bubble.Color=Color.Black + if user==MY_Name then + bubble.TFrame.text=bubble.TFrame.text:gsub("("..user.."):","You:") bubble:anchorRight(1) end - self.lastBubbleHeight=self.lastBubbleHeight+(math.ceil(#msg/24)*12)+13 - if self.lastBubbleHeight>mainapp.height-60 then - self.bubbles.offset.pos.y=-(self.lastBubbleHeight-(mainapp.height-60)) + self.lastBubbleHeight=self.lastBubbleHeight+#wrappedtext*height+11 + if self.lastBubbleHeight>self.height-20 then + self.offset.pos.y=-(self.lastBubbleHeight-(self.height-20)) end end - mainapp.textbox=mainapp:newTextBox("",5,-35,-10,30,0,1,1) -- creates a textbox that allows the user to be able to send messages - mainapp.textbox.TextFormat="left" -- sets the format to left hand side of screen - mainapp.textbox.Color=Color.tan - mainapp.textbox:setRoundness(5,5,360) - mainapp.textbox:OnEnter(function(self,txt) -- handles the send event - client:sendChat(MY_Name,txt) -- sends the data to the server + function AG:sendChat(msg) + client:sendChat(MY_Name,msg) + end + function AC:PopulateChat(user,msg,isself) + if CFrame.IsPChat then + local width, wrappedtext = _defaultfont:getWrap(msg, math.floor((CFrame.width)/2)) + local height = _defaultfont:getHeight() + local bubble; + if #wrappedtext>1 then + bubble=CFrame:newTextLabel("",0,CFrame.lastBubbleHeight+5,0,(#wrappedtext+1)*height+6,0,0,.5) + else + bubble=CFrame:newTextLabel("",0,CFrame.lastBubbleHeight+5,0,(#wrappedtext)*height+6,0,0,.5) + end + bubble.TFrame=bubble:newTextLabel(msg,8,0,-16,0,0,0,1,1) + bubble.TFrame.Visibility=0 + bubble.TFrame.TextFormat="left" + bubble.TFrame.Tween=-4 + bubble.TFrame.TextColor=Color.White + bubble.Color=Color.White + bubble:setRoundness(5,5,360) + bubble.Visibility=.5 + bubble.Color=Color.Black + if isself then + bubble.TFrame.text="You: "..msg + bubble:anchorRight(1) + else + bubble.TFrame.text=CFrame.Nick..": "..msg + end + print(#wrappedtext) + if #wrappedtext>1 then + CFrame.lastBubbleHeight=CFrame.lastBubbleHeight+(#wrappedtext+1)*height+11 + else + CFrame.lastBubbleHeight=CFrame.lastBubbleHeight+(#wrappedtext)*height+11 + end + if CFrame.lastBubbleHeight>CFrame.height-20 then + CFrame.offset.pos.y=-(CFrame.lastBubbleHeight-(self.height-20)) + end + end + end + CFrame=nil + client.OnUserList(function(list) + if input.Visible then + c=0 + local collections={} + local childs=AC.holder:getChildren() + for i=1,#childs do + collections[childs[i].Name]=childs[i] + end + for i,v in pairs(list) do + collections[v]=nil + if i~=MY_Name and not(AC.holder.Children[v]) then + local temp=Chatting:newTextLabel(i,0,20*(c+#Chatting:getChildren()),0,20,0,0,1) + c=c+1 + temp:setRoundness(7,7,360) + temp.Color=Color.Yellow + temp.Tween=-4 + temp.USERID=v + temp.link=AC.holder:newFrame(v,0,0,0,0,0,0,1,1) + temp.link.Visibility=0 + app[v]=temp.link + temp.link.Visible=false + temp.link.USERID=v + temp.link.Nick=i + temp.link.holder=temp.link + temp.link.button=temp + function temp.link:sendChat(txt) + AC:PopulateChat("",txt,true) + client:sendChatTo(MY_Name,self.USERID,txt) + end + temp.link.IsPChat=true + temp.link.lastBubbleHeight=0 + temp:OnReleased(function(b,self) + CFrame=self.link + local c=Chatting:getChildren() + for i=1,#c do + c[i].Color=Color.Yellow + end + temp.Color=Color.Green + local c=AC.holder:getChildren() + for i=1,#c do + c[i].Visible=false + end + self.link.Visible=true + end) + end + end + for i,v in pairs(collections) do + collections[i].button:Destroy() + collections[i]:Destroy() + AC.holder.Children[i]=nil + end + local c=Chatting:getChildren() + for i=1,#c do + c[i]:SetDualDim(0,20*(i-1),0,20,0,0,1) + end + else + anim.Visible=false + local c=AO.holder:getChildren() + for i=1,#c do + c[i]:Destroy() + end + c=0 + for i,v in pairs(list) do + if i~=MY_Name then + local temp=AO.holder:newTextLabel(i,0,(c)*35,0,30,0,0,.5) + c=c+1 + temp.USERID=v + temp:setRoundness(5,5,360) + temp.Color=Color.dark_gray + temp.Tween=2 + temp:OnReleased(function(b,self) + table.insert(app.PrivateChats,{i,self.USERID}) + end) + end + end + end + end) + function AO:Act() + CFrame=self + anim.Visible=true + input.Visible=false + client:getUserList() + end + function AC:Act() + input.Visible=true + CFrame=self + input:setDualDim(0,-60,0,60,.4,1,.6) + input:setRoundness(nil,nil,nil) + client:getUserList() + end + function AG:Act() + input.Visible=true + CFrame=self + input:setDualDim(0,-60,0,60,0,1,1) + input:setRoundness(10,10,360) + end + function app:hideOptions() + gui.massMutate({ + Visible=false, + },app["Online"],app["Private Chats"],app["Global Chat"]) + end + gui.massMutate({ + Visibility=0, + ClipDescendants=true, + Visible=false, + },app["Online"],app["Private Chats"],app["Global Chat"]) + gui.massMutate({ + Tween=2, + Visibility=0, + TextColor=Color.Darken(Color.White,.3), + "setNewFont(18)", + [[OnEnter(function(self) + self.TextColor=Color.White + end)]], + [[OnExit(function(self) + self.TextColor=Color.Darken(Color.White,.3) + end)]], + [[OnReleased(function(b,self) + app:hideOptions() + app[self.text].Visible=true + app[self.text]:Act() + end)]], + },Online,CChat,Global) + textDisp=header:newTextLabel("Chats",10,15,100,30) + textDisp.TextFormat="left" + textDisp:setNewFont(28) + textDisp.TextColor=Color.White + textDisp.Visibility=0 + input=app:newFrame("InputHolder",0,-60,0,60,0,1,1) + input:anchorRight(1) + input.Visibility=1 + input.BorderSize=0 + input:setRoundness(10,10,360) + input:ApplyGradient{Color.Black,Color.Lighten(Color.Black,.10)} + input.Visible=false + textbox=input:newTextBox("",11,14,-22,-25,0,0,1,1) + textbox:setRoundness(5,5,360) + textbox.Visibility=1 + textbox.TextFormat="left" + textbox.Tween=4 + textbox.Color=Color.White + textbox.XTween=4 + textbox.ClipDescendants=true + input:OnUpdate(function(self) + local width, wrappedtext = _defaultfont:getWrap(textbox.text, textbox.width) + local height = _defaultfont:getHeight() + if #wrappedtext==0 then + input:SetDualDim(0,-60,0,60,0,1,1) + else + input:SetDualDim(0,-60-((#wrappedtext-1)*(height)),0,60+((height)*(#wrappedtext-1)),0,1,1) + end + end) + textbox:OnEnter(function(self,txt) + CFrame:sendChat(txt) self.text="" - self.Color=Color.tan + self.ttext="" end) - mainapp.textbox:OnFocus(function(self) - self.Color=Color.Lighten(Color.tan,.25) - end) - mainapp.textbox.ClearOnFocus=true - mainapp.textbox.XTween=2 - mainapp.textbox.Tween=2 -- positions the text in the text box + AG.Visible=true + AG:Act() end +--must be last object created! +anim=gui:newAnim("loading",.01, 0, 0, 41, 39) +anim.Visible=false +anim:OnAnimEnd(function(self) + self:Reset() + self:Resume() +end) +anim:OnUpdate(function(self) + self:centerX() + self:centerY() +end) +--~ bubble=gui:newFrame("Test",100,100,100,100) + diff --git a/client/net/chatting.lua b/client/net/chatting.lua index 4def550..ff50086 100644 --- a/client/net/chatting.lua +++ b/client/net/chatting.lua @@ -1,4 +1,5 @@ require("net") +require("net.identity") --General Stuff --[[ What this module does! Adds @@ -8,25 +9,78 @@ client:OnChatRecieved(function(user,msg) end) client:sendChat(user,msg) ]] net:registerModule("chatting",{2,1,0}) +net.chatting.users={} +function net.chatting:getUserIdFromIP(ip) + return net.chatting.users[ip] +end 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.OnUserLoggedIn(function(user,cid,ip,port,dTable) + dTable=loadstring("return "..dTable)() + local USERID=bin.new(user):getHash(32) + print(USERID) + net.chatting.users[USERID]={dTable.nick,cid,ip,port,dTable} -- add users that log in to the userlist + net.chatting.users[ip]=USERID -- add users that log in to the userlist + local users={} + for i,v in pairs(net.chatting.users) do + if type(i)~="userdata" then + table.insert(users,i.."|"..net.chatting.users[i][1]) + end + end + table.insert(users,"") + for i,v in pairs(s.ips) do + s:send(v,"!chatting! $Users|NIL|NIL '"..table.concat(users,",").."'") + end + end) + s.OnUserLoggerOut(function(self,user) + local USERID=bin.new(user):getHash(32) + local ip=net.chatting.users[USERID] + print(USERID) + net.chatting.users[USERID]=nil + net.chatting.users[ip]=nil + end) 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 - for i,v in pairs(self.ips) do - if ip==v then - print("Self: "..struct.user) - self:send(v,"!chatting! 1 "..struct.user.." '"..struct.msg.."'") - else - self:send(v,"!chatting! 0 "..struct.user.." '"..struct.msg.."'") + if user:sub(1,1)=="$" then + local cmd,arg=user:match("$(.+)|(.+)") + print("Using extended chatting protocal!") + if cmd=="DM" 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,"PRIVATE") + print("USERID",arg) + self:send(net.chatting.users[arg][3],"!chatting! $DM|"..net.chatting.users[arg][1].."|"..net.chatting:getUserIdFromIP(ip).." '"..msg.."'",net.chatting.users[arg][4]) + elseif cmd=="getUsers" then + local users={} + for i,v in pairs(net.chatting.users) do + if type(i)~="userdata" then + table.insert(users,i.."|"..net.chatting.users[i][1]) + end + end + table.insert(users,"") + self:send(ip,"!chatting! $Users|NIL|NIL '"..table.concat(users,",").."'",port) + elseif cmd=="getPrivateChat" then -- will do later! + --send: "!sft! *...*" + end + else + 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,"GROUP") -- trigger the chat event + local USERID=net.chatting:getUserIdFromIP(ip) + for i,v in pairs(self.ips) do + if ip==v then + self:send(v,"!chatting! 1|"..struct.user.."|"..USERID.." '"..struct.msg.."'") + else + self:send(v,"!chatting! 0|"..struct.user.."|"..USERID.." '"..struct.msg.."'") + end end end end @@ -41,16 +95,39 @@ function net.chatting:init() -- calling this initilizes the library and binds it 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 isself, user,msg = data:match("!chatting! (%d) (%S-) '(.+)'") - if user and msg then + local isself,user,USERID,msg = data:match("!chatting! (%S-)|(%S-)|(%S-) '(.+)'") + if not isself then return end + if tonumber(isself) then --This is the client so our job here is done - print(isself) - self.OnChatRecieved:Fire(user,msg,({["1"]=true, ["0"]=false})[isself]) -- trigger the chat event + self.OnChatRecieved:Fire(user,msg,({["1"]=true, ["0"]=false})[isself],USERID) -- trigger the chat event + elseif isself:sub(1,1)=="$" then + local cmd=isself:match("$(.+)") + if cmd=="DM" then + print("DM: ",user,msg,USERID) + c.OnPrivateChatRecieved:Fire(user,msg,USERID) + elseif cmd=="Users" then + local tab={} + for ID,nick in msg:gmatch("(%S-)|(%S-),") do + tab[nick]=ID + end + c.OnUserList:Fire(tab) + end end end) function c:sendChat(user,msg) self:send("!chatting! "..user.." '"..msg.."'") end + function c:sendChatTo(user,touser,msg) + self:send("!chatting! $DM|"..touser.." '"..msg.."'") + end + function c:getUserList() + self:send("!chatting! $getUsers|NIL 'NIL'") + end + function c:getChatFrom(userID) + self:send("!chatting! getPrivateChat|NIL '"..userID.."'") -- add if time permits + end + c.OnPrivateChatRecieved=multi:newConnection() + c.OnUserList=multi:newConnection() c.OnChatRecieved=multi:newConnection() -- create a chat event end) end diff --git a/client/net/identity.lua b/client/net/identity.lua index 2cf9d0f..8997496 100644 --- a/client/net/identity.lua +++ b/client/net/identity.lua @@ -10,6 +10,8 @@ function net.hash(text,n) n=n or 16 return bin.new(text.."jgmhktyf"):getHash(n) end +net.identity.UIDS={} +net.identity.UIDS.ids={} 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) @@ -39,6 +41,7 @@ function net.identity:init() -- calling this initilizes the library and binds it self.userFolder=loc end function s:loginUserOut(user) + net.identity.UIDS.ids[user.UID]=nil self.loggedIn[user]=nil end function s:loginUserIn(user,cid) @@ -47,6 +50,7 @@ function net.identity:init() -- calling this initilizes the library and binds it table.merge(self.loggedIn[user],dTable or {}) self.loggedIn[user].cid=cid self.loggedIn[user].nick=nick + self.loggedIn[user].UID=net.resolveID(net.identity.UIDS) return self:getUserDataHandle(user) end function s:getUserDataHandle(user) @@ -100,7 +104,7 @@ function net.identity:init() -- calling this initilizes the library and binds it 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) + self.OnUserLoggedIn:Fire(user,cid,ip,port,bin.ToStr(handle)) return else self:send(ip,"!identity! LOGINBAD <-|nil|->",port)