Add files via upload

This commit is contained in:
Ryan Ward 2016-12-03 00:45:36 -05:00 committed by GitHub
parent 555f9de5f7
commit b5590af9bd
9 changed files with 1797 additions and 14 deletions

797
client/Libs/Utils.lua Normal file
View File

@ -0,0 +1,797 @@
-- os Additions
function os.getSystemBit()
if (os.getenv('PROCESSOR_ARCHITEW6432')=='AMD64' or os.getenv('PROCESSOR_ARCHITECTURE')=='AMD64') then
return 64
else
return 32
end
end
function os.sleep(n)
if not n then n=0 end
local t0 = os.clock()
while os.clock() - t0 <= n do end
end
function os.pause(msg)
if msg ~= nil then
print(msg)
end
io.read()
end
function os.batCmd(cmd)
io.mkFile('temp.bat',cmd)
local temp = os.execute([[temp.bat]])
io.delFile('temp.bat')
return temp
end
function os._getOS()
if package.config:sub(1,1)=='\\' then
return 'windows'
else
return 'unix'
end
end
function os.getOS(t)
if not t then
return os._getOS()
end
if os._getOS()=='unix' then
fh,err = io.popen('uname -o 2>/dev/null','r')
if fh then
osname = fh:read()
end
if osname then return osname end
end
local winver='Unknown Version'
local a,b,c=os.capture('ver'):match('(%d+).(%d+).(%d+)')
local win=a..'.'..b..'.'..c
if type(t)=='string' then
win=t
end
if win=='4.00.950' then
winver='95'
elseif win=='4.00.1111' then
winver='95 OSR2'
elseif win=='4.00.1381' then
winver='NT 4.0'
elseif win=='4.10.1998' then
winver='98'
elseif win=='4.10.2222' then
winver='98 SE'
elseif win=='4.90.3000' then
winver='ME'
elseif win=='5.00.2195' then
winver='2000'
elseif win=='5.1.2600' then
winver='XP'
elseif win=='5.2.3790' then
winver='Server 2003'
elseif win=='6.0.6000' then
winver='Vista/Windows Server 2008'
elseif win=='6.0.6002' then
winver='Vista SP2'
elseif win=='6.1.7600' then
winver='7/Windows Server 2008 R2'
elseif win=='6.1.7601' then
winver='7 SP1/Windows Server 2008 R2 SP1'
elseif win=='6.2.9200' then
winver='8/Windows Server 2012'
elseif win=='6.3.9600' then
winver='8.1/Windows Server 2012'
elseif win=='6.4.9841' then
winver='10 Technical Preview 1'
elseif win=='6.4.9860' then
winver='10 Technical Preview 2'
elseif win=='6.4.9879' then
winver='10 Technical Preview 3'
elseif win=='10.0.9926' then
winver='10 Technical Preview 4'
end
return 'Windows '..winver
end
function os.getLuaArch()
return (#tostring({})-7)*4
end
if os.getOS()=='windows' then
function os.sleep(n)
if n > 0 then os.execute('ping -n ' .. tonumber(n+1) .. ' localhost > NUL') end
end
else
function os.sleep(n)
os.execute('sleep ' .. tonumber(n))
end
end
function os.capture(cmd, raw)
local f = assert(io.popen(cmd, 'r'))
local s = assert(f:read('*a'))
f:close()
if raw then return s end
s = string.gsub(s, '^%s+', '')
s = string.gsub(s, '%s+$', '')
s = string.gsub(s, '[\n\r]+', ' ')
return s
end
function os.getCurrentUser()
return os.getenv('$USER') or os.getenv('USERNAME')
end
-- string Additions
function string.trim(s)
local from = s:match"^%s*()"
return from > #s and "" or s:match(".*%S", from)
end
function string.random(n)
local str = ''
strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}
for i=1,n do
h = math.random(1,#strings)
str = str..''..strings[h]
end
return str
end
function string.linesToTable(s)
local t = {}
local i = 0
while true do
i = string.find(s, '\n', i+1)
if i == nil then return t end
table.insert(t, i)
end
end
function string.lines(str)
local t = {}
local function helper(line) table.insert(t, line) return '' end
helper((str:gsub('(.-)\r?\n', helper)))
return t
end
function string.split(str, pat)
local t = {} -- NOTE: use {n = 0} in Lua-5.0
local fpat = '(.-)' .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= '' then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
function string.shuffle(inputStr)
math.randomseed(os.time());
local outputStr = '';
local strLength = string.len(inputStr);
while (strLength ~=0) do
local pos = math.random(strLength);
outputStr = outputStr..string.sub(inputStr,pos,pos);
inputStr = inputStr:sub(1, pos-1) .. inputStr:sub(pos+1);
strLength = string.len(inputStr);
end
return outputStr;
end
function string.genKeys(chars,a,f,s,GG)
if GG then
chars=string.rep(chars,a)
end
if s then
chars=string.shuffle(chars)
end
b=#chars
if a==0 then return end
local taken = {} local slots = {}
for i=1,a do slots[i]=0 end
for i=1,b do taken[i]=false end
local index = 1
local tab={}
for i=1,#chars do
table.insert(tab,chars:sub(i,i))
end
while index > 0 do repeat
repeat slots[index] = slots[index] + 1
until slots[index] > b or not taken[slots[index]]
if slots[index] > b then
slots[index] = 0
index = index - 1
if index > 0 then
taken[slots[index]] = false
end
break
else
taken[slots[index]] = true
end
if index == a then
local tt={}
for i=1,a do
table.insert(tt,tab[slots[i]])
end
f(table.concat(tt))
taken[slots[index]] = false
break
end
index = index + 1
until true end
end
-- io Additions
function io.getInput(msg)
if msg ~= nil then
io.write(msg)
end
return io.read()
end
function io.scanDir(directory)
directory=directory or io.getDir()
local i, t, popen = 0, {}, io.popen
if os.getOS()=='unix' then
for filename in popen('ls -a \''..directory..'\''):lines() do
i = i + 1
t[i] = filename
end
else
for filename in popen('dir \''..directory..'\' /b'):lines() do
i = i + 1
t[i] = filename
end
end
return t
end
function io.buildFromTree(tbl, indent,folder)
if not indent then indent = 0 end
if not folder then folder = '' end
for k, v in pairs(tbl) do
formatting = string.rep(' ', indent) .. k .. ':'
if type(v) == 'table' then
if not(io.dirExists(folder..string.sub(formatting,1,-2))) then
io.mkDir(folder..string.sub(formatting,1,-2))
end
io.buildFromTree(v,0,folder..string.sub(formatting,1,-2)..'\\')
else
a=string.find(tostring(v),':',1,true)
if a then
file=string.sub(tostring(v),1,a-1)
data=string.sub(tostring(v),a+1)
io.mkFile(folder..file,data,'wb')
else
io.mkFile(folder..v,'','wb')
end
end
end
end
function io.cpFile(path,topath)
if os.getOS()=='unix' then
os.execute('cp '..file1..' '..file2)
else
os.execute('Copy '..path..' '..topath)
end
end
function io.delDir(directoryname)
if os.getOS()=='unix' then
os.execute('rm -rf '..directoryname)
else
os.execute('rmdir '..directoryname..' /s /q')
end
end
function io.delFile(path)
os.remove(path)
end
function io.mkDir(dirname)
os.execute('mkdir "' .. dirname..'"')
end
function io.mkFile(filename,data,tp)
if not(tp) then tp='wb' end
if not(data) then data='' end
file = io.open(filename, tp)
if file==nil then return end
file:write(data)
file:close()
end
function io.movFile(path,topath)
io.cpFile(path,topath)
io.delFile(path)
end
function io.listFiles(dir)
if not(dir) then dir='' end
local f = io.popen('dir \''..dir..'\'')
if f then
return f:read('*a')
else
print('failed to read')
end
end
function io.getDir(dir)
if not dir then return io.getWorkingDir() end
if os.getOS()=='unix' then
return os.capture('cd '..dir..' ; cd')
else
return os.capture('cd '..dir..' & cd')
end
end
function io.getWorkingDir()
return io.popen'cd':read'*l'
end
function io.fileExists(path)
g=io.open(path or '','r')
if path =='' then
p='empty path'
return nil
end
if g~=nil and true or false then
p=(g~=nil and true or false)
end
if g~=nil then
io.close(g)
else
return false
end
return p
end
function io.fileCheck(file_name)
if not file_name then print('No path inputed') return false end
local file_found=io.open(file_name, 'r')
if file_found==nil then
file_found=false
else
file_found=true
end
return file_found
end
function io.dirExists(strFolderName)
strFolderName = strFolderName or io.getDir()
local fileHandle, strError = io.open(strFolderName..'\\*.*','r')
if fileHandle ~= nil then
io.close(fileHandle)
return true
else
if string.match(strError,'No such file or directory') then
return false
else
return true
end
end
end
function io.getAllItems(dir)
local t=os.capture("cd \""..dir.."\" & dir /a-d | find",true):lines()
return t
end
function io.listItems(dir)
if io.dirExists(dir) then
temp=io.listFiles(dir) -- current directory if blank
if io.getDir(dir)=='C:\\\n' then
a,b=string.find(temp,'C:\\',1,true)
a=a+2
else
a,b=string.find(temp,'..',1,true)
end
temp=string.sub(temp,a+2)
list=string.linesToTable(temp)
temp=string.sub(temp,1,list[#list-2])
slist=string.lines(temp)
table.remove(slist,1)
table.remove(slist,#slist)
temp={}
temp2={}
for i=1,#slist do
table.insert(temp,string.sub(slist[i],40,-1))
end
return temp
else
return nil
end
end
function io.getDirectories(dir,l)
if dir then
dir=dir..'\\'
else
dir=''
end
local temp2=io.scanDir(dir)
for i=#temp2,1,-1 do
if io.fileExists(dir..temp2[i]) then
table.remove(temp2,i)
elseif l then
temp2[i]=dir..temp2[i]
end
end
return temp2
end
function io.getFiles(dir,l)
if dir then
dir=dir..'\\'
else
dir=''
end
local temp2=io.scanDir(dir)
for i=#temp2,1,-1 do
if io.dirExists(dir..temp2[i]) then
table.remove(temp2,i)
elseif l then
temp2[i]=dir..temp2[i]
end
end
return temp2
end
function io.getFullName(name)
local temp=name or arg[0]
if string.find(temp,'\\',1,true) or string.find(temp,'/',1,true) then
temp=string.reverse(temp)
a,b=string.find(temp,'\\',1,true)
if not(a) or not(b) then
a,b=string.find(temp,'/',1,true)
end
return string.reverse(string.sub(temp,1,b-1))
end
return temp
end
function io.getName(file)
local name=io.getFullName(file)
name=string.reverse(name)
a,b=string.find(name,'.',1,true)
name=string.sub(name,a+1,-1)
return string.reverse(name)
end
function io.readFile(file)
local f = io.open(file, 'rb')
local content = f:read('*all')
f:close()
return content
end
function io.getExtension(file)
local file=io.getFullName(file)
file=string.reverse(file)
local a,b=string.find(file,'.',0,true)
local temp=string.sub(file,1,b)
return string.reverse(temp)
end
function io.pathToTable(path)
local p=io.splitPath(path)
local temp={}
temp[p[1]]={}
local last=temp[p[1]]
for i=2,#p do
snd=last
last[p[i]]={}
last=last[p[i]]
end
return temp,last,snd
end
function io.splitPath(str)
return string.split(str,'[\\/]+')
end
function io.parseDir(dir,t)
io.tempFiles={}
function _p(dir)
local dirs=io.getDirectories(dir,true)
local files=io.getFiles(dir,true)
for i=1,#files do
p,l,s=io.pathToTable(files[i])
if t then
s[io.getFullName(files[i])]=io.readFile(files[i])
else
s[io.getFullName(files[i])]=io.open(files[i],'r+')
end
table.merge(io.tempFiles,p)
end
for i=1,#dirs do
table.merge(io.tempFiles,io.pathToTable(dirs[i]))
_p(dirs[i],t)
end
end
_p(dir)
return io.tempFiles
end
function io.parsedir(dir,f)
io.tempFiles={}
function _p(dir,f)
local dirs=io.getDirectories(dir,true)
local files=io.getFiles(dir,true)
for i=1,#files do
if not f then
table.insert(io.tempFiles,files[i])
else
f(files[i])
end
end
for i=1,#dirs do
_p(dirs[i],f)
end
end
_p(dir,f)
return io.tempFiles
end
function io.driveReady(drive)
drive=drive:upper()
if not(drive:find(':',1,true)) then
drive=drive..':'
end
drives=io.getDrives()
for i=1,#drives do
if drives[i]==drive then
return true
end
end
return false
end
function io.getDrives()
if os.getOS()=='windows' then
local temp={}
local t1=os.capture('wmic logicaldisk where drivetype=2 get deviceid, volumename',true)
local t2=os.capture('wmic logicaldisk where drivetype=3 get deviceid, volumename',true)
for drive,d2 in t1:gmatch('(.:)%s-(%w+)') do
if #d2>1 then
table.insert(temp,drive)
end
end
for drive in t2:gmatch('(.:)') do
table.insert(temp,drive)
end
return temp
end
error('Command is windows only!')
end
-- table Additions
function table.dump(t,indent)
local names = {}
if not indent then indent = '' end
for n,g in pairs(t) do
table.insert(names,n)
end
table.sort(names)
for i,n in pairs(names) do
local v = t[n]
if type(v) == 'table' then
if(v==t) then
print(indent..tostring(n)..': <-')
else
print(indent..tostring(n)..':')
table.dump(v,indent..' ')
end
else
if type(v) == 'function' then
print(indent..tostring(n)..'()')
else
print(indent..tostring(n)..': '..tostring(v))
end
end
end
end
function table.alphanumsort(o)
local function padnum(d) local dec, n = string.match(d, '(%.?)0*(.+)')
return #dec > 0 and ('%.12f'):format(d) or ('%s%03d%s'):format(dec, #n, n)
end
table.sort(o, function(a,b) return tostring(a):gsub('%.?%d+',padnum)..('%3d'):format(#b)< tostring(b):gsub('%.?%d+',padnum)..('%3d'):format(#a) end)
return o
end
function table.foreach(t,f)
for i,v in pairs(t) do
f(v)
end
end
function table.merge(t1, t2)
for k,v in pairs(t2) do
if type(v) == 'table' then
if type(t1[k] or false) == 'table' then
table.merge(t1[k] or {}, t2[k] or {})
else
t1[k] = v
end
else
t1[k] = v
end
end
return t1
end
function table.print(tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
formatting = string.rep(' ', indent) .. k .. ': '
if type(v) == 'table' then
print(formatting)
table.print(v, indent+1)
else
print(formatting .. tostring(v))
end
end
end
function table.merge(t1, t2)
for k,v in pairs(t2) do
if type(v) == 'table' then
if type(t1[k] or false) == 'table' then
table.merge(t1[k] or {}, t2[k] or {})
else
t1[k] = v
end
else
t1[k] = v
end
end
return t1
end
function table.clear(t)
for k in pairs (t) do
t[k] = nil
end
end
function table.copy(t)
function deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deepcopy(orig_key)] = deepcopy(orig_value)
end
setmetatable(copy, deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
return deepcopy(t)
end
function table.swap(tab,i1,i2)
tab[i1],tab[i2]=tab[i2],tab[i1]
end
function table.append(t1, ...)
t1,t2= t1 or {},{...}
for k,v in pairs(t2) do
t1[#t1+1]=t2[k]
end
return t1
end
function table.compare(t1, t2,d)
if d then
return table.deepCompare(t1,t2)
end
--if #t1 ~= #t2 then return false end
if #t2>#t1 then
for i=1,#t2 do
if t1[i] ~= t2[i] then
return false,t2[i]
end
end
else
for i=1,#t1 do
if t1[i] ~= t2[i] then
return false,t2[i]
end
end
end
return true
end
function table.deepCompare(t1,t2)
if t1==t2 then return true end
if (type(t1)~='table') then return false end
local mt1 = getmetatable(t1)
local mt2 = getmetatable(t2)
if( not table.deepCompare(mt1,mt2) ) then return false end
for k1,v1 in pairs(t1) do
local v2 = t2[k1]
if( not table.deepCompare(v1,v2) ) then return false end
end
for k2,v2 in pairs(t2) do
local v1 = t1[k2]
if( not table.deepCompare(v1,v2) ) then return false end
end
return true
end
function table.has(t,_v)
for i,v in pairs(t) do
if v==_v then
return true
end
end
return false
end
function table.reverse(tab)
local size = #tab
local newTable = {}
for i,v in ipairs (tab) do
newTable[size-i] = v
end
for i=1,#newTable do
tab[i]=newTable[i]
end
end
-- Math Additions
local Y = function(g) local a = function(f) return f(f) end return a(function(f) return g(function(x) local c=f(f) return c(x) end) end) end
local F = function(f) return function(n)if n == 0 then return 1 else return n*f(n-1) end end end
math.factorial = Y(F)
math.fib={}
math.fib.fibL={}
setmetatable(math.fib,{__call=function(self,n)
if n<=2 then
return 1
else
if self.fibL[n] then
return self.fibL[n]
else
local t=math.fib(n-1)+math.fib(n-2)
self.fibL[n]=t
return t
end
end
end})
local floor,insert = math.floor, table.insert
function math.basen(n,b)
n = floor(n)
if not b or b == 10 then return tostring(n) end
local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
local t = {}
local sign = ''
if n < 0 then
sign = '-'
n = -n
end
repeat
local d = (n % b) + 1
n = floor(n / b)
insert(t, 1, digits:sub(d,d))
until n == 0
return sign .. table.concat(t,'')
end
function math.convbase(n,b,tb)
return math.basen(tonumber(tostring(n),b),tb)
end
if BigNum then
function BigNum.mod(a,b)
return a-((a/b)*b)
end
local floor,insert = math.floor, table.insert
function math.basen(n,b)
n = BigNum.new(n)
if not b or b == 10 then return tostring(n) end
local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
local t = {}
local sign = ''
if n < BigNum.new(0) then
sign = '-'
n = -n
end
repeat
local d = BigNum.mod(n , b) + 1
n = n/b
d=tonumber(tostring(d))
insert(t, 1, digits:sub(d,d))
until tonumber(tostring(n)) == 0
return sign .. table.concat(t,'')
end
function math.to10(n,b)
local num=tostring(n)
local sum=BigNum.new()
local digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for i=1,#num do
local v=digits:find(num:sub(i,i),1,true)
sum=sum+BigNum.new(tonumber(v)-1)*BigNum.pow(BigNum.new(b),BigNum.new(#num-i))
end
return sum
end
function math.convbase(n,b,tb)
return math.basen(math.to10(n,b),tb)
end
end
function math.numfix(n,x)
local str=tostring(n)
if #str<x then
str=('0'):rep(x-#str)..str
end
return str
end
-- Misc Additions
function smartPrint(...)
local args={...}
for i=1,#args do
if type(args[i])=='table' then
table.print(args[i])
else
print(args[i])
end
end
end
function totable(v)
if type(v)=='table' then return v end
return {v}
end
print(math.factorial(2))

View File

@ -1,3 +1,4 @@
MY_Name="" -- Will be set at a later time
-- This is a comment -- This is a comment
--This is the test client code! --This is the test client code!
require("Libs/Library") -- One of the defualt libraies that i load... Not needed for this project require("Libs/Library") -- One of the defualt libraies that i load... Not needed for this project
@ -10,25 +11,96 @@ require("net") -- Loads the networking library
require("net.chatting") require("net.chatting")
client=net:newTCPClient("localhost",12345) -- Connects to the server client=net:newTCPClient("localhost",12345) -- Connects to the server
if type(client)=="boolean" then error("Please run the server file first!") end if type(client)=="boolean" then error("Please run the server file first!") end
client.OnChatRecieved(function(user,msg) -- hook to grab chat data client.OnChatRecieved(function(user,msg,isself) -- hook to grab chat data
mainapp.chatFrame.text=mainapp.chatFrame.text..user..": "..msg.."\n" Chat:AddChatBubble(user,msg,isself)
end) end)
gui.enableAutoWindowScaling(true) -- allows mobile support. Not needed for PC use --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)
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
end
print(Chat.bubbles.offset.pos.y)
end
gui.ff:OnUpdate(func)
function InitEngine() function InitEngine()
mainapp=gui:newFrame("",0,0,0,0,0,0,1,1) -- creates a frame that takes up the enitre window mainapp=gui:newFrame("",0,0,0,0,0,0,1,1) -- creates a frame that takes up the enitre window
mainapp.header=mainapp:newTextLabel("Chat Program",0,0,0,20,0,0,1) -- creates the header for the app mainapp.Color=Color.Lighten(Color.Brown,.25)
mainapp.header.Tween=-3 -- moves the text up by a factor of 3 pixels 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.header.Color=Color.Lighten(Color.Blue,.25) -- Sets the Color of the header object to light blue
mainapp.chatFrame=mainapp:newTextLabel("",0,20,0,-20,0,0,1,1) -- creates the chat frame where users can see the text that is sent 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,.15) -- Color stuff mainapp.chatFrame.Color=Color.Lighten(Color.Brown,.25) -- Color stuff
mainapp.chatFrame.Tween=-3 -- text positioning mainapp.chatFrame.ClipDescendants=true
mainapp.chatFrame.TextFormat="left" -- changes the text format to left hand side of screen 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)
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
bubble:setRoundness(5,5,360)
if isself then
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))
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=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.TextFormat="left" -- sets the format to left hand side of screen
mainapp.textbox.Color=Color.tan mainapp.textbox.Color=Color.tan
mainapp.textbox:setRoundness(5,5,360) mainapp.textbox:setRoundness(5,5,360)
mainapp.textbox:OnEnter(function(self,txt) -- handles the send event mainapp.textbox:OnEnter(function(self,txt) -- handles the send event
client:sendChat("NAMENOSPACE",txt) -- sends the data to the server client:sendChat(MY_Name,txt) -- sends the data to the server
self.text="" self.text=""
self.Color=Color.tan self.Color=Color.tan
end) end)
@ -38,5 +110,4 @@ function InitEngine()
mainapp.textbox.ClearOnFocus=true mainapp.textbox.ClearOnFocus=true
mainapp.textbox.XTween=2 mainapp.textbox.XTween=2
mainapp.textbox.Tween=2 -- positions the text in the text box mainapp.textbox.Tween=2 -- positions the text in the text box
--This displays the chatting frame and allows connection to the server... Look at server.lua to see the servers code
end end

View File

@ -21,7 +21,14 @@ function net.chatting:init() -- calling this initilizes the library and binds it
msg=msg msg=msg
} }
self.OnChatRecieved:Fire(struct) -- trigger the chat event self.OnChatRecieved:Fire(struct) -- trigger the chat event
self:sendAll("!chatting! "..struct.user.." '"..struct.msg.."'") 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.."'")
end
end
end end
end) end)
s.rooms={} s.rooms={}
@ -34,10 +41,11 @@ function net.chatting:init() -- calling this initilizes the library and binds it
net.OnClientCreated:connect(function(c) net.OnClientCreated:connect(function(c)
c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered
--First Lets make sure we are getting chatting data --First Lets make sure we are getting chatting data
local user,msg = data:match("!chatting! (%S-) '(.+)'") local isself, user,msg = data:match("!chatting! (%d) (%S-) '(.+)'")
if user and msg then if user and msg then
--This is the client so our job here is done --This is the client so our job here is done
self.OnChatRecieved:Fire(user,msg) -- trigger the chat event print(isself)
self.OnChatRecieved:Fire(user,msg,({["1"]=true, ["0"]=false})[isself]) -- trigger the chat event
end end
end) end)
function c:sendChat(user,msg) function c:sendChat(user,msg)

53
client/net/email.lua Normal file
View File

@ -0,0 +1,53 @@
require("net.identity")
net:registerModule("email",{1,0,0})
smtp = require 'socket.smtp'
ssl = require 'ssl'
function net.email.init(from,user,pass)
net.OnServerCreated:connect(function(s)
s.from=from
s.user=user
s.pass=pass
function s:sendMessage(subject, body, dTable)
local msg = {
headers = {
from = '<'..dTable.email..'>'
to = dTable.nick..' <'..dTable.email..'>',
subject = subject
},
body = body
}
local ok, err = smtp.send {
from = '<'..self.from..'>',
rcpt = '<'..dTable.email..'>',
source = smtp.message(msg),
user = self.user,
password = self.pass,
server = 'smtp.gmail.com',
port = 465,
create = net.sslCreate
}
if not ok then
print("Mail send failed", err) -- better error handling required
end
end
end)
end
function net.sslCreate()
local sock = socket.tcp()
return setmetatable({
connect = function(_, host, port)
local r, e = sock:connect(host, port)
if not r then return r, e end
sock = ssl.wrap(sock, {mode='client', protocol='tlsv1'})
return sock:dohandshake()
end
}, {
__index = function(t,n)
return function(_, ...)
return sock[n](sock, ...)
end
end
})
end

192
client/net/identity.lua Normal file
View File

@ -0,0 +1,192 @@
require("net")
--General Stuff
--[[ What this module does!
Adds
net.identity:init()
]]
net:registerModule("identity",{1,0,0})
function net.hash(text,n)
n=n or 16
return bin.new(text.."jgmhktyf"):getHash(n)
end
function net.identity:init() -- calling this initilizes the library and binds it to the servers and clients created
--Server Stuff
net.OnServerCreated:connect(function(s)
s.userFolder="./"
print("The identity Module has been loaded onto the server!")
function s:_isRegistered(user)
return io.fileExists(self.userFolder..net.hash(user)..".dat")
end
function s:getUserData(user)
local userdata=bin.load(self.userFolder..net.hash(user)..".dat")
local nick,dTable=userdata:match("%S-|%S-|(%S-)|(.+)")
return nick,loadstring("return "..(dTable or "{}"))()
end
function s:getUserCred(user)
local userdata=bin.load(self.userFolder..net.hash(user)..".dat")
return userdata:match("%S-|(%S-)|")
end
function s:userLoggedIn(cid)
for i,v in pairs(self.loggedIn) do
if v.cid==cid then
return i
end
end
return false
end
function s:setDataLocation(loc)
self.userFolder=loc
end
function s:loginUserOut(user)
self.loggedIn[user]=nil
end
function s:loginUserIn(user,cid)
local nick,dTable=self:getUserData(user)
self.loggedIn[user]={}
table.merge(self.loggedIn[user],dTable or {})
self.loggedIn[user].cid=cid
self.loggedIn[user].nick=nick
return self:getUserDataHandle(user)
end
function s:getUserDataHandle(user)
return self.loggedIn[user]
end
function s:syncUserData(user,ip,port)
local handle=self:getUserDataHandle(user)
self:send(ip,"!identity! SYNC <-|"..bin.ToStr(handle).."|->",port)
end
s.loggedIn={}
s.OnUserRegistered=multi:newConnection()
s.OnUserLoggedIn=multi:newConnection()
s.OnUserLoggerOut=multi:newConnection()
s.OnAlreadyLoggedIn=multi:newConnection()
s.OnPasswordForgotten=multi:newConnection()
s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
local cmd,arg1,arg2,arg3,arg4 = data:match("!identity! (%S-) '(.-)' '(.-)' '(.-)' <%-|(.+)|%->")
if cmd=="register" then
local user,pass,nick,dTable = arg1,arg2,arg3,arg4
if self:_isRegistered(user) then
self:send(ip,"!identity! REGISTERED <-|"..user.."|->",port)
else
if not(self.userFolder:sub(-1,-1)=="/" or self.userFolder:sub(-1,-1)=="\\") then
self.userFolder=self.userFolder.."/"
end
local rets=self.OnUserRegistered:Fire(user,pass,nick,loadstring("return "..(dTable or "{}"))())
for i=1,#rets do
if rets[i][1]==false then
print("Server refused to accept registration request!")
self:send(ip,"!identity! REGISTERREFUSED <-|NIL|->",port)
return
end
end
bin.new(string.format("%s|%s|%s|%s\n",user,pass,nick,dTable)):tofile(self.userFolder..net.hash(user)..".dat")
self:send(ip,"!identity! REGISTEREDGOOD <-|"..user.."|->",port)
end
return
elseif cmd=="login" then
local user,pass = arg1,arg2
local _pass=s:getUserCred(user)
if not(self:_isRegistered(user)) then
self:send(ip,"!identity! LOGINBAD <-|nil|->",port)
return
end
print(pass,_pass)
if pass==_pass then
if self:userLoggedIn(cid) then
self.OnAlreadyLoggedIn:Fire(self,user,cid,ip,port)
self:send(ip,"!identity! ALREADYLOGGEDIN <-|nil|->",port)
return
end
local handle=self:loginUserIn(user,cid) -- binds the cid to username
self:send(ip,"!identity! LOGINGOOD <-|"..bin.ToStr(handle).."|->",port)
self.OnUserLoggedIn:Fire(user,cid,ip,port)
return
else
self:send(ip,"!identity! LOGINBAD <-|nil|->",port)
return
end
elseif cmd=="logout" then
self:loginUserOut(user)
self.OnClientClosed:Fire(self,"User logged out!",cid,ip,port)
elseif cmd=="sync" then
local dTable = loadstring("return "..(arg4 or "{}"))()
local handle = self:getUserDataHandle(self:userLoggedIn(cid))
table.merge(handle,dTable)
elseif cmd=="pass" then
local user=arg1
if self:_isRegistered(user) then
self.OnPasswordForgotten:Fire(arg1,cid)
self:send(ip,"!identity! PASSREQUESTHANDLED <-|NONE|->",port)
else
self:send(ip,"!identity! NOUSER <-|"..user.."|->",port)
end
end
end)
s.OnClientClosed:connect(function(self,reason,cid,ip,port)
self.OnUserLoggerOut:Fire(self,self:userLoggedIn(cid),cid,reason)
end)
end)
--Client Stuff
net.OnClientCreated:connect(function(c)
c.userdata={}
c.OnUserLoggedIn=multi:newConnection()
c.OnBadLogin=multi:newConnection()
c.OnUserAlreadyRegistered=multi:newConnection()
c.OnUserAlreadyLoggedIn=multi:newConnection()
c.OnUserRegistered=multi:newConnection()
c.OnNoUserWithName=multi:newConnection()
c.OnPasswordRequest=multi:newConnection()
c.OnUserRegisterRefused=multi:newConnection()
function c:logout()
self:send("!identity! logout 'NONE' 'NONE' 'NONE' <-|nil|->")
end
c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered
local cmd,arg1 = data:match("!identity! (%S-) <%-|(.+)|%->")
if cmd=="REGISTERED" then
self.OnUserAlreadyRegistered:Fire(self,arg1)
elseif cmd=="REGISTEREDGOOD" then
self.OnUserRegistered:Fire(self,arg1)
elseif cmd=="REGISTERREFUSED" then
self.OnUserRegisterRefused:Fire(self,arg1)
elseif cmd=="ALREADYLOGGEDIN" then
self.OnUserAlreadyLoggedIn:Fire(self,arg1)
elseif cmd=="LOGINBAD" then
self.OnBadLogin:Fire(self)
elseif cmd=="LOGINGOOD" then
local dTable=loadstring("return "..(arg1 or "{}"))()
table.merge(self.userdata,dTable)
self.OnUserLoggedIn:Fire(self,self.userdata)
elseif cmd=="SYNC" then
local dTable=loadstring("return "..(arg1 or "{}"))()
table.merge(self.userdata,dTable)
elseif cmd=="NOUSER" then
self.OnNoUserWithName:Fire(self,arg1)
elseif cmd=="PASSREQUESTHANDLED" then
self.OnPasswordRequest:Fire(self)
end
end)
function c:syncUserData()
self:send(string.format("!identity! sync 'NONE' 'NONE' 'NONE' <-|%s|->",bin.ToStr(dTable)))
end
function c:forgotPass(user)
self:send(string.format("!identity! pass '%s' 'NONE' 'NONE' <-|nil|->",user))
end
function c:getUserDataHandle()
return self.userdata
end
function c:logIn(user,pass)
self:send(string.format("!identity! login '%s' '%s' 'NONE' <-|nil|->",user,net.hash(pass)))
end
function c:register(user,pass,nick,dTable)
if dTable then
self:send(string.format("!identity! register '%s' '%s' '%s' <-|%s|->",user,net.hash(pass),nick,bin.ToStr(dTable)))
else
self:send(string.format("!identity! register '%s' '%s' '%s' <-|nil|->",user,net.hash(pass),nick))
end
end
end)
end
if net.autoInit then
net.identity:init()
end

483
client/net/init.lua Normal file
View File

@ -0,0 +1,483 @@
function string.trim(s)
local from = s:match"^%s*()"
return from > #s and "" or s:match(".*%S", from)
end
socket=require("socket")
net={}
net.Version={1,0,0}
net.OnServerCreated=multi:newConnection()
net.OnClientCreated=multi:newConnection()
net.loadedModules={}
net.autoInit=true
function net:registerModule(mod,version)
table.insert(self.loadedModules,mod)
net[mod]={}
if version then
net[mod].Version=version
else
net[mod].Version={1,0,0}
end
end
function net.getModuleVersion(ext)
if not ext then
return string.format("%d.%d.%d",net.Version[1],net.Version[2],net.Version[3])
end
return string.format("%d.%d.%d",net[ext].Version[1],net[ext].Version[2],net[ext].Version[3])
end
function net.resolveID(obj)
local num=math.random(10000000,99999999)
if obj[tostring(num)] then
return net.resolveID(obj)
end
obj.ids[tostring(num)]=true
return tostring(num)
end
function net.inList(list,dat)
for i,v in pairs(list) do
if v==dat then
return true
end
end
return false
end
function net.setTrigger(funcW,funcE)
multi:newTrigger(func)
end
-- UDP Stuff
function net:newServer(port,servercode)
local c={}
c.udp=assert(socket.udp())
c.udp:settimeout(0)
c.udp:setsockname("*", port)
c.ips={}
c.Type="udp"
c.port=port
c.ids={}
c.servercode=servercode
c.bannedIPs={}
c.bannedCIDs={}
function c:setUpdateRate(n)
print("Not needed in a udp server!")
end
function c:banCID(cid)
table.insert(self.bannedCIDs,cid)
end
function c:banIP(ip)
table.insert(self.bannedIPs,cid)
end
function c:send(ip,data,port,cid)
if self.servercode then
cid=cid or self:CIDFrom(ip,port)
if not self.ips[cid] then
print("Can't determine cid from client... sending the client a new one!")
local cid=net.resolveID(self)
print("Sending unique cid to client: "..cid)
self.ips[cid]={ip,port,0,self.servercode==nil}
print(ip)
self.udp:sendto("I!"..cid,ip,port)
if self.servercode then
self.udp:sendto("S!",ip,port)
end
return
end
if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then
self.udp:sendto("BANNED CLIENT", ip, port or self.port)
elseif self.ips[cid][4] then
self.udp:sendto(data, ip, port or self.port)
elseif self.ips[cid][4]==false then
self.udp:sendto("Make sure your server code is correct!", ip, port)
end
else
self.udp:sendto(data, ip, port or self.port)
end
end
function c:pollClientModules(ip,port)
self:send(ip,"L!",port)
end
function c:CIDFrom(ip,port)
for i,v in pairs(self.ips) do
if(ip==v[1] and v[2]==port) then
return i
end
end
end
function c:sendAll(data)
for i,v in pairs(self.ips) do
self:send(v[1],data,v[2],i)
end
end
function c:sendAllBut(data,cid)
for i,v in pairs(self.ips) do
if i~=cid then
self:send(v[1],data,v[2],i)
end
end
end
function c:clientRegistered(cid)
return self.ips[cid]
end
function c:clientLoggedIn(cid)
if not self.clientRegistered(cid) then
return nil
end
return self.ips[cid][4]
end
function c:update()
local data,ip,port=self.udp:receivefrom()
if net.inList(self.bannedIPs,ip) or net.inList(self.bannedCIDs,cid) then
print("We will ingore data from a banned client!")
return
end
if data then
if data:sub(1,4)=="pong" then
print("Recieved pong from: "..data:sub(5,-1))
self.ips[data:sub(5,-1)][3]=os.clock()
elseif data:sub(1,2)=="S!" then
local cid=self:CIDFrom(ip,port)
if data:sub(3,-1)==self.servercode then
print("Servercode Accepted: "..self.servercode)
if self.ips[cid] then
self.ips[cid][4]=true
else
print("Server can't keep up! CID: "..cid.." has been skipped! Sending new CID to the client!")
local cid=net.resolveID(self)
print("Sending unique cid to client: "..cid)
self.ips[cid]={ip,port,0,self.servercode==nil}
print(ip)
self.udp:sendto("I!"..cid,ip,port)
if self.servercode then
self.udp:sendto("S!",ip,port)
end
end
else
self.udp:sendto("Make sure your server code is correct!", ip, port)
end
elseif data:sub(1,2)=="C!" then
self.OnDataRecieved:Fire(self,data:sub(11,-1),data:sub(3,10),ip,port)
elseif data:sub(1,2)=="E!" then
self.ips[data:sub(3,10)]=nil
obj.ids[data:sub(3,10)]=false
self.OnClientClosed:Fire(self,"Client Closed Connection!",data:sub(3,10),ip,port)
elseif data=="I!" then
local cid=net.resolveID(self)
print("Sending unique cid to client: "..cid)
self.ips[cid]={ip,port,os.clock(),self.servercode==nil}
print(ip)
self.udp:sendto("I!"..cid,ip,port)
if self.servercode then
self.udp:sendto("S!",ip,port)
end
elseif data:sub(1,2)=="L!" then
cid,cList=data:sub(3,10),data:sub(11,-1)
local list={}
for m,v in cList:gmatch("(%S-):(%S-)|") do
list[m]=v
end
self.OnClientsModulesList:Fire(list,cid,ip,port)
end
end
for cid,dat in pairs(self.ips) do
if not((os.clock()-dat[3])<65) then
self.ips[cid]=nil
self.OnClientClosed:Fire(self,"Client lost Connection: ping timeout",cid,ip,port)
end
end
end
c.OnClientsModulesList=multi:newConnection()
c.OnDataRecieved=multi:newConnection()
c.OnPongRecieved=multi:newConnection()
c.OnClientClosed=multi:newConnection()
c.connectiontest=multi:newAlarm(30)
c.connectiontest.link=c
c.connectiontest:OnRing(function(alarm)
print("pinging clients!")
alarm.link:sendAll("ping")
alarm:Reset()
end)
multi:newLoop(function()
c:update()
end)
net.OnServerCreated:Fire(c)
return c
end
function net:newClient(host,port,servercode,nonluaServer)
local c={}
c.ip=assert(socket.dns.toip(host))
c.udp=assert(socket.udp())
c.udp:setpeername(c.ip, port)
c.udp:settimeout(0)
c.cid="NIL"
c.lastPing=0
c.Type="udp"
c.servercode=servercode
c.autoReconnect=true
function c:pollPing(n)
return not((os.clock()-self.lastPing)<(n or 60))
end
function c:send(data)
self.udp:send("C!"..self.cid..data)
end
function c:sendRaw(data)
self.udp:send(data)
end
function c:getCID()
if self:IDAssigned() then
return self.cid
end
end
function c:close()
self:send("E!")
end
function c:IDAssigned()
return self.cid~="NIL"
end
function c:update()
local data=self.udp:receive()
if data then
if data:sub(1,2)=="I!" then
self.cid=data:sub(3,-1)
self.OnClientReady:Fire(self)
elseif data=="S!" then
self.udp:send("S!"..(self.servercode or ""))
elseif data=="L!" then
local mods=""
local m=""
for i=1,#net.loadedModules do
m=net.loadedModules[i]
mods=mods..m..":"..net.getModuleVersion(m).."|"
end
self.udp:send("L!"..self.cid..mods)
elseif data=="ping" then
self.lastPing=os.clock()
self.OnPingRecieved:Fire(self)
self.udp:send("pong"..self.cid)
else
self.OnDataRecieved:Fire(self,data)
end
end
end
function c:reconnect()
if not nonluaServer then
self.cid="NIL"
c.udp:send("I!")
end
end
c.pingEvent=multi:newEvent(function(self) return self.link:pollPing() end)
c.pingEvent:OnEvent(function(self)
if self.link.autoReconnect then
self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout! Attempting to reconnect...")
self.link:reconnect()
else
self.link.OnServerNotAvailable:Fire("Connection to server lost: ping timeout!")
end
end)
c.pingEvent.link=c
c.OnPingRecieved=multi:newConnection()
c.OnDataRecieved=multi:newConnection()
c.OnServerNotAvailable=multi:newConnection()
c.OnClientReady=multi:newConnection()
c.notConnected=multi:newFunction(function(self)
self:hold(3)
if self.link:IDAssigned()==false then
self.link.OnServerNotAvailable:Fire("Can't connect to the server: no response from server")
end
end)
c.notConnected.link=c
if not nonluaServer then
c.udp:send("I!")
end
multi:newLoop(function()
c:update()
end)
multi:newJob(function() c.notConnected() end)
net.OnClientCreated:Fire(c)
return c
end
--TCP Stuff
function net:newTCPServer(port)
local c={}
c.tcp=assert(socket.bind("*", port))
c.tcp:settimeout(0)
c.ip,c.port=c.tcp:getsockname()
c.ips={}
c.port=port
c.ids={}
c.bannedIPs={}
c.Type="tcp"
c.rMode="*l"
c.sMode="*l"
c.updaterRate=1
function c:setUpdateRate(n)
self.updaterRate=n
end
function c:setReceiveMode(mode)
self.rMode=mode
end
function c:setSendMode(mode)
self.rMode=mode
end
function c:banCID(cid)
print("Function not supported on a tcp server!")
end
function c:banIP(ip)
table.insert(self.bannedIPs,cid)
end
function c:send(handle,data)
if self.sMode=="*l" then
handle:send(data.."\n")
else
handle:send(data)
end
end
function c:pollClientModules(ip,port)
self:send(ip,"L!",port)
end
function c:CIDFrom(ip,port)
print("Method not supported when using a TCP Server!")
return "CIDs in TCP work differently!"
end
function c:sendAll(data)
for i,v in pairs(self.ips) do
self:send(v,data)
end
end
function c:sendAllBut(data,cid)
for i,v in pairs(self.ips) do
if not(cid==i) then
self:send(v,data)
end
end
end
function c:clientRegistered(cid)
return self.ips[cid]
end
function c:clientLoggedIn(cid)
return self.ips[cid]
end
function c:update()
local client = self.tcp:accept(self.rMode)
if not client then return end
table.insert(self.ips,client)
client:settimeout(0)
--client:setoption('tcp-nodelay', true)
client:setoption('keepalive', true)
ip,port=client:getpeername()
if ip and port then
print("Got connection from: ",ip,port)
local updater=multi:newUpdater(skip)
updater:OnUpdate(function(self)
local data, err = self.client:receive(self.Link.rMode)
if err=="closed" then
for i=1,#self.Link.ips do
if self.Link.ips[i]==self.client then
table.remove(self.Link.ips,i)
end
end
self.Link.OnClientClosed:Fire(self.Link,"Client Closed Connection!",self.client,self.client,ip)
self:Destroy()
end
if data then
if net.inList(self.Link.bannedIPs,ip) then
print("We will ingore data from a banned client!")
return
end
self.Link.OnDataRecieved:Fire(self.Link,data,self.client,self.client,ip)
if data:sub(1,2)=="L!" then
cList=data
local list={}
for m,v in cList:gmatch("(%S-):(%S-)|") do
list[m]=v
end
self.Link.OnClientsModulesList:Fire(list,self.client,self.client,ip)
end
end
end)
updater:setSkip(self.updaterRate)
updater.client=client
updater.Link=self
end
end
c.OnClientsModulesList=multi:newConnection()
c.OnDataRecieved=multi:newConnection()
c.OnClientClosed=multi:newConnection()
multi:newLoop(function()
c:update()
end)
net.OnServerCreated:Fire(c)
return c
end
function net:newTCPClient(host,port)
local c={}
c.ip=assert(socket.dns.toip(host))
c.port=post
c.tcp=socket.connect(c.ip,port)
if not c.tcp then
print("Can't connect to the server: no response from server")
return false
end
c.tcp:settimeout(0)
c.tcp:setoption('tcp-nodelay', true)
c.tcp:setoption('keepalive', true)
c.Type="tcp"
c.autoReconnect=true
c.rMode="*l"
c.sMode="*l"
function c:setReceiveMode(mode)
self.rMode=mode
end
function c:setSendMode(mode)
self.sMode=mode
end
function c:send(data)
if self.sMode=="*l" then
self.tcp:send(data.."\n")
else
self.tcp:send(data)
end
end
function c:sendRaw(data)
self.tcp:send(data)
end
function c:getCID()
return "No Cid on a tcp client!"
end
function c:close()
self.tcp:close()
end
function c:IDAssigned()
return true
end
function c:update()
local data=self.tcp:receive()
if data then
self.OnDataRecieved:Fire(self,data)
end
end
function c:reconnect()
self.ip=assert(socket.dns.toip(host))
self.tcp=socket.connect(self.ip,self.port)
if not self.tcp then
print("Can't connect to the server: no response from server")
return
end
self.tcp:settimeout(0)
self.tcp:setoption('tcp-nodelay', true)
self.tcp:setoption('keepalive', true)
end
c.event=multi:newEvent(function(event)
return event.link:IDAssigned()
end)
c.event:OnEvent(function(event)
event.link.OnClientReady:Fire(event.link)
end)
c.event.link=c
c.OnClientReady=multi:newConnection()
c.OnDataRecieved=multi:newConnection()
multi:newLoop(function()
c:update()
end)
net.OnClientCreated:Fire(c)
return c
end

179
client/net/sft.lua Normal file
View File

@ -0,0 +1,179 @@
require("net")
--General Stuff
--[[ What this module does!
Adds
]]
function io.fileExists(path)
g=io.open(path or '','r')
if path =='' then
p='empty path'
return nil
end
if g~=nil and true or false then
p=(g~=nil and true or false)
end
if g~=nil then
io.close(g)
else
return false
end
return p
end
net:registerModule("sft",{1,0,0})
function net.sft:init() -- calling this initilizes the library and binds it to the servers and clients created
--Server Stuff
net.OnServerCreated:connect(function(s)
print("The sft(Simple File Transfer) Module has been loaded onto the server!")
if s.Type~="tcp" then
print("It is recomended that you use tcp to transfer files!")
end
s.transfers={}
s.OnUploadRequest=multi:newConnection() -- create a sft event
s.OnFileUploaded=multi:newConnection() -- create a sft event
s.OnDownloadRequest=multi:newConnection()
s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
--First Lets make sure we are getting sft data
--filename,dat=data:match("!sft! (%S-) (%S+)")
local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)")
if cmd=="tstart" then
local rets=self.OnUploadRequest:Fire(self,cid,ip,port)
for i=1,#rets do
if rets[i][1]==false then
print("Server refused to accept upload request!")
self:send(ip,"!sft! CANTUPLOAD NIL NIL",port)
return
end
end
local ID,streamable=arg1:match("(.+)|(.+)")
local file,hash=arg2:match("(.+)|(.+)")
if streamable~="NIL" then
self.transfers[ID]={bin.stream(streamable,false),hash,file}
else
self.transfers[ID]={bin.new(""),hash,file}
end
return
elseif cmd=="transfer" then
if self.transfers[arg1]~=nil then
self.transfers[arg1][1]:tackE(bin.fromhex(arg2))
--print(self.transfers[arg1][1]:getSize())
end
return
elseif cmd=="tend" then
if self.transfers[arg1]~=nil then
if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then
self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!")
else
print("Hash Error!")
self.OnFileUploaded:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!")
end
self.transfers[arg1]=nil
end
return
end
local filename=cmd
local dat=arg1
if filename==nil then return end
local rets=self.OnDownloadRequest:Fire(self,cid,ip,port)
for i=1,#rets do
if rets[i][1]==false then
print("Server refused to accept download request!")
self:send(ip,"!sft! CANTREQUEST NIL NIL",port)
return
end
end
if io.fileExists(filename) then
--Lets first load the file
local file=bin.stream(filename,false)
local size=file:getSize()
local pieceSize=512
local pieces=math.ceil(size/pieceSize)
local step=multi:newStep(1,pieces)
step.TransferID=tostring(math.random(1000,9999))
step.sender=self
step.ip=ip
step.port=port
step.pieceSize=pieceSize
step:OnStart(function(self)
self.sender:send(self.ip,"!sft! TSTART "..self.TransferID.."|"..dat.." "..filename.."|"..file:getHash(32),self.port)
end)
step:OnStep(function(pos,self)
self:hold(.01)
self.sender:send(self.ip,"!sft! TRANSFER "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos)),self.port)
end)
step:OnEnd(function(self)
self.sender:send(self.ip,"!sft! TEND "..self.TransferID.." NIL",self.port)
end)
else
self:send(ip,"!sft! CANTREQUEST NIL NIL",port)
end
end)
end)
--Client Stuff
net.OnClientCreated:connect(function(c)
c.transfers={}
c.OnTransferStarted=multi:newConnection() -- create a sft event
c.OnTransferFinished=multi:newConnection() -- create a sft event
c.OnFileRequestFailed=multi:newConnection() -- create a sft event
c.OnFileUploadFailed=multi:newConnection() -- create a sft event
c.OnDataRecieved:connect(function(self,data) -- when the client recieves data this method is triggered
--First Lets make sure we are getting sft data
local cmd,arg1,arg2=data:match("!sft! (%S-) (%S-) (.+)")
if cmd=="TSTART" then
local ID,streamable=arg1:match("(.+)|(.+)")
local file,hash=arg2:match("(.+)|(.+)")
if streamable~="NIL" then
self.transfers[ID]={bin.stream(streamable,false),hash,file}
else
self.transfers[ID]={bin.new(""),hash,file}
end
self.OnTransferStarted:Fire(self)
elseif cmd=="TRANSFER" then
self.transfers[arg1][1]:tackE(bin.fromhex(arg2))
elseif cmd=="TEND" then
if self.transfers[arg1][1]:getHash(32)==self.transfers[arg1][2] then
self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Good!")
else
print("Hash Error!")
self.OnTransferFinished:Fire(self,self.transfers[arg1][1],self.transfers[arg1][3],"Hash Bad!")
end
self.transfers[arg1]=nil
elseif cmd=="CANTREQUEST" then
self.OnFileRequestFailed:Fire(self,"Could not request the file for some reason!")
elseif cmd=="CANTUPLOAD" then
self.OnFileUploadFailed:Fire(self,"Could not upload the file for some reason!")
end
end)
function c:uploadFile(filename)
if io.fileExists(filename) then
local file=bin.stream(filename,false)
local size=file:getSize()
local pieceSize=512
local pieces=math.ceil(size/pieceSize)
local step=multi:newStep(1,pieces)
step.TransferID=tostring(math.random(1000,9999))
step.sender=self
step.pieceSize=pieceSize
step:OnStart(function(self)
self.sender:send("!sft! tstart "..self.TransferID.."|NIL "..filename.."|"..file:getHash(32))
end)
step:OnStep(function(pos,self)
self:hold(.01)
self.sender:send("!sft! transfer "..self.TransferID.." "..bin.tohex(file:sub(((self.pieceSize*pos)+1)-self.pieceSize,self.pieceSize*pos)))
end)
step:OnEnd(function(self)
print("Request done!")
self.sender:send("!sft! tend "..self.TransferID.." NIL")
end)
else
self.OnFileUploadFailed:Fire(self,filename,"File does not exist!")
end
end
function c:requestFile(filename)
self:send("!sft! "..filename.." NIL NIL NIL")
end
end)
end
if net.autoInit then
net.sft.init()
end

BIN
client/them.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
client/you.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB