Add projects including README.md(s), .gitignore(s) and the actual project files.

Signed-off-by: Michael Fabian Dirks <michael.dirks@project-kube.de>
This commit is contained in:
Michael Fabian Dirks
2014-11-24 18:18:24 +01:00
parent 934da62076
commit 8f3114e377
170 changed files with 22028 additions and 3 deletions
+6
View File
@@ -0,0 +1,6 @@
# Binary Files
*.o
*.a
*.exe
*/.bmx
*/.indevIDE
@@ -0,0 +1,124 @@
Strict
Import BRL.Stream
Import BRL.Retro
Function FileMD5$(filePath$, bufferSize=$400000)
Assert (bufferSize & 63) = 0 Else "bufferSize must be a multiple of 64 bytes"
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476
Local r[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
Local k[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A,..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]
Local fileStream:TStream = OpenStream(filePath$, True, False)
If fileStream = Null Then Return
Local buffer:Byte Ptr = MemAlloc(bufferSize)
Local bitCount:Long, dataTop = bufferSize
Repeat
Local bytesRead = fileStream.Read(buffer, bufferSize)
If fileStream.EOF()
dataTop = (((bytesRead + 8) Shr 6) + 1) Shl 6
If dataTop > bufferSize
buffer = MemExtend(buffer, bufferSize, dataTop)
EndIf
bitCount :+ (bytesRead Shl 3)
For Local b = (bytesRead + 1) Until (dataTop - 8)
buffer[b] = 0
Next
buffer[bytesRead] = $80
LEPokeLong(buffer, dataTop - 8, bitCount)
Else
bitCount :+ (bufferSize Shl 3)
EndIf
For Local chunkStart=0 Until (dataTop Shr 2) Step 16
Local a = h0, b = h1, c = h2, d = h3
For Local i=0 To 15
Local f = d ~ (b & (c ~ d))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + i) Shl 2)), r[i]) + b
a = t
Next
For Local i=16 To 31
Local f = c ~ (d & (b ~ c))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + (((5 * i) + 1) & 15)) Shl 2)), r[i]) + b
a = t
Next
For Local i=32 To 47
Local f = b ~ c ~ d
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + (((3 * i) + 5) & 15)) Shl 2)), r[i]) + b
a = t
Next
For Local i=48 To 63
Local f = c ~ (b | ~d)
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + ((7 * i) & 15)) Shl 2)), r[i]) + b
a = t
Next
h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next
Until fileStream.EOF()
fileStream.Close()
MemFree(buffer)
Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3)).ToLower()
End Function
Function Rol(val, shift)
Return (val Shl shift) | (val Shr (32 - shift))
End Function
Function LEPeekInt(buffer:Byte Ptr, offset)
Return (buffer[offset + 3] Shl 24) | (buffer[offset + 2] Shl 16) | ..
(buffer[offset + 1] Shl 8) | buffer[offset]
End Function
Function LEPokeLong(buffer:Byte Ptr, offset, value:Long)
For Local b=7 To 0 Step -1
buffer[offset + b] = (value Shr (b Shl 3)) & $ff
Next
End Function
Function LEHex$(val)
Local out$ = Hex(val)
Return out$[6..8] + out$[4..6] + out$[2..4] + out$[0..2]
End Function
@@ -0,0 +1,197 @@
'Function DebugProgressCB:Int(data:Object,dltotal:Double,dlnow:Double,ultotal:Double,ulnow:Double)
' DebugLog "dltotal="+Int(dltotal)+",dlnow="+Int(dlnow)+",ultotal="+Int(ultotal)+",ulnow="+Int(ulnow)
'EndFunction
Rem
Type TTaskPatchCheck Extends TTaskPatch
Field m_stFile:String
Field m_stHash:String
Field l_bValid:Byte = True
Method Run()
' Retrieve Hash
Local stHash:String = FileMD5(m_stFile).ToUpper();l_fProgress = 0.5
' Compare Hash
If stHash <> m_stHash Then
l_bValid = False
oPatchListMutex.Lock()
oPatchList.AddLast(m_stFile)
oPatchListMutex.Unlock()
EndIf
l_fProgress = 1.0
EndMethod
Function Create:TTask(File:String, Hash:String)
Local oTask:TTaskPatchCheck = New TTaskPatchCheck
oTask.m_stFile = File
oTask.m_stHash = Hash
Return oTask
EndFunction
EndType
Type TTaskPatchFile Extends TTaskPatch
Field m_stFile:String
Method Run()
Local oCurl:TCurlEasy = New TCurlEasy
oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
oCurl.setOptString(CURLOPT_REFERER, TPatcher_Server)
oCurl.setOptString(CURLOPT_URL, TPatcher_Server + m_stFile)
oCurl.setWriteString()
EndMethod
Function Create:TTask(File:String)
Local oTask:TTaskPatchFile = New TTaskPatchFile
oTask.m_stFile = File
Return oTask
EndFunction
EndType
Rem
Import BRL.LinkedList
Const TPatcher_MaxParallelTasks:Int = 4
Const TPatcher_Server:String = "http://sirius-online.us.to/patch/"
Type TPatcher
' TCurlMulti Instance for non-blocking IO.
Field oCurlMulti:TCurlMulti = TCurlMulti.Create()
' List of available tasks and active tasks.
Field oTasks:TList = (New TList)
Field oTaskSlots:TTaskSlot[] = New TTaskSlot[TPatcher_MaxParallelTasks]
Field oTasksDone:TList = (New TList)
Method New()
For Local i:Int = 0 Until TPatcher_MaxParallelTasks
oTaskSlots[i].oCurl = oCurlMulti.newEasy()
next
oTasks.AddLast(TTask_PatchInfo.Create())
EndMethod
' Main loop for TPatcher
Method Perform()
Local runningHandles:Int
If oTaskSlots[0].oTask <> Null or oTaskSlots[1].oTask <> Null or oTaskSlots[2].oTask <> Null or oTaskSlots[3].oTask <> Null Then
Local iResult:Int = CURLM_OK
Repeat
iResult = oCurlMulti.multiPerform(runningHandles)
For Local slot:Int = 0 Until TPatcher_MaxParallelTasks
If oTaskSlots[slot].oTask = Null And oTasks.Count() > 0 Then
oTaskSlots[slot].oTask = TTask(oTasks.RemoveLast())
oTaskSlots[slot].oTask.Initialize(Self, oTaskSlots[slot].oCurl)
ElseIf oTaskSlots[slot].oTask <> Null Then
If oTaskSlots[slot].oTask.bComplete = True Then
oTasksDone.AddLast(oTaskSlots[slot].oTask)
oTaskSlots[slot].oTask = Null
' Restore TCurlEasy to useable state.
oCurlMulti.multiRemove(oTaskSlots[slot].oCurl)
oTaskSlots[slot].oCurl.cleanup()
oCurlMulti.multiAdd(oTaskSlots[slot].oCurl)
EndIf
Endif
Next
Until iResult <> CURLM_CALL_MULTI_PERFORM
Else
oCurlMulti.cleanup()
EndIf
EndMethod
EndType
Type TTaskSlot
Field oTask:TTask
Field oCurl:TCurlEasy
EndType
Type TTask Abstract
Field oPatcher:TPatcher = Null
Field stName:String = "Unknown"
Field bComplete:Byte = False
Field fProgress:Float = 0.0
Method Initialize(oPatcher:TPatcher, oCurl:TCurlEasy)
Self.oPatcher = oPatcher
oCurl.setWriteCallback(_HandleWriteCallback, Self)
oCurl.setProgressCallback(_HandleProgressCallback, Self)
EndMethod
Method HandleProgressCallback:Int(dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
fProgress = dlnow / dltotal
If dlnow = dltotal Then bComplete = True
EndMethod
Method HandleWriteCallback:Int(buffer:Byte Ptr, size:Int)
EndMethod
Function _HandleProgressCallback:Int(Data:Object, dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
Local Task:TTask = TTask(Data)
Return Task.HandleProgressCallback(dltotal, dlnow, ultotal, ulnow)
EndFunction
Function _HandleWriteCallback(buffer:Byte Ptr, size:Int, Data:Object)
Local Task:TTask = TTask(Data)
Return Task.HandleWriteCallback(buffer, size)
EndFunction
EndType
Type TTask_PatchInfo Extends TTask
Method New()
Self.stName = "Retrieving Patch Information"
EndMethod
Method Initialize(oPatcher:TPatcher, oCurl:TCurlEasy)
Super.Initialize(oPatcher, oCurl)
oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
oCurl.setOptString(CURLOPT_REFERER, TPatcher_Server)
oCurl.setOptString(CURLOPT_URL, TPatcher_Server + "info")
oCurl.setWriteString()
EndMethod
Method HandleProgressCallback:Int(dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
Super.HandleProgressCallback()
If bComplete = True Then
EndIf
EndMethod
Function Create:TTask()
Return (New TTask_PatchInfo)
EndFunction
EndType
Type TTask_File Extends TTask
Field stHash:String
Field stFile:String
Method Initialize(oPatcher:TPatcher, oCurl:TCurlEasy)
Super.Initialize(oPatcher, oCurl)
oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
oCurl.setOptString(CURLOPT_REFERER, TPatcher_Server + "info")
'Local oFileStream:TStream =
oCurl.setWriteString()
EndMethod
Method HandleProgressCallback:Int(dltotal:Double, dlnow:Double, ultotal:Double, ulnow:Double)
Super.HandleProgressCallback()
EndMethod
Function Create:TTask(File:String, Hash:String)
Local oTask:TTask_File = New TTask_File
oTask.stHash = Hash
oTask.stFile = File
oCurl.setOptString(CURLOPT_URL, TPatcher_Server + oTask.File)
Return oTask
EndFunction
EndType
EndRem
@@ -0,0 +1,242 @@
SuperStrict
Import BRL.Threads
Import BRL.LinkedList
Import BRL.StandardIO
Const DEF_THREADPOOL_MINTHREADS:Int = 1
Const DEF_THREADPOOL_MAXTHREADS:Int = 4
Type TThreadPool
' Threads
Field m_oThreads:TList = New TList
Field m_iMinThreads:Int = DEF_THREADPOOL_MINTHREADS
Field m_iMaxThreads:Int = DEF_THREADPOOL_MAXTHREADS
' Task Queue
Field m_oTaskList:TList = New TList
Field m_oTaskMutex:TMutex = TMutex.Create()
' Construction
Function Create:TThreadPool(iMinThreads:Int = DEF_THREADPOOL_MINTHREADS, iMaxThreads:Int = DEF_THREADPOOL_MAXTHREADS)
Local oThreadPool:TThreadPool = New TThreadPool
oThreadPool.SetLimits(iMinThreads, iMaxThreads)
Return oThreadPool
EndFunction
' Destruction
Method Destroy()
For Local oThreadWorker:TThreadWorker = EachIn m_oThreads
oThreadWorker.ForceDestroy()
Next
m_oThreads.Clear()
m_oTaskList.Clear()
EndMethod
' Change the thread limits, for example when the game configuration changes. Effective immediately or after
Method SetLimits(iMinThreads:Int = DEF_THREADPOOL_MINTHREADS, iMaxThreads:Int = DEF_THREADPOOL_MAXTHREADS)
m_iMinThreads = iMinThreads
If (iMaxThreads < iMinThreads) Then iMaxThreads = iMinThreads
m_iMaxThreads = iMaxThreads
EndMethod
' Add new Task to the queue.
Method AddTask(oTask:TTask)
m_oTaskMutex.Lock()
m_oTaskList.AddLast(oTask)
m_oTaskMutex.Unlock()
EndMethod
' Distributes work across threads, destroys and spawns threads
Method Update:Int()
Local iThreadCount:Int = m_oThreads.Count()
' Spawn more Threads if we don't have at least m_iMinThreads
If iThreadCount < m_iMinThreads Then
Local iSpawnCount:Int = m_iMinThreads - iThreadCount
For Local spawn:Int = 1 To iSpawnCount
m_oThreads.AddLast(New TThreadWorker)
iThreadCount :+ 1
Next
EndIf
For Local oThreadWorker:TThreadWorker = EachIn m_oThreads
' Loosely enforce m_iMaxThreads by destroying unused Threads.
If iThreadCount > m_iMaxThreads And oThreadWorker.m_oAvailable.TryLock() = True Then
If oThreadWorker.m_oTask = Null Then
oThreadWorker.m_oAvailable.Unlock()
oThreadWorker.Destroy()
m_oThreads.Remove(oThreadWorker)
iThreadCount :- 1
Exit
EndIf
EndIf
' Distribute available work.
m_oTaskMutex.Lock()
If m_oTaskList.Count() > 0 And oThreadWorker.m_oAvailable.TryLock() = True Then
oThreadWorker.m_oAvailable.Unlock()
Local oTask:TTask = TTask(m_oTaskList.RemoveFirst())
If oThreadWorker.AssignTask(oTask) = False Then m_oTaskList.AddLast(oTask)
EndIf
m_oTaskMutex.Unlock()
' Destroy Threads that have been waiting too long on Work, given that they are unneeded.
If iThreadCount > m_iMinThreads And oThreadWorker.m_oAvailable.TryLock() = True Then
oThreadWorker.m_oAvailable.Unlock()
If oThreadWorker.m_oTask = Null And (MilliSecs() - oThreadWorker.m_lTaskTime) > 5000 Then
m_oThreads.Remove(oThreadWorker)
oThreadWorker.Destroy()
iThreadCount :- 1
EndIf
EndIf
Next
' Spawn more Threads if we did not hit m_iMaxThreads and there is still work left.
m_oTaskMutex.Lock()
If m_oTaskList.Count() > 0 And iThreadCount < m_iMaxThreads Then
Local iSpawnCount:Int = Min(m_oTaskList.Count(), m_iMaxThreads - iThreadCount)
For Local spawn:Int = 1 To iSpawnCount
m_oThreads.AddLast(New TThreadWorker)
iThreadCount :+ 1
Next
EndIf
m_oTaskMutex.Unlock()
Return iThreadCount
EndMethod
Method CountTasks:Int()
Local retVal:Int = 0
m_oTaskMutex.Lock()
retVal = m_oTaskList.Count()
m_oTaskMutex.Unlock()
Return retVal
EndMethod
Method CountActiveTasks:Int()
Local retVal:Int = 0
For Local oThreadWorker:TThreadWorker = EachIn m_oThreads
oThreadWorker.m_oAvailable.Lock()
If oThreadWorker.m_oTask <> Null Then retVal :+ 1
oThreadWorker.m_oAvailable.Unlock()
Next
Return retVal
EndMethod
EndType
Type TThreadWorker
Field m_oThread:TThread
' Used to make the Thread sleep and work.
Field m_oAvailable:TMutex
Field m_oCondVar:TCondVar
' Contains Task and the time it was assigned at.
Field m_oTask:TTask
Field m_lTaskTime:Long
Field d_iCount:Int
' Construction
Method New()
m_oAvailable = TMutex.Create()
m_oCondVar = TCondVar.Create()
m_oThread = TThread.Create(Execute, Self)
m_lTaskTime = MilliSecs()
EndMethod
' Destruction
Method Destroy()
While AssignTask(oTaskTerminate) = False
Delay 10
Wend
m_oThread.Wait() 'broken?
m_oThread.Detach()
EndMethod
Method ForceDestroy()
m_oThread.Detach()
EndMethod
' Task Management
Method AssignTask:Int(oTask:TTask)
If m_oAvailable.TryLock() = True And m_oTask = Null Then
m_oTask = oTask
m_lTaskTime = MilliSecs()
m_oAvailable.Unlock()
m_oCondVar.Signal()
Return True
EndIf
Return False
EndMethod
' Thread Wrapper Function
Function Execute:Object(Data:Object)
Local oThreadWorker:TThreadWorker = TThreadWorker(Data)
Local oTask:TTask = Null
oThreadWorker.m_oAvailable.Lock()
Repeat
oThreadWorker.m_oCondVar.Wait(oThreadWorker.m_oAvailable)
If oThreadWorker.m_oTask <> Null Then
oThreadWorker.d_iCount :+ 1
oTask = oThreadWorker.m_oTask
oThreadWorker.m_oAvailable.Unlock()
oTask.Run()
oThreadWorker.m_oAvailable.Lock()
oThreadWorker.m_oTask = Null
EndIf
Until oTask = oTaskTerminate
oThreadWorker.m_oAvailable.Unlock()
EndFunction
EndType
Type TTask Abstract
' Called when a thread is working on this item.
Method Run()
EndMethod
EndType
Type TTaskTerminate Extends TTask
EndType
Global oTaskTerminate:TTask = New TTaskTerminate
Type TTaskPtr Extends TTask
Field m_pFunc:Object(data:Object)
Field m_pData:Object
Field m_pReturn:Object
' Construction
Function Create:TTask(pFunc:Object(data:Object), pData:Object)
Local oTWPtr:TTaskPtr = New TTaskPtr
oTWPtr.SetFunction(pFunc)
oTWPtr.SetData(pData)
Return oTWPtr
EndFunction
' Called when a thread is working on this item.
Method Run()
m_pReturn = m_pFunc(m_pData)
EndMethod
' Set the Function executed by Run()
Method SetFunction(pFunc:Object(data:Object))
m_pFunc = pFunc
EndMethod
' Set the Data passed to the Function.
Method SetData(pData:Object)
m_pData = pData
EndMethod
' Retrieve the return value of the executed Function
Method GetReturn:Object()
Return m_pReturn
EndMethod
EndType
Global PrintMutex:TMutex = TMutex.Create()
Function _Print(Str:String)
PrintMutex.Lock()
Print(Str)
PrintMutex.Unlock()
EndFunction
+14
View File
@@ -0,0 +1,14 @@
#include <brl.mod/blitz.mod/blitz.h>
#include <time.h>
int getClocksPerSecond_() {
return CLOCKS_PER_SEC;
}
int getClock_() {
return (int)clock();
}
int getClockDiff_(int clockStart, int clockEnd) {
return ((clock_t)clockEnd - (clock_t)clockStart);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 KiB

@@ -0,0 +1,488 @@
SuperStrict
' Modules and Includes -----------------------------------------------------------------------------------------------------------------------------------------
Framework BRL.Blitz
Import BRL.StandardIO
Import BRL.Timer
Import BRL.Max2D
Import BRL.GLMax2D
Import BRL.Event
Import BRL.EventQueue
Import PUB.FreeProcess
Import MaxGUI.MaxGUI
Import MaxGUI.Drivers
' Libraries
Import "TGUI.bmx"
Import "Max2DExtended.bmx"
' Resources -----------------------------------------------------------------------------------------------------------------------------------------------------
' Binary Resources
Incbin "GFX/LNC/GUIxSTYLE.png"
Incbin "SFX/M/launcher.ogg"
' Initialization ------------------------------------------------------------------------------------------------------------------------------------------------
SetGraphicsDriver(GLMax2DDriver())
' Create Timers to reduce CPU load.
Global tmrRender:TTimer = CreateTimer(20) ' One for rendering the GUI
Global tmrUpdate:TTimer = CreateTimer(100) ' And one for working.
' Create the Window and Canvas for the Patcher, set the Graphics Driver to OpenGL and enable polled input.
Global gdgPatcher:TGadget = CreateWindow("Sirius Online", 0, 0, 720, 460, Desktop(), WINDOW_CLIENTCOORDS | WINDOW_CENTER | WINDOW_HIDDEN)
Global gdgCanvas:TGadget = CreateCanvas(0, 0, ClientWidth(gdgPatcher), ClientHeight(gdgPatcher), gdgPatcher)
SetGraphics(gdgCanvas) ' Change OpenGL Context to the Canvas.
EnablePolledInput(gdgCanvas) ' Enable input handling for the Canvas.
DebugLog TShader.CheckCompatability()
End
Rem
' Load our GUI Style and split it into the required images.
Global guiStyle:TPixmap = LoadPixmap("GFX/LNC/GUIxSTYLE.png")
If guiStyle = Null Then guiStyle = LoadPixmap("incbin::GFX/LNC/GUIxSTYLE.png")
Global guiWindowBackground:TImage = LoadImage(guiStyle.Window(0, 0, 32, 32), FILTEREDIMAGE)
Global guiWindowShade:TImage[] = New TImage[2]
guiWindowShade[0] = LoadImage(guiStyle.Window(32, 0, 16, 16), FILTEREDIMAGE)
guiWindowShade[1] = LoadImage(guiStyle.Window(32, 16, 16, 16), FILTEREDIMAGE)
Global guiWindowTitleBar:TImage[] = New TImage[2]
guiWindowTitleBar[0] = LoadImage(guiStyle.Window(48, 0, 16, 16), FILTEREDIMAGE)
guiWindowTitleBar[1] = LoadImage(guiStyle.Window(48, 16, 16, 16), FILTEREDIMAGE)
Global guiSymbols:TImage[] = New TImage[8]
guiSymbols[0] = LoadImage(guiStyle.Window(64, 0, 16, 16), FILTEREDIMAGE) 'Close
guiSymbols[1] = LoadImage(guiStyle.Window(80, 0, 16, 16), FILTEREDIMAGE) 'Minimize
guiSymbols[2] = LoadImage(guiStyle.Window(96, 0, 16, 16), FILTEREDIMAGE) 'Maximize
guiSymbols[3] = LoadImage(guiStyle.Window(112, 0, 16, 16), FILTEREDIMAGE) 'Restore
guiSymbols[4] = LoadImage(guiStyle.Window(64, 16, 16, 16), FILTEREDIMAGE)
guiSymbols[5] = LoadImage(guiStyle.Window(80, 16, 16, 16), FILTEREDIMAGE)
guiSymbols[6] = LoadImage(guiStyle.Window(96, 16, 16, 16), FILTEREDIMAGE)
guiSymbols[7] = LoadImage(guiStyle.Window(112, 16, 16, 16), FILTEREDIMAGE)
Global guiButtonNormal:TImage[] = New TImage[3]
guiButtonNormal[0] = LoadImage(guiStyle.Window(0, 32, 16, 16), FILTEREDIMAGE)
guiButtonNormal[1] = LoadImage(guiStyle.Window(0, 48, 16, 16), FILTEREDIMAGE)
guiButtonNormal[2] = LoadImage(guiStyle.Window(0, 64, 16, 16), FILTEREDIMAGE)
Global guiButtonShaped:TImage[] = New TImage[3]
guiButtonShaped[0] = LoadImage(guiStyle.Window(16, 32, 16, 16), FILTEREDIMAGE)
guiButtonShaped[1] = LoadImage(guiStyle.Window(16, 48, 16, 16), FILTEREDIMAGE)
guiButtonShaped[2] = LoadImage(guiStyle.Window(16, 64, 16, 16), FILTEREDIMAGE)
Global guiProgressBar:TImage[] = New TImage[3]
guiProgressBar[0] = LoadImage(guiStyle.Window(16, 80, 16, 16), FILTEREDIMAGE)
guiProgressBar[1] = LoadImage(guiStyle.Window(16, 96, 16, 16), FILTEREDIMAGE)
guiProgressBar[2] = LoadImage(guiStyle.Window(16, 112, 16, 16), FILTEREDIMAGE)
EndRem
' Show the Patcher Window
ShowGadget gdgPatcher
' GUI Values
Const guiTitleHeight:Int = 24
Global guiWidth:Int = ClientWidth(gdgPatcher)
Global guiHeight:Int = ClientHeight(gdgPatcher)
Global guiActive:Int = True
' Main Loop -----------------------------------------------------------------------------------------------------------------------------------------------------
Repeat
WaitEvent()
Select EventSource()
Case tmrRender
SetGraphics CanvasGraphics(gdgCanvas);Cls
Rem
' Draw GUI
SetColor(255, 255, 255); SetAlpha(1.0); SetBlend(SOLIDBLEND); SetScale(1.0, 1.0); SetRotation(0.0)
' Title Bar and Title
DrawTiledImage guiWindowTitleBar[guiActive], 0, 0, guiWidth, guiTitleHeight, 0, 0, 16, 16,,,,4,4,4,4, True, MODE_SCALEUPX | MODE_SCALEUPY
DrawText(GadgetText(gdgPatcher), 4, guiTitleHeight / 2 - (12 / 2))
' Content Background
DrawSubImageRectEx guiWindowBackground, 0, guiTitleHeight, guiWidth, guiHeight - guiTitleHeight, 0, 0, 32, 32,,,, MODE_REPEATX | MODE_REPEATY
SetBlend SHADEBLEND
DrawTiledImage guiContent[guiActive], 0, guiTitleHeight, guiWidth, guiHeight - guiTitleHeight, 0, 0, 16, 16,,,, 4, 4, 4, 4, True, MODE_REPEATX | MODE_REPEATY | MODE_SCALEUPX | MODE_SCALEUPY
EndRem
' Show the now rendered GUI
Flip False
Case gdgPatcher
Select EventID()
Case EVENT_WINDOWMODE, EVENT_WINDOWSIZE
' Update GUI Values {
guiWidth = ClientWidth(gdgPatcher)
guiHeight = ClientWidth(gdgPatcher)
' }
End Select
End Select
Forever
End
Rem
' Files
Import "Patcher.bmx"
'=====> Constants
?Win32
Const LAUNCHER_NAME:String = "Launcher.exe"
?Linux
Const LAUNCHER_NAME:String = "Launcher.bin"
?MacOS
Const LAUNCHER_NAME:String = "Launcher.app"
?
'=====> Parse Arguments
Global stProgram:String = AppArgs[0]
Global stProgramPath:String = ExtractDir(AppArgs[0])
Global stProgramName:String = StripDir(AppArgs[0])
Global bPatchLauncher:Byte = False
Global iPatchRetries:Int = 30
For Local stArgument:String = EachIn AppArgs[1..]
Local stArgName:String, stArgValue:String
' Skip arguments not starting with a dash
If stArgument[0..1] <> "-" Then Continue
Local iValuePos:Int = stArgument.Find("=")
If iValuePos >= 0 Then
stArgName = stArgument[1..iValuePos]
stArgValue = stArgument[iValuePos..]
Else
stArgName = stArgument[1..]
stArgValue = "1"
EndIf
Select stArgName
Case "patch"
bPatchLauncher = Byte(stArgValue)
Case "retry"
iPatchRetries = Int(stArgValue)
End Select
Next
'=====> Use parsed Arguments
'--> Patch the Launcher
If bPatchLauncher = True Then
Local iRetryCount:Int = 0
Local oRetryTimer:TTimer = TTimer.Create(10)
' Copy the newly downloaded Launcher file
If stProgramName <> LAUNCHER_NAME Then
If FileType(LAUNCHER_NAME) = FILETYPE_FILE Then
Repeat
oRetryTimer.Wait()
iRetryCount :+ 1
Until (DeleteFile(LAUNCHER_NAME) = True) or (iRetryCount > iPatchRetries)
EndIf
If FileType(LAUNCHER_NAME) = 0 Then
Repeat
oRetryTimer.Wait()
iRetryCount :+ 1
Until (CopyFile(stProgramName, LAUNCHER_NAME) = True) or (iRetryCount > iPatchRetries)
If FileType(LAUNCHER_NAME) = FILETYPE_FILE Then
Local oProcess:TProcess = CreateProcess(LAUNCHER_NAME)
TProcess.ProcessList.Remove oProcess
End
Else
Notify("Error: Failed to replace Launcher", True)
End
EndIf
Else
Notify("Error: Failed to delete old Launcher", True)
End
EndIf
EndIf
EndIf
' Resources: Create Variables that store resources.
Global riMainBackground:Int, imMainBackground:TImage;LoadResource("GFX/LNC/LAUxPATxB.png",, imMainBackground, riMainBackground)
Global riMainForeground:Int, imMainForeground:TImage;LoadResource("GFX/LNC/LAUxPATxA.png",, imMainForeground, riMainForeground)
Global riProgressBar:Int, imProgressBar:TImage; LoadResource("GFX/LNC/BARxPROGRESS.png",, imProgressBar, riProgressBar)
Global riButtonClose:Int, imButtonClose:TImage; LoadResource("GFX/LNC/BTNxCLOSE.png",, imButtonClose, riButtonClose)
Global riButtonAccount:Int, imButtonAccount:TImage; LoadResource("GFX/LNC/BTNxACCOUNT.png",, imButtonAccount, riButtonAccount)
Global riButtonWebsite:Int, imButtonWebsite:TImage; LoadResource("GFX/LNC/BTNxWEBSITE.png",, imButtonWebsite, riButtonWebsite)
Global riButtonSupport:Int, imButtonSupport:TImage; LoadResource("GFX/LNC/BTNxSUPPORT.png",, imButtonSupport, riButtonSupport)
Global riButtonEULATOS:Int, imButtonEULATOS:TImage; LoadResource("GFX/LNC/BTNxEULATOS.png",, imButtonEULATOS, riButtonEULATOS)
Global riButtonCheck:Int, imButtonCheck:TImage; LoadResource("GFX/LNC/BTNxCHECK.png",, imButtonCheck, riButtonCheck)
Global riButtonPatch:Int, imButtonPatch:TImage; LoadResource("GFX/LNC/BTNxPATCH.png",, imButtonPatch, riButtonPatch)
Global riButtonPlay:Int, imButtonPlay:TImage; LoadResource("GFX/LNC/BTNxPLAY.png",, imButtonPlay, riButtonPlay)
Global riButtonRestart:Int, imButtonRestart:TImage; LoadResource("GFX/LNC/BTNxRESTART.png",, imButtonRestart, riButtonRestart)
Global rfSmallFont:Int, fnSmallFont:TImageFont; LoadFontResource("GFX/FNT/TranscencsGames.otf", 10,, fnSmallFont, rfSmallFont)
Global rfMediumFont:Int, fnMediumFont:TImageFont;LoadFontResource("GFX/FNT/TranscencsGames.otf", 12,, fnMediumFont, rfMediumFont)
Global rfBigFont:Int, fnBigFont:TImageFont; LoadFontResource("GFX/FNT/TranscencsGames.otf", 14,, fnBigFont, rfBigFont)
' Buttons
Const BTN_STT_NORMAL:Int = 0, BTN_STT_HOVER:Int = 1, BTN_STT_DOWN:Int = 2, BTN_STT_ACTION:Int = 3
Global stButtonClose:Int = BTN_STT_NORMAL
Global stButtonAccount:Int = BTN_STT_NORMAL
Global stButtonWebsite:Int = BTN_STT_NORMAL
Global stButtonSupport:Int = BTN_STT_NORMAL
Global stButtonEULATOS:Int = BTN_STT_NORMAL
Global stButtonCheck:Int = BTN_STT_NORMAL
Global stButtonPatch:Int = BTN_STT_NORMAL
Global stButtonPlay:Int = BTN_STT_NORMAL
Global stButtonRestart:Int = BTN_STT_NORMAL
' PatchLog
Global oPatchLog:TList = New TList
' Patcher
Global oPatcher:TPatcher = TPatcher.Create()
ShowGadget(gdPatcherWindow)
EndRem
Rem
'=====> Mainloop
Local relMouseX:Int, relMouseY:Int, bDragging:Byte
Repeat
WaitEvent()
Select EventSource()
Case tmTimer ' Core timer that is basically our main loop.
'=====> User-input
Local MX:Int = MouseX(), MY:Int = MouseY()
Local MD1:Int = MouseDown(1), MH1:Int = MouseHit(1)
stButtonClose = GetButtonState(stButtonClose, 684, 0, 24, 18, MX, MY, MD1)
stButtonWebsite = GetButtonState(stButtonWebsite, 618, 330, 96, 16, MX, MY, MD1)
stButtonSupport = GetButtonState(stButtonSupport, 618, 348, 96, 16, MX, MY, MD1)
stButtonAccount = GetButtonState(stButtonAccount, 618, 366, 96, 16, MX, MY, MD1)
stButtonEULATOS = GetButtonState(stButtonEULATOS, 618, 384, 96, 16, MX, MY, MD1)
' React on the close button by sending a WindowCloseEvent
If stButtonClose = BTN_STT_ACTION Then PostEvent(TEvent.Create(EVENT_WINDOWCLOSE, gdPatcherWindow, 0, 0, 0, 0, Null))
If stButtonWebsite = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/")
If stButtonSupport = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/#contact")
If stButtonAccount = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/")
If stButtonEULATOS = BTN_STT_ACTION Then OpenURL("http://www.sirius.vektor-studios.com/")
' State based checking
Select oPatcher.GetState()
Case TPatcher.STATE_PATCHINFO
stButtonCheck = GetButtonState(stButtonCheck, 312, 441, 96, 16, MX, MY, MD1)
If stButtonCheck = BTN_STT_ACTION Then oPatcher.Advance()
Case TPatcher.STATE_PREPATCH
stButtonPatch = GetButtonState(stButtonPatch, 312, 441, 96, 16, MX, MY, MD1)
If stButtonPatch = BTN_STT_ACTION Then oPatcher.Advance()
Case TPatcher.STATE_COMPLETE
stButtonPlay = GetButtonState(stButtonPlay, 312, 441, 96, 16, MX, MY, MD1)
If stButtonPlay = BTN_STT_ACTION Then oPatcher.Advance()
Case TPatcher.STATE_LAUNCHER
stButtonRestart = GetButtonState(stButtonRestart, 312, 441, 96, 16, MX, MY, MD1)
If stButtonRestart = BTN_STT_ACTION Then oPatcher.Advance()
EndSelect
' Window Dragging
If bDragging = False And (MH1 = True And (MY >= 0 And MY < 32) And (MX >= 0 And MX < 720)) Then
bDragging = True
relMouseX = MX;relMouseY = MY
ElseIf bDragging = True And MD1 = True Then
SetGadgetShape(gdPatcherWindow, GadgetX(gdPatcherWindow) - (relMouseX - MX), GadgetY(gdPatcherWindow) - (relMouseY - MY), 720, 460)
relMouseX = MX + (relMouseX - MX);relMouseY = MY + (relMouseY - MY) 'Magic o.o - I don't understand why this works this way, but not when using :+ notation.
Else
bDragging = False
EndIf
'=====> Rendering
SetGraphics CanvasGraphics(gdRenderCanvas)
Cls
' Draw Back- & Foreground
SetBlend ALPHABLEND;SetMaskColor 0, 0, 0
SetColor 255, 255, 255;SetAlpha 1.0
SetOrigin 0, 0;SetTransform 0, 1, 1
If imMainBackground <> Null Then DrawImage(imMainBackground, 0, 0)
If imMainForeground <> Null Then DrawImage(imMainForeground, 0, 0)
' Window Close Button
DrawButtonState(stButtonClose, 684, 0, 24, 18, imButtonClose, "X")
' Buttons
DrawButtonState(stButtonWebsite, 618, 330, 96, 16, imButtonWebsite, "Website")
DrawButtonState(stButtonSupport, 618, 348, 96, 16, imButtonSupport, "Support")
DrawButtonState(stButtonAccount, 618, 366, 96, 16, imButtonAccount, "Account")
DrawButtonState(stButtonEULATOS, 618, 384, 96, 16, imButtonEULATOS, "EULA/TOS")
' State based drawing.
Select oPatcher.GetState()
Case TPatcher.STATE_PATCHINFO
DrawButtonState(stButtonCheck, 312, 441, 96, 16, imButtonCheck, "Check")
Case TPatcher.STATE_PREPATCH
DrawButtonState(stButtonPatch, 312, 441, 96, 16, imButtonPatch, "Patch")
Case TPatcher.STATE_COMPLETE
DrawButtonState(stButtonPlay, 312, 441, 96, 16, imButtonPlay, "Play")
Case TPatcher.STATE_LAUNCHER
DrawButtonState(stButtonRestart, 312, 441, 96, 16, imButtonRestart, "Restart")
Case TPatcher.STATE_PATCHINFO, TPatcher.STATE_CHECKING, TPatcher.STATE_PATCHING
DrawProgressBar(8, 442, 704, 12, oPatcher.GetProgress(), imProgressBar)
EndSelect
' Draw Patcher Tasklog
SetBlend ALPHABLEND;SetMaskColor 0, 0, 0
SetColor 255, 255, 255;SetAlpha 0.66;SetImageFont fnSmallFont
SetOrigin 0, 0;SetTransform 0, 1, 1
SetViewport 11, 332, 600, 100
Local iLogNum:Int = 1, oLogEntry:TLink = oPatcher.m_oTaskList.FirstLink()
While (iLogNum < 9) And (oLogEntry <> Null)
Local stLine:String = String(oLogEntry.Value())
If stLine[0..1] = "n" Then SetColor 204, 244, 255
If stLine[0..1] = "e" Then SetColor 255, 222, 204
If stLine[0..1] = "g" Then SetColor 204, 255, 204
If stLine[0..1] = "h" Then SetColor 222, 222, 255
DrawText stLine[1..], 11, 430 - iLogNum * 12
oLogEntry = oLogEntry.NextLink()
iLogNum :+ 1
Wend
SetViewport 0, 0, 720, 460; SetColor 255,255,255; SetImageFont Null
Flip False
Case tmPatch
'=====> Patcher
oPatcher.Update()
If oPatcher.GetShutdown() <> Null Then
Local oProcess:TProcess = CreateProcess(oPatcher.GetShutdown())
TProcess.ProcessList.Remove oProcess
PostEvent(TEvent.Create(EVENT_WINDOWCLOSE, gdPatcherWindow, 0, 0, 684, 0, Null))
EndIf
Case tmResource
LoadResource("GFX/LNC/LAUxPATxB.png",, imMainBackground, riMainBackground)
LoadResource("GFX/LNC/LAUxPATxA.png",, imMainForeground, riMainForeground)
LoadResource("GFX/LNC/BARxPROGRESS.png",, imProgressBar, riProgressBar)
LoadResource("GFX/LNC/BTNxCLOSE.png",, imButtonClose, riButtonClose)
LoadResource("GFX/LNC/BTNxACCOUNT.png",, imButtonAccount, riButtonAccount)
LoadResource("GFX/LNC/BTNxWEBSITE.png",, imButtonWebsite, riButtonWebsite)
LoadResource("GFX/LNC/BTNxSUPPORT.png",, imButtonSupport, riButtonSupport)
LoadResource("GFX/LNC/BTNxEULATOS.png",, imButtonEULATOS, riButtonEULATOS)
LoadResource("GFX/LNC/BTNxCHECK.png",, imButtonCheck, riButtonCheck)
LoadResource("GFX/LNC/BTNxPATCH.png",, imButtonPatch, riButtonPatch)
LoadResource("GFX/LNC/BTNxPLAY.png",, imButtonPlay, riButtonPlay)
LoadFontResource("GFX/FNT/TranscencsGames.otf", 10,, fnSmallFont, rfSmallFont)
LoadFontResource("GFX/FNT/TranscencsGames.otf", 12,, fnMediumFont, rfMediumFont)
LoadFontResource("GFX/FNT/TranscencsGames.otf", 14,, fnBigFont, rfBigFont)
Case gdPatcherWindow
Select EventID()
Case EVENT_WINDOWCLOSE
'=====> End the patcher.
End
End Select
EndSelect
Forever
'=====> Functions
Function PointInsideRect:Byte(PX:Int, PY:Int, RX:Int, RY:Int, RW:Int, RH:Int)
If PX >= RX And PX < RX + RW Then
If PY >= RY And PY < RY + RH Then
Return True
EndIf
EndIf
Return False
EndFunction
Function GetButtonState:Byte(BS:Int, BX:Int, BY:Int, BW:Int, BH:Int, MX:Int, MY:Int, MB:Int)
Local retVal:Int = BS
If PointInsideRect(MX, MY, BX, BY, BW, BH) = True Then
If BS = BTN_STT_NORMAL Then
retVal = BTN_STT_HOVER
ElseIf BS = BTN_STT_HOVER And MB = True Then
retVal = BTN_STT_DOWN
ElseIf BS = BTN_STT_DOWN And MB = False Then
retVal = BTN_STT_ACTION
ElseIf BS = BTN_STT_ACTION Then
retVal = BTN_STT_HOVER
EndIf
Else
retVal = BTN_STT_NORMAL
EndIf
Return retVal
EndFunction
Function DrawBorder(X:Int, Y:Int, W:Int, H:Int)
DrawLine X, Y, X+W, Y
DrawLine X+W, Y, X+W, Y+H
DrawLine X+W, Y+H, X, Y+H
DrawLine X, Y+H, X, Y
EndFunction
Function DrawButtonState(BS:Int, BX:Int, BY:Int, BW:Int, BH:Int, imButton:TImage, Text:String = "")
SetBlend ALPHABLEND; SetAlpha 1.0; SetColor 255, 255, 255
SetTransform 0, 1, 1;SetOrigin 0, 0; SetImageFont Null
Select BS
Case BTN_STT_NORMAL
If imButton <> Null Then
DrawSubImageRect(imButton, BX, BY, BW, BH, 0, 0, BW, BH, 0, 0, 0)
Else
SetColor 0, 0, 0;DrawRect BX, BY, BW, BH
SetColor 255, 255, 255;DrawBorder(BX,BY,BW,BH)
DrawText Text, BX + BW/2 - TextWidth(Text)/2, BY + BH/2 - TextHeight(Text)/2
EndIf
Case BTN_STT_HOVER
If imButton <> Null Then
DrawSubImageRect(imButton, BX, BY, BW, BH, 0, BH, BW, BH, 0, 0, 0)
Else
SetColor 0, 0, 0;DrawRect BX, BY, BW, BH
SetColor 204, 225, 255;DrawBorder(BX,BY,BW,BH)
DrawText Text, BX + BW/2 - TextWidth(Text)/2, BY + BH/2 - TextHeight(Text)/2
EndIf
Case BTN_STT_DOWN, BTN_STT_ACTION
If imButton <> Null Then
DrawSubImageRect(imButton, BX, BY, BW, BH, 0, BH*2, BW, BH, 0, 0, 0)
Else
SetColor 0, 0, 0;DrawRect BX, BY, BW, BH
SetColor 102, 123, 188;DrawBorder(BX,BY,BW,BH)
DrawText Text, BX + BW/2 - TextWidth(Text)/2, BY + BH/2 - TextHeight(Text)/2
EndIf
EndSelect
EndFunction
Function DrawProgressBar(X:Int, Y:Int, W:Int, H:Int, fProgress:Float, imProgressBar:TImage)
SetBlend ALPHABLEND; SetAlpha 1.0; SetColor 255, 255, 255
SetTransform 0, 1, 1;SetOrigin 0, 0
If imProgressBar = Null Then
SetColor 255, 255, 255;DrawBorder(X,Y,W,H)
SetColor 0, 0, 0;DrawRect X+1,Y+1,W-2,H-2
SetColor 204, 225, 255;SetAlpha 0.75 + Sin(MilliSecs()/5) * 0.25;DrawRect X, Y, W * fProgress, H
Else
DrawSubImageRect(imProgressBar, X, Y, W, H, 0, 0, W, H, 0, 0, 0)
SetAlpha 0.75 + Sin(MilliSecs()/5) * 0.25
Local iLength:Int = (W-6) * fProgress
DrawSubImageRect(imProgressBar, X, Y, 3, H, 0, H, 3, H, 0, 0, 0)
DrawSubImageRect(imProgressBar, X+3, Y, iLength, H, 3, H, iLength, H, 0, 0, 0)
DrawSubImageRect(imProgressBar, X+3+iLength, Y, 3, H, W-3, H, 3, H, 0, 0, 0)
EndIf
EndFunction
Function LoadResource(URL:String, Flags:Int = - 1, ImagePtr:TImage Var, InfoPtr:Int Var)
Local iModTime:Int = FileTime(URL)
If iModTime <> InfoPtr Then
ImagePtr = LoadImage(URL, Flags)
InfoPtr = iModTime
EndIf
EndFunction
Function LoadFontResource(URL:String, Size:Int, Style:Int = SMOOTHFONT, FontPtr:TImageFont Var, InfoPtr:Int Var)
Local iModTime:Int = FileTime(URL)
If iModTime <> InfoPtr Then
FontPtr = LoadImageFont(URL, Size, Style)
InfoPtr = iModTime
EndIf
EndFunction
EndRem
@@ -0,0 +1,300 @@
SuperStrict
Import BRL.Max2D
Import BRL.TextStream
Import PUB.OpenGL
Import PUB.Glew
Const MODE_REPEATX:Byte = $00000001 ' Repeat.
Const MODE_REPEATY:Byte = $00000010
Const MODE_MIRRORX:Byte = $00000100 ' Mirror every second repeat.
Const MODE_MIRRORY:Byte = $00001000
Const MODE_SCALEUPX:Byte = $00010000 ' Scale up to fit the destination area if the source doesn't fit exactly in.
Const MODE_SCALEUPY:Byte = $00100000
Const MODE_SCALEDOWNX:Byte = $01000000 ' Similar to MODE_SCALEUP*, except that it scales down to fit.
Const MODE_SCALEDOWNY:Byte = $10000000
Function DrawSubImageRectEx:Int(img:TImage, ..
dstX:Float, dstY:Float, dstW:Float, dstH:Float, ..
srcX:Float, srcY:Float, srcW:Float, srcH:Float, ..
hndX:Float=0, hndY:Float=0, frame:Int=0, bFlags:Byte=0)
Assert img <> Null Else "Image does Not exist"
Local bRepeatX:Byte = ((bFlags & MODE_REPEATX) <> 0)
Local bRepeatY:Byte = ((bFlags & MODE_REPEATY) <> 0)
Local bMirrorX:Byte = ((bFlags & MODE_MIRRORX) <> 0)
Local bMirrorY:Byte = ((bFlags & MODE_MIRRORY) <> 0)
Local bScaleUpX:Byte = ((bFlags & MODE_SCALEUPX) <> 0)
Local bScaleUpY:Byte = ((bFlags & MODE_SCALEUPY) <> 0)
Local bScaleDownX:Byte = ((bFlags & MODE_SCALEDOWNX) <> 0)
Local bScaleDownY:Byte = ((bFlags & MODE_SCALEDOWNY) <> 0)
Local lXRepeat:Float = 1, lXScale:Float = 1
If bRepeatX Then
lXRepeat = dstW / srcW
If bScaleUpX Then
lXRepeat = Floor(lXRepeat)
lXScale = (dstW / srcW) / lXRepeat
ElseIf bScaleDownX Then
lXRepeat = Ceil(lXRepeat)
lXScale = (dstW / srcW) / lXRepeat
EndIf
Else
lXScale = dstW / srcW
EndIf
Local lYRepeat:Float = 1, lYScale:Float = 1
If bRepeatY Then
lYRepeat = dstH / srcH
If bScaleUpY Then
lYRepeat = Floor(lYRepeat)
lYScale = (dstH / srcH) / lYRepeat
ElseIf bScaleDownY Then
lYRepeat = Ceil(lYRepeat)
lYScale = (dstH / srcH) / lYRepeat
EndIf
Else
lYScale = dstH / srcH
EndIf
Local lXSize:Float = srcW * lXScale, lYSize:Float = srcH * lYScale
Local lM2DScaleXOrig:Float, lM2DScaleYOrig:Float
Local lM2DScaleX:Float, lM2DScaleY:Float
GetScale(lM2DScaleXOrig, lM2DScaleYOrig)
GetScale(lM2DScaleX, lM2DScaleY)
' Cache some variables, so that we don't waste CPU time
Local lXRepeatFl:Int = Floor(lXRepeat), lXRepeatOverflow:Float = lXRepeat - lXRepeatFl
Local lYRepeatFl:Int = Floor(lYRepeat), lYRepeatOverflow:Float = lYRepeat - lYRepeatFl
For Local lYIndex:Int = 0 To lYRepeatFl
Local lYSizeMul:Float = 1
Local lYPos:Float = dstY + lYIndex * lYSize
If bMirrorY Then lM2DScaleY :* -1
If (lYIndex = lYRepeatFl) Then lYSizeMul = lYRepeatOverflow
For Local lXIndex:Int = 0 To lXRepeatFl
Local lXSizeMul:Float = 1
Local lXPos:Float = dstX + lXIndex * lXSize
If bMirrorX Then lM2DScaleX :* -1
If (lXIndex = lXRepeatFl) Then lXSizeMul = lXRepeatOverflow
SetScale lM2DScaleX, lM2DScaleY
DrawSubImageRect(img, lXPos, lYPos, lXSize * lXSizeMul, lYSize * lYSizeMul, srcX, srcY, srcW * lXSizeMul, srcH * lYSizeMul, hndX, hndY, frame)
Next
Next
SetScale(lM2DScaleXOrig, lM2DScaleYOrig)
EndFunction
Function DrawTiledImage:Int(img:TImage, dstX:Float, dstY:Float, dstW:Float, dstH:Float, srcX:Float, srcY:Float, srcW:Float, srcH:Float, hndX:Float=0, hndY:Float=0, frame:Int=0, lft:Float, top:Float, rgt:Float, btm:Float, bBackground:Byte=True, bFlags:Byte=MODE_REPEATX | MODE_REPEATY)
DrawSubImageRect(img, dstX, dstY, lft, top, srcX, srcY, lft, top, hndX, hndY, frame)
DrawSubImageRect(img, dstX + dstW - rgt, dstY, rgt, top, srcX + srcW - rgt, srcY, rgt, top, hndX, hndY, frame)
DrawSubImageRect(img, dstX, dstY + dstH - btm, lft, top, srcX, srcY + srcH - btm, lft, btm, hndX, hndY, frame)
DrawSubImageRect(img, dstX + dstW - rgt, dstY + dstH - btm, rgt, top, srcX + srcW - rgt, srcY + srcH - btm, rgt, btm, hndX, hndY, frame)
' Left
DrawSubImageRectEx(img, dstX, dstY + top, lft, dstH - top - btm, srcX, srcY + top, lft, srcH - top - btm, hndX, hndY, frame, bFlags)
' Right
DrawSubImageRectEx(img, dstX + dstW - rgt, dstY + top, rgt, dstH - top - btm, srcX + srcW - rgt, srcY + top, rgt, srcH - top - btm, hndX, hndY, frame, bFlags)
' Top
DrawSubImageRectEx(img, dstX + lft, dstY, dstW - lft - rgt, top, srcX + lft, srcY, srcW - lft - rgt, top, hndX, hndY, frame, bFlags)
' Bottom
DrawSubImageRectEx(img, dstX + lft, dstY + dstH - btm, dstW - lft - rgt, btm, srcX + lft, srcY + srcH - btm, srcW - lft - rgt, btm, hndX, hndY, frame, bFlags)
If bBackground Then DrawSubImageRectEx(img, dstX + lft, dstY + top, dstW - lft - rgt, dstH - top - btm, srcX + lft, srcY + top, srcW - lft - rgt, srcH - top - btm, hndX, hndY, frame, bFlags)
End Function
' Max2D Shader Support ---------------------------------------------------------
Type TShader
' Functions ----------------------------------------------------------------
Function Create:TShader()
Return (New TShader)
EndFunction
Function CreateVertex:TShader(oVertexCode:String)
Local oShader:TShader = TShader.Create()
oShader.Load(oVertexCode, True)
Return oShader
EndFunction
Function CreateFragement:TShader(oFragmentCode:String)
Local oShader:TShader = TShader.Create()
oShader.Load(oFragmentCode, True)
Return oShader
EndFunction
Function CreateCombined:TShader(oVertexCode:String, oFragmentCode:String)
Local oShader:TShader = TShader.Create()
oShader.Load(oVertexCode, True)
oShader.Load(oFragmentCode, False)
Return oShader
EndFunction
Function CheckForErrors:Int(ShaderObject:Int, ErrorString:String Var, Compiled:Int = True)
Local Successful:Int
If Compiled Then
glGetShaderiv (ShaderObject, GL_COMPILE_STATUS, Varptr Successful)
Else
glGetProgramiv(ShaderObject, GL_LINK_STATUS, Varptr Successful)
EndIf
If Not Successful Then
Local ErrorLength:Int
glGetObjectParameterivARB(ShaderObject, GL_OBJECT_INFO_LOG_LENGTH_ARB, Varptr ErrorLength)
Local Message:Byte Ptr = MemAlloc(ErrorLength), Dummy:Int
glGetInfoLogARB(ShaderObject, ErrorLength, Varptr Dummy, Message)
ErrorString = String.FromCString(Message)
MemFree(Message)
Return True
EndIf
Return False
End Function
Function CheckCompatability:Int()
Local Extensions:String = String.FromCString(Byte Ptr glGetString(GL_EXTENSIONS))
Local GLVersion:String = String.FromCString(Byte Ptr glGetString(GL_VERSION))
Local GLVersionInt:Int = GLVersion[.. 3].Replace(".", "").ToInt()
DebugLog Extensions
If Extensions.Find("GL_ARB_shader_objects" ) >= 0 And ..
Extensions.Find("GL_ARB_vertex_shader" ) >= 0 And ..
Extensions.Find("GL_ARB_fragment_shader") >= 0 or GLVersionInt >= 20 Then
Return True
EndIf
Return False
End Function
' Variables ----------------------------------------------------------------
Field iProgramObject:Int ' Shader Program Object
Field tError:String ' Shader Compile Errors & Warnings
' Members ------------------------------------------------------------------
Method New()
Self.iProgramObject = glCreateProgram()
EndMethod
Method Delete()
glDeleteProgram(Self.iProgramObject)
EndMethod
'' Retrieves the error that happened during loading or linking.
' @return <String> Error log retrieved from the
Method GetError:String()
Return Self.tError
EndMethod
'' Loads a new shader and, if successful, attaches it to the program.
' @param <String> tShaderCode A string containing the shader code.
' @param <Bool> bIsVertexShader Is this code a vertex Shader
' @return <Bool> Success
Method Load:Byte(tShaderCode:String, bIsVertexShader:Byte = True)
Local liShaderObject:Int
If tShaderCode = Null Then Return False
If tShaderCode.length = 0 Then Return False
' Create a new Shader Object, either for Vertex or Fragment processing.
If bIsVertexShader Then
liShaderObject = glCreateShader(GL_VERTEX_SHADER)
Else
liShaderObject = glCreateShader(GL_FRAGMENT_SHADER)
EndIf
If liShaderObject = 0 Then Return False
' Load the shader source into the compiler.
Local lbShaderCodePtr:Byte Ptr = tShaderCode.ToCString()
Local liShaderLength:Int = tShaderCode.length
glShaderSource(liShaderObject, 1, VarPtr lbShaderCodePtr, VarPtr liShaderLength)
MemFree(lbShaderCodePtr)
' Compile the shader and check for errors
glCompileShader(liShaderObject)
If (TShader.CheckForErrors(liShaderObject, Self.tError, True) = False) Then
glAttachShader(iProgramObject, liShaderObject)
glDeleteShader(liShaderObject)
Return True
EndIf
glDeleteShader(liShaderObject)
EndMethod
'' Links the attached shaders to the program, if successful.
' @return <Bool> Success
Method Link:Byte()
glLinkProgramARB(Self.iProgramObject)
Return (TShader.CheckForErrors(Self.iProgramObject, Self.tError, False) = False)
EndMethod
'' Enable the this program and disable all other programs.
' @return <Bool> Success
Method Enable:Byte()
glUseProgramObjectARB(Self.iProgramObject)
Return (TShader.CheckForErrors(Self.iProgramObject, Self.tError, False) = False)
End Method
'' Disable the all programs.
' @return <Bool> Success
Method Disable:Byte()
glUseProgramObjectARB(0)
Return (TShader.CheckForErrors(Self.iProgramObject, Self.tError, False) = False)
End Method
'' Uniform Management
Method GetUniformLocation:Int(tUniform:String)
Return glGetUniformLocationARB(Self.iProgramObject, tUniform)
End Method
Method SetUniform1F(tUniform:String, fValue1:Float)
glUniform1f(GetUniformLocation(tUniform), fValue1)
EndMethod
Method SetUniform2F(tUniform:String, fValue1:Float, fValue2:Float)
glUniform2f(GetUniformLocation(tUniform), fValue1, fValue2)
EndMethod
Method SetUniform3F(tUniform:String, fValue1:Float, fValue2:Float, fValue3:Float)
glUniform3f(GetUniformLocation(tUniform), fValue1, fValue2, fValue3)
EndMethod
Method SetUniform4F(tUniform:String, fValue1:Float, fValue2:Float, fValue3:Float, fValue4:Float)
glUniform4f(GetUniformLocation(tUniform), fValue1, fValue2, fValue3, fValue4)
EndMethod
Method SetUniform1I(tUniform:String, iValue1:Int)
glUniform1i(GetUniformLocation(tUniform), iValue1)
EndMethod
Method SetUniform2I(tUniform:String, iValue1:Int, iValue2:Int)
glUniform2i(GetUniformLocation(tUniform), iValue1, iValue2)
EndMethod
Method SetUniform3I(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int)
glUniform3i(GetUniformLocation(tUniform), iValue1, iValue2, iValue3)
EndMethod
Method SetUniform4I(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int, iValue4:Int)
glUniform4i(GetUniformLocation(tUniform), iValue1, iValue2, iValue3, iValue4)
EndMethod
Method SetUniform1UI(tUniform:String, iValue1:Int)
glUniform1ui(GetUniformLocation(tUniform), iValue1)
EndMethod
Method SetUniform2UI(tUniform:String, iValue1:Int, iValue2:Int)
glUniform2ui(GetUniformLocation(tUniform), iValue1, iValue2)
EndMethod
Method SetUniform3UI(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int)
glUniform3ui(GetUniformLocation(tUniform), iValue1, iValue2, iValue3)
EndMethod
Method SetUniform4UI(tUniform:String, iValue1:Int, iValue2:Int, iValue3:Int, iValue4:Int)
glUniform4ui(GetUniformLocation(tUniform), iValue1, iValue2, iValue3, iValue4)
EndMethod
EndType
@@ -0,0 +1,9 @@
Sirius Online Launcher
=======================
Originally supposed to be the official launcher, it was later dumped as contact died off to the lead developer due to him going from 100mbit to potato quality internet. He didn't like the idea that it would check for an update and download it, instead of letting you play directly. Neither did he like the way the updates were handled, hash based checking for new files seemed to not go over well to him.
The project contains some things from the forums for BlitzMax, as well as my try at adding some extra support to Max2D. Remember Blitz3D? The 2D system in BlitzMax is basically the same, except worse.
License
=======
Sirius Online Launcher by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+285
View File
@@ -0,0 +1,285 @@
Strict
Import BRL.Retro
Function MD5$(in:String Var)
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476
Local r[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
Local k[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A,..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]
Local intCount = (((in$.length + 8) Shr 6) + 1) Shl 4
Local data[intCount]
For Local c=0 Until in$.length
data[c Shr 2] = data[c Shr 2] | ((in$[c] & $FF) Shl ((c & 3) Shl 3))
Next
data[in$.length Shr 2] = data[in$.length Shr 2] | ($80 Shl ((in$.length & 3) Shl 3))
data[data.length - 2] = (Long(in$.length) * 8) & $FFFFFFFF
data[data.length - 1] = (Long(in$.length) * 8) Shr 32
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3
For Local i=0 To 15
Local f = d ~ (b & (c ~ d))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + i]), r[i]) + b
a = t
Next
For Local i=16 To 31
Local f = c ~ (d & (b ~ c))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((5 * i) + 1) & 15)]), r[i]) + b
a = t
Next
For Local i=32 To 47
Local f = b ~ c ~ d
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((3 * i) + 5) & 15)]), r[i]) + b
a = t
Next
For Local i=48 To 63
Local f = c ~ (b | ~d)
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + ((7 * i) & 15)]), r[i]) + b
a = t
Next
h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next
Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3))
End Function
Function MD5Bank:String(inbank:TBank Var)
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476
Local r[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
Local k[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A,..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]
Local intCount = (((inbank.Size() + 8) Shr 6) + 1) Shl 4
Local data[intCount]
Local inPtr:Byte Ptr = inbank.Buf()
For Local c=0 Until inbank.Size()
data[c Shr 2] = data[c Shr 2] | ((inPtr[c] & $FF) Shl ((c & 3) Shl 3))
Next
data[inbank.Size() Shr 2] = data[inbank.Size() Shr 2] | ($80 Shl ((inbank.Size() & 3) Shl 3))
data[data.length - 2] = (Long(inbank.Size()) * 8) & $FFFFFFFF
data[data.length - 1] = (Long(inbank.Size()) * 8) Shr 32
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3
For Local i=0 To 15
Local f = d ~ (b & (c ~ d))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + i]), r[i]) + b
a = t
Next
For Local i=16 To 31
Local f = c ~ (d & (b ~ c))
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((5 * i) + 1) & 15)]), r[i]) + b
a = t
Next
For Local i=32 To 47
Local f = b ~ c ~ d
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((3 * i) + 5) & 15)]), r[i]) + b
a = t
Next
For Local i=48 To 63
Local f = c ~ (b | ~d)
Local t = d
d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + ((7 * i) & 15)]), r[i]) + b
a = t
Next
h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next
Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3))
End Function
Function SHA1$(in$)
Local h0 = $67452301, h1 = $EFCDAB89, h2 = $98BADCFE, h3 = $10325476, h4 = $C3D2E1F0
Local intCount = (((in$.length + 8) Shr 6) + 1) Shl 4
Local data[intCount]
For Local c=0 Until in$.length
data[c Shr 2] = (data[c Shr 2] Shl 8) | (in$[c] & $FF)
Next
data[in$.length Shr 2] = ((data[in$.length Shr 2] Shl 8) | $80) Shl ((3 - (in$.length & 3)) Shl 3)
data[data.length - 2] = (Long(in$.length) * 8) Shr 32
data[data.length - 1] = (Long(in$.length) * 8) & $FFFFFFFF
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3, e = h4
Local w[] = data[chunkStart..chunkStart + 16]
w = w[..80]
For Local i=16 To 79
w[i] = Rol(w[i - 3] ~ w[i - 8] ~ w[i - 14] ~ w[i - 16], 1)
Next
For Local i=0 To 19
Local t = Rol(a, 5) + (d ~ (b & (c ~ d))) + e + $5A827999 + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
For Local i=20 To 39
Local t = Rol(a, 5) + (b ~ c ~ d) + e + $6ED9EBA1 + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
For Local i=40 To 59
Local t = Rol(a, 5) + ((b & c) | (d & (b | c))) + e + $8F1BBCDC + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
For Local i=60 To 79
Local t = Rol(a, 5) + (b ~ c ~ d) + e + $CA62C1D6 + w[i]
e = d ; d = c
c = Rol(b, 30)
b = a ; a = t
Next
h0 :+ a ; h1 :+ b ; h2 :+ c
h3 :+ d ; h4 :+ e
Next
Return (Hex(h0) + Hex(h1) + Hex(h2) + Hex(h3) + Hex(h4)).ToLower()
End Function
Function SHA256$(in$)
Local h0 = $6A09E667, h1 = $BB67AE85, h2 = $3C6EF372, h3 = $A54FF53A
Local h4 = $510E527F, h5 = $9B05688C, h6 = $1F83D9AB, h7 = $5BE0CD19
Local k[] = [$428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1,..
$923F82A4, $AB1C5ED5, $D807AA98, $12835B01, $243185BE, $550C7DC3,..
$72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174, $E49B69C1, $EFBE4786,..
$0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DA,..
$983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147,..
$06CA6351, $14292967, $27B70A85, $2E1B2138, $4D2C6DFC, $53380D13,..
$650A7354, $766A0ABB, $81C2C92E, $92722C85, $A2BFE8A1, $A81A664B,..
$C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070,..
$19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A,..
$5B9CCA4F, $682E6FF3, $748F82EE, $78A5636F, $84C87814, $8CC70208,..
$90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2]
Local intCount = (((in$.length + 8) Shr 6) + 1) Shl 4
Local data[intCount]
For Local c=0 Until in$.length
data[c Shr 2] = (data[c Shr 2] Shl 8) | (in$[c] & $FF)
Next
data[in$.length Shr 2] = ((data[in$.length Shr 2] Shl 8) | $80) Shl ((3 - (in$.length & 3)) Shl 3)
data[data.length - 2] = (Long(in$.length) * 8) Shr 32
data[data.length - 1] = (Long(in$.length) * 8) & $FFFFFFFF
For Local chunkStart=0 Until intCount Step 16
Local a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7
Local w[] = data[chunkStart..chunkStart + 16]
w = w[..64]
For Local i=16 To 63
w[i] = w[i - 16] + (Ror(w[i - 15], 7) ~ Ror(w[i - 15], 18) ~ (w[i - 15] Shr 3))..
+ w[i - 7] + (Ror(w[i - 2], 17) ~ Ror(w[i - 2], 19) ~ (w[i - 2] Shr 10))
Next
For Local i=0 To 63
Local t0 = (Ror(a, 2) ~ Ror(a, 13) ~ Ror(a, 22)) + ((a & b) | (b & c) | (c & a))
Local t1 = h + (Ror(e, 6) ~ Ror(e, 11) ~ Ror(e, 25)) + ((e & f) | (~e & g)) + k[i] + w[i]
h = g ; g = f ; f = e ; e = d + t1
d = c ; c = b ; b = a ; a = t0 + t1
Next
h0 :+ a ; h1 :+ b ; h2 :+ c ; h3 :+ d
h4 :+ e ; h5 :+ f ; h6 :+ g ; h7 :+ h
Next
Return (Hex(h0) + Hex(h1) + Hex(h2) + Hex(h3) + Hex(h4) + Hex(h5) + Hex(h6) + Hex(h7)).ToLower()
End Function
Function Rol(val, shift)
Return (val Shl shift) | (val Shr (32 - shift))
End Function
Function Ror(val, shift)
Return (val Shr shift) | (val Shl (32 - shift))
End Function
Function LEHex$(val)
Local out$ = Hex(val)
Return out$[6..8] + out$[4..6] + out$[2..4] + out$[0..2]
End Function
+184
View File
@@ -0,0 +1,184 @@
SuperStrict
Import BRL.LinkedList
Import BRL.Map
Import BRL.Graphics
Import BRL.GLGraphics
Import BRL.Max2D
Import BRL.GLMax2D
Import BRL.Pixmap
Import Pub.OpenGL
Import "Max2DExtended.bmx"
Import BRL.BMPLoader
Import BRL.JPGLoader
Import BRL.PNGLoader
Import BRL.TGALoader
'-------------------------------------------------------------------------------
Type TGUI
' Variables ----------------------------------------------------------------
' Skinning
Field oSkinImageSet:TPixmap = Null
' GUI Area
Field oRootGadget:TGUIGadget = New TGUIGadget
' Functions ----------------------------------------------------------------
Function Create:TGUI(X:Float, Y:Float, W:Float, H:Float, Skin:Object)
Local loGUI:TGUI = New TGUI
Return loGUI
EndFunction
' Members ------------------------------------------------------------------
Method New()
Self.oRootGadget = (New TGUIGadget)
EndMethod
Method Destroy()
Self.oRootGadget = Null
EndMethod
Method Update:Int(fDelta:Float)
oRootGadget.Update(fDelta)
EndMethod
Method Render:Int(fDelta:Float)
oRootGadget.Render(fDelta)
EndMethod
'' Changes the
Method SetRootGadget:TGUIGadget(oRootGadget:TGUIGadget)
If oRootGadget = Null Or oRootGadget.Insane() Then Return Null
Local loRootWindow:TGUIGadget = Self.oRootGadget
Self.oRootGadget = oRootGadget
Return loRootWindow
EndMethod
Method GetRootGadget:TGUIGadget()
Return oRootGadget
EndMethod
EndType
'-------------------------------------------------------------------------------
Type TGUIGadget
' Constants ----------------------------------------------------------------
Const COORD_ABSOLUTE:Byte = 0
Const COORD_RELATIVE:Byte = 1
' Variables ----------------------------------------------------------------
' Gadget Coordinates
Field bLocalCoordType:Byte[] = New Byte[4]
Field dLocalCoord:Double[] = New Double[4]
Field dCoord:Double[] = New Double[4]
' Parent and Childs
Field oParentGUI:TGUI = Null
Field oParent:TGUIGadget = Null
Field oChildList:TList = New TList
' Members ------------------------------------------------------------------
'' Deconstructor for TGUIGadget
' Automatically removed itself from the parent and releases all pointers to chils
Method Delete()
' Unregister from parent gadget and release all pointers to childs.
SetParent(Null)
Self.oChildList.Clear()
' Destroy objects in reverse order.
Self.bCoordType = Null
Self.dCoord = Null
Self.dLocalCoord = Null
Self.oChildList = Null
EndMethod
'' Checks if the Gadget went insane due to invalid usage or other influence.
' @return <Bool> True if the TGUIGadget went insane, otherwise false.
Method Insane:Byte()
If Self.bCoordType = Null Then Return True
If Self.dCoord = Null Then Return True
If Self.dLocalCoord = Null Then Return True
If Self.oChildList = Null Then Return True
EndMethod
'' Updates the GUIGadget and any other objects in it.
' @return <Int>
Method Update:Int(fDelta:Float)
EndMethod
Method Render:Int(fDelta:Float)
EndMethod
' Parent Management
Method SetParent(oParent:TGUIGadget)
If Self.oParent <> Null Then Self.oParent.RemoveChild(Self)
If oParent <> Null Then oParent.AddChild(Self)
EndMethod
Method GetParent:TGUIGadget()
Return Self.oParent
EndMethod
' Child Management
Method IsChild:Int(oChild:TGUIGadget)
If oChild = Null Then Return False
Return Self.oChildList.Contains(oChild)
EndMethod
Method AddChild:Int(oChild:TGUIGadget)
If oChild <> Null Then
If IsChild(oChild) Then
Return True
Else
Return (Self.oChildList.AddLast(oChild) <> Null)
EndIf
EndIf
EndMethod
Method RemoveChild:Int(oChild:TGUIGadget)
If oChild <> Null Then
If IsChild(oChild) Then
Return True
Else
Return Self.oChildList.Remove(oChild)
EndIf
EndIf
EndMethod
Method GetChildAtIndex:TGUIGadget(iIndex:Int)
If iIndex <> -1 Then
Local liChildCount:Int = Self.oChildList.Count()
If iIndex >= 0 And iIndex < liChildCount Then
Return Self.oChildList.ValueAtIndex(iIndex)
Else
Return Null
EndIf
Else
Return Self.oChildList.Last()
EndIf
EndMethod
Method SetChildIndex:Int(oChild:TGUIGadget, iIndex:Int)
If oChild <> Null Then
If IsChild(oChild) Then
Local liChildCount:Int = Self.oChildList.Count()
If iIndex >= 0 And iIndex < liChildCount Then
'Local loChild:TGUIGadget = Self.oChildList.ValueAtIndex(iIndex)
'Local lChild:TGUIGadget = Self.oChildList.ValueAtIndex(iIndex)
'Self.oChildList.Insert
EndIf
EndIf
EndIf
EndMethod
' Signal Handlers ----------------------------------------------------------
EndType
'-------------------------------------------------------------------------------
Public
Type TGUIWindow Extends TGUIGadget
'-------------------------------------------------------------------------------
EndType
@@ -0,0 +1,435 @@
SuperStrict
Import BaH.libcurl
Import BRL.Bank
Import BRL.FileSystem
Import BRL.LinkedList
Import BRL.StandardIO
Import BRL.Stream
Import BRL.Timer
Import "Clock.c"
Import "Digest.bmx"
Type TPatcher
Const STATE_DEFAULT:Byte = 0
Const STATE_PATCHINFO:Byte = 1
Const STATE_CHECKING:Byte = 2
Const STATE_PREPATCH:Byte = 3
Const STATE_PATCHING:Byte = 4
Const STATE_COMPLETE:Byte = 5
Const STATE_LAUNCHER:Byte = 6
Const SSTATE_ENTER:Byte = 0
Const SSTATE_WORK:Byte = 1
Const SSTATE_LEAVE:Byte = 2
Const SERVER:String = "http://sirius-online.us.to/patch/"
' State-based Patcher
Field m_bState:Byte = TPatcher.STATE_DEFAULT
Field m_bSubState:Byte = TPatcher.SSTATE_ENTER
' lib/cURL is used for downloading of data.
Field m_oCurlMulti:TCurlMulti = Null
Field m_oCurl:TCurlEasy = Null
Field m_fCurlProgress:Float
' State: All
Field m_oTaskList:TList = New TList
Field m_fProgress:Float = 0
' State: Patchinfo, Checking, Patching
Field m_oFileHashList:TList = New TList
Field m_iFileCount:Int = 0
' State: Checking, Patching
Field m_oFileLoader:TAsyncLoader = New TAsyncLoader
Field m_oFileHashPair:TFileHash = Null
' State: Patching
Field m_oFileList:TList = New TList
Field m_oFile:String, m_oFileDL:String
Field m_oFileStream:TStream
' Construction
Method New()
EndMethod
Function Create:TPatcher()
Local oPatcher:TPatcher = New TPatcher
Return oPatcher
EndFunction
' Deconstruction
Method Destroy()
m_oCurlMulti.multiCleanup()
m_oCurl.cleanup()
EndMethod
' Basically the Main Loop of the Patcher, handles everything. Call GetShutdown:String() if you want to know when the patcher is telling you to run an executable and close.
Method Update()
' Check
Select m_bState
Case TPatcher.STATE_DEFAULT
If m_bSubState = TPatcher.SSTATE_ENTER Then
m_oCurlMulti = TCurlMulti.Create()
m_oCurl = m_oCurlMulti.newEasy()
m_oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
m_oCurl.setOptInt(CURLOPT_CRLF, False)
m_oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
m_oCurl.setOptString(CURLOPT_REFERER, TPatcher.SERVER)
m_oCurl.setOptString(CURLOPT_URL, TPatcher.SERVER + "info")
m_oCurl.setProgressCallback(TPatcher.ProgressCallback, Self)
m_oCurl.setWriteString()
m_oTaskList.AddFirst("n[WAIT] Getting patch information...")
m_bSubState = TPatcher.SSTATE_WORK
EndIf
If m_bSubState = TPatcher.SSTATE_WORK Then
Local iResult:Int = Perform()
m_fProgress = m_fCurlProgress
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[" + RSet(String(Int(m_fProgress * 100)), 3) + "%] Retrieving patch information...")
If iResult = CURLM_OK Then
If m_fCurlProgress = 1.0 And m_iCurlMultiHandles = 0 Then
m_bSubState = TPatcher.SSTATE_LEAVE
EndIf
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[FAIL] Retrieving patch information... ("+CurlError(iResult)+")")
SetState(TPatcher.STATE_COMPLETE)
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_LEAVE Then
m_oCurlMulti.multiRemove(m_oCurl)
m_oCurlMulti.multiCleanup()
m_oCurlMulti = Null
Local oCurlRCode:Int = m_oCurl.getInfo().responseCode()
Local stResult:String = m_oCurl.toString()
m_oCurl.cleanup()
m_oCurl = Null
If oCurlRCode <> 404 Then
m_oFileHashList.Clear()
If stResult.length > 0 Then
Local stFileHashArr:String[] = stResult.Split("~n")
For Local stFileHashPair:String = EachIn stFileHashArr
If stFileHashPair.length > 0 And stFileHashPair[0..1] <> "#" Then ' Ignore Comments
Local stPairArr:String[] = stFileHashPair.Split(":")
m_oFileHashList.AddLast(TFileHash.Create(stPairArr[0], stPairArr[1]))
EndIf
Next
m_iFileCount = m_oFileHashList.Count()
m_oFileList.Clear()
SetState(TPatcher.STATE_PATCHINFO) ' Got Patchinfo, and it had information.
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[ OK ] Retrieving patch information... done.")
Else
SetState(TPatcher.STATE_COMPLETE)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Retrieving patch information... invalid information file.")
EndIf
Else
SetState(TPatcher.STATE_COMPLETE)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Retrieving patch information... file not found.")
EndIf
EndIf
Case TPatcher.STATE_CHECKING
If m_bSubState = TPatcher.SSTATE_ENTER Then ' Used to load a new File
m_oFileHashPair = TFileHash(m_oFileHashList.RemoveFirst())
If m_oFileHashPair <> Null Then
m_oFileLoader.Initialize(m_oFileHashPair.stName)
m_oTaskList.AddFirst("n[WAIT] Checking '" + m_oFileHashPair.stName + "'...")
m_bSubState = TPatcher.SSTATE_WORK
Else
m_bSubState = TPatcher.SSTATE_LEAVE
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_WORK Then
If m_oFileLoader.m_bComplete = 0 Then
m_oFileLoader.Process(2, 1024)
m_fProgress = ((m_iFileCount - (m_oFileHashList.Count() + 1)) / Float(m_iFileCount)) + m_oFileLoader.m_fProgress * (1.0 / m_iFileCount)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[" + RSet(String(Int(m_fProgress * 100)), 3) + "%] Checking '" + m_oFileHashPair.stName + "'...")
Else
If m_oFileLoader.m_bComplete = 1
If m_oFileLoader.m_oBank <> Null Then
Local stHash:String = MD5Bank(m_oFileLoader.m_oBank).ToUpper()
If stHash <> m_oFileHashPair.stHash Then
m_oFileList.AddLast(m_oFileHashPair.stName)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("h[ OK ] Checking '" + m_oFileHashPair.stName + "'... requires update.")
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[ OK ] Checking '" + m_oFileHashPair.stName + "'... up to date.")
EndIf
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Checking '" + m_oFileHashPair.stName + "'... (File in use?)")
EndIf
Else
m_oFileList.AddLast(m_oFileHashPair.stName)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("h[ OK ] Checking '" + m_oFileHashPair.stName + "'... missing.")
EndIf
m_bSubState = TPatcher.SSTATE_ENTER
m_oFileLoader.Cleanup()
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_LEAVE Then
If m_oFileList.Count() > 0 Then
m_iFileCount = m_oFileList.Count()
SetState(TPatcher.STATE_PREPATCH)
Else
SetState(TPatcher.STATE_COMPLETE)
EndIf
EndIf
Case TPatcher.STATE_PATCHING
If m_bSubState = TPatcher.SSTATE_ENTER Then
Local m_oEntry:Object = m_oFileList.RemoveFirst()
If m_oEntry <> Null Then
m_oFile = String(m_oEntry);m_oFileDL = m_oFile + ".part"
CreateDir(ExtractDir(m_oFile), True)
m_oFileStream = WriteFile(m_oFileDL)
If m_oFileStream <> Null Then
m_oCurlMulti = TCurlMulti.Create()
m_oCurl = m_oCurlMulti.newEasy()
m_oCurl.setOptInt(CURLOPT_FOLLOWLOCATION, 1)
m_oCurl.setOptInt(CURLOPT_CRLF, False)
m_oCurl.setOptString(CURLOPT_USERAGENT, "Sirius Online Launcher")
m_oCurl.setOptString(CURLOPT_REFERER, TPatcher.SERVER + "info")
m_oCurl.setOptString(CURLOPT_URL, TPatcher.SERVER + m_oFile)
m_oCurl.setWriteStream(m_oFileStream)
m_oCurl.setProgressCallback(TPatcher.ProgressCallback, Self)
m_oTaskList.AddFirst("n[WAIT] Downloading '" + m_oFile + "'...")
m_bSubState = TPatcher.SSTATE_WORK
EndIf
Else
SetState(TPatcher.STATE_DEFAULT)
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_WORK Then
Local iResult:Int = Perform()
m_fProgress = ((m_iFileCount - (m_oFileList.Count() + 1)) / Float(m_iFileCount)) + m_fCurlProgress * (1.0 / m_iFileCount)
If iResult = CURLM_OK Then
m_oFileStream.Flush()
If m_fCurlProgress = 1.0 And m_iCurlMultiHandles = 0 Then
m_oCurlMulti.multiRemove(m_oCurl)
m_oCurlMulti.multiCleanup()
Local oCurlRCode:Int = m_oCurl.getInfo().responseCode()
m_oCurl.cleanup()
' Cleanup(1)
m_oCurl = Null
m_oCurlMulti = Null
m_oFileStream.Close()
m_oFileStream = Null
If oCurlRCode <> 404 Then
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("g[ OK ] Downloading '" + m_oFile + "'...")
' Rename files
If m_oFile <> "Launcher.exe" Then
RenameFile(m_oFile, m_oFile + ".old")
If RenameFile(m_oFileDL, m_oFile) Then
DeleteFile(m_oFile + ".old")
Else
RenameFile(m_oFile + ".old", m_oFile)
EndIf
Else' If we patched the launcher, tell the parent program to start the new one.
RenameFile(m_oFileDL, "-" + m_oFile)
m_oFileList.Clear() ' Clear the list to be sure
SetState(TPatcher.STATE_LAUNCHER)
EndIf
Else
DeleteFile(m_oFileDL)
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Downloading '" + m_oFile + "'... file not found.")
EndIf
'Cleanup (2)
m_oFileDL = Null
m_oFile = Null
If m_oFileList.Count() = 0 Then
m_bSubState = TPatcher.SSTATE_LEAVE
Else
m_bSubState = TPatcher.SSTATE_ENTER
EndIf
Else
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("n[" + RSet(String(Int(m_fCurlProgress * 100)), 3) + "%] Downloading '" + m_oFile + "'...")
EndIf
Else
m_oFileStream.Close()
m_oTaskList.RemoveFirst()
m_oTaskList.AddFirst("e[FAIL] Downloading '" + m_oFile + "'... " + CurlError(iResult))
EndIf
EndIf
If m_bSubState = TPatcher.SSTATE_LEAVE And m_bState = TPatcher.STATE_PATCHING Then
SetState(TPatcher.STATE_DEFAULT)
EndIf
EndSelect
EndMethod
Method Advance()
Select m_bState
Case TPatcher.STATE_PATCHINFO
SetState(TPatcher.STATE_CHECKING)
Case TPatcher.STATE_PREPATCH
SetState(TPatcher.STATE_PATCHING)
Case TPatcher.STATE_COMPLETE
m_stProcessToRun = "ExeFile.exe"
Case TPatcher.STATE_LAUNCHER
m_stProcessToRun = "-Launcher.exe 1"
EndSelect
EndMethod
Field m_iCurlMultiHandles:Int, m_bCurlMultiState:Byte = 0
Method Perform:Int()
Local iResult:Int = 0
iResult = MultiPerform()
Select m_bCurlMultiState
Case 0, 2
m_bCurlMultiState = (m_bCurlMultiState + 1) Mod 3
Case 1
If m_oCurlMulti.multiSelect(0.1) <> -1 And m_iCurlMultiHandles Then
iResult = MultiPerform()
If m_iCurlMultiHandles = 0 Then m_bCurlMultiState = 2
EndIf
EndSelect
Return iResult
EndMethod
Method MultiPerform:Int()
Local iResult:Int = m_oCurlMulti.multiPerform(m_iCurlMultiHandles)
While iResult = CURLM_CALL_MULTI_PERFORM
iResult = m_oCurlMulti.multiPerform(m_iCurlMultiHandles)
Wend
Return iResult
EndMethod
' State Management
Method SetState(bState:Byte)
m_bState = bState
m_bSubState = TPatcher.SSTATE_ENTER
m_fProgress = 0.0
EndMethod
Method GetState:Byte()
Return m_bState
EndMethod
' Information
Method GetProgress:Float()
Return m_fProgress
EndMethod
Field m_stProcessToRun:String = NUll
Method GetShutdown:String()
Return m_stProcessToRun
EndMethod
' Callbacks
Function ProgressCallback:Int(oPatcherObj:Object, dDownloadTotal:Double, dDownloadNow:Double, dUploadTotal:Double, dUploadNow:Double)
If dDownloadTotal = 0 And dDownloadNow = 0 And dUploadTotal = 0 And dUploadNow = 0 Then TPatcher(oPatcherObj).m_fCurlProgress = 0.0;Return 0
TPatcher(oPatcherObj).m_fCurlProgress = (dDownloadNow / dDownloadTotal)
EndFunction
EndType
Type TFileHash
Field stName:String, stHash:String
Function Create:TFileHash(stName:String, stHash:String)
Local oFH:TFileHash = New TFileHash
oFH.stName = stName
oFH.stHash = stHash
Return oFH
EndFunction
EndType
Type TAsyncLoader
Field m_oBank:TBank
Field m_oStream:TStream, m_iFileSize:Int
Field m_fProgress:Float, m_bComplete:Byte
Method Initialize(stFile:String)
If FileType(stFile) = FILETYPE_FILE Then
m_oStream = ReadFile(stFile)
If m_oStream <> Null Then
m_iFileSize = FileSize(stFile)
m_oBank = CreateBank(m_iFileSize)
If m_oBank <> Null Then
m_fProgress = 0.0
m_bComplete = False
Else
m_oStream.Close()
EndIf
Else
m_fProgress = 1.0
m_bComplete = -2
EndIf
Else
m_fProgress = 1.0
m_bComplete = -2
EndIf
EndMethod
Method Process(iMs:Float, iBufferSize:Int = 1024)
Local iClockStart:Int = getClock()
If (m_oStream <> Null And m_oBank <> Null) And m_oStream.Eof() = False Then
Local iClockNow:Int = getClock()
Repeat
Local iRemaining:Int = Min(m_iFileSize - m_oStream.Pos(), iBufferSize)
m_oBank.Read(m_oStream, m_oStream.Pos(), iRemaining)
iClockNow = getClock()
Until m_oStream.Eof() = True or getClockDiff(iClockStart, iClockNow) > (iMs / 1000.0 * getClocksPerSecond())
m_fProgress = m_oStream.Pos() / Float(m_iFileSize)
m_bComplete = m_oStream.Eof()
If m_oStream.Eof() = True Then
m_oStream.Close()
m_oStream = Null
EndIf
ElseIf m_bComplete = 0 Then
m_fProgress = 1.0
m_bComplete = -1
EndIf
EndMethod
Method Cleanup()
m_oBank = Null
EndMethod
EndType
Function DebugClock(Text:String)
DebugLog getClock() + ":" + Text
EndFunction
Extern "c"
Function getClocksPerSecond:Int()="getClocksPerSecond_"
Function getClock:Int()="getClock_"
Function getClockDiff:Int(clockStart:Int, clockEnd:Int)="getClockDiff_"
EndExtern
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
Sirius Online Server
=======================
This project was supposed to be the official server software for Sirius Online, before the idea of multiplayer was dumped completely. Talk about sticking to the project plan. Oh wait, there was none. Why did I join that trainwreck of a team. Anyway, the server was designed to be somewhat efficient at its job of calculating and transferring. It supports up to 65535 players and will re-use Ids where possible instead of constantly incrementing. This makes memory management really easy, but join times are sometimes higher than normal. The project uses Xaymar.IOQueue, something which no longer exists. All it did was store packets to be sent off at a later point in time. Networking was done using UDP and TCP, i think. No idea anymore, don't care either, I'm now using Unreal Engine 4 for game development.
License
=======
Sirius Online Server by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+639
View File
@@ -0,0 +1,639 @@
SuperStrict
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Framework BRL.Blitz
Import BRL.Threads
Import BRL.Timer
Import "BlitzNet.bmx"
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
' Fix GC weirdness
OnEnd(GCCollect)
Local Server:BNetServer = New BNetServer
Server.Open(27000, 27001, 8)
While
Server.Update()
Wend
Server.Close()
'----------------------------------------------------------------
'-- Types
'----------------------------------------------------------------
'Type Server
' Field m_Server:BNetServer
'End Type
Rem
Const VersionMajor:Byte = 0
Const VersionMinor:Byte = 40
Const Net_VersionMajor:Byte = 0
Const Net_VersionMinor:Byte = 1
' Network Initiation
Global InfoSocket:TSocket = TSocket.CreateTCP()
Global DataSocket:TSocket = TSocket.CreateUDP()
' Set up Information Socket.
Const SOCKET_INFO_PORT:Short = 27000
Const SOCKET_DATA_PORT:Short = 27001
If InfoSocket.Bind(SOCKET_INFO_PORT) Then
InfoSocket.SetTCPNoDelay(True)
Else
InfoSocket.Close()
Print "[ERR] Unable to bind Information Socket to port " + SOCKET_INFO_PORT + ". Make sure it is not in use."
End
EndIf
InfoSocket.Listen(128)
' Set up Data Socket.
If Not DataSocket.Bind(SOCKET_DATA_PORT) Then
DataSocket.Close()
Print "[ERR] Unable to bind Data Socket to port " + SOCKET_DATA_PORT + ". Make sure it is not in use."
End
EndIf
'END OF: Network Initiation
' Timers
Const DataTicks:Int = 5
Local l_LoopTimer:TTimer = TTimer.Create(120)
' Network Packet Buffer
Const NetPacketBufferSize:Int = 64
Local NetPacketBuffer:TBank = TBank.Create(NetPacketBufferSize)
Local NetPacketBufferStream:TBankStream = TBankStream.Create(NetPacketBuffer)
Local NetPacketQueueTCP:TList = (New TList)
Local NetPacketQueueTCPSwap:TList = (New TList)
Local NetPacketQueueUDP:TList = (New TList)
Local NetPacketQueueUDPSwap:TList = (New TList)
Repeat
Local l_LoopTime:Int = MilliSecs()
' Check for data on InfoSockets {
' Check for new connections. {
Local l_NewSocket:TSocket
Repeat
l_NewSocket = InfoSocket.Accept(0)
If l_NewSocket <> Null Then
Local l_NewPlayer:TPlayer = TPlayer.Create(l_NewSocket)
If l_NewPlayer <> Null Then
Print RSet(l_NewPlayer.m_UniqueId, 6) + ": Connected from " + DottedIP(l_NewSocket.RemoteIp()) + ":" + l_NewSocket.RemotePort() + "."
Else
l_NewSocket.Close()
Print "Server: New player tried connecting, but we are full."
EndIf
EndIf
Until l_NewSocket = Null
' }
' Check if a pregame client sent his login information {
For Local l_PGPlayer:TPlayer = EachIn TPlayer.PreGame
If l_PGPlayer.m_InfoSocket.Connected() = False Then
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Closed connection."
l_PGPlayer.Destroy();Continue
EndIf
While l_PGPlayer.m_InfoSocket.ReadAvail() > 0
Local l_ReadLength:Int = l_PGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, 1);NetPacketBufferStream.Seek(0)
If l_ReadLength = 1
Local l_PacketId:Byte = NetPacketBufferStream.ReadByte()
Select l_PacketId
Case TInfoLogin.Id
l_PGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, TInfoLogin.Size);NetPacketBufferStream.Seek(0)
Local l_InfoLogin:TInfoLogin = TInfoLogin(TInfoLogin.Read(NetPacketBufferStream))
If l_InfoLogin Then
' Retrieve Information from Packet
l_PGPlayer.m_Name = l_InfoLogin.m_Name
l_PGPlayer.m_Position[0] = l_InfoLogin.m_Position[0]
l_PGPlayer.m_Position[1] = l_InfoLogin.m_Position[1]
l_PGPlayer.m_Position[2] = l_InfoLogin.m_Position[2]
' Create UDP Socket for Client.
l_PGPlayer.m_DataSocket = TSocket.CreateUDP()
l_PGPlayer.m_DataSocket.Connect(l_PGPlayer.m_InfoSocket.RemoteIp(), l_InfoLogin.m_PunchPort)
' Send information to this client (order is important!).
Local l_InfoLogin:TInfoLogin = (New TInfoLogin)
l_InfoLogin.m_UniqueId = l_PGPlayer.m_UniqueId
l_InfoLogin.m_Name = l_PGPlayer.m_Name
'Local l_InfoUpdate:TInfoUpdate = (New TInfoUpdate)
'l_InfoUpdate.m_UniqueId = l_PGPlayer.m_UniqueId
'l_InfoUpdate.m_Name = l_PGPlayer.m_Name
'NetPacketBufferStream.Seek(0)
'Local l_Size:Int = l_InfoUpdate.Write(NetPacketBufferStream)
'l_PGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_Size)
' Add Player to ingame list.
TPlayer.PreGame.Remove(l_PGPlayer)
TPlayer.InGame.AddLast(l_PGPlayer)
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Logged in at " + l_PGPlayer.m_Position[0] + ":" + l_PGPlayer.m_Position[1] + ":" + l_PGPlayer.m_Position[2] + "."
Else
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": CheckSum did not match with ours, Client is probably outdated."
l_PGPlayer.Destroy();Exit
EndIf
EndSelect
Else
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Unable to read first byte, socket might be corrupted. Dropping client."
l_PGPlayer.Destroy();Exit
EndIf
Wend
' If we still have no login packet, check if they are supposed to be dropped by timeout.
If l_PGPlayer.m_InfoSocket And (l_LoopTime - l_PGPlayer.m_Time) > 5000 Then
Print RSet(l_PGPlayer.m_UniqueId, 6) + ": Did not login, dropped."
l_PGPlayer.Destroy();Continue
EndIf
Next
' }
' Check if an ingame client sent packets. {
While DataSocket.ReadAvail() > 0
Local l_ReadLength:Int = DataSocket.Recv(NetPacketBuffer._buf, 1);NetPacketBufferStream.Seek(0)
If l_ReadLength = 1
Local l_PacketId:Byte = NetPacketBufferStream.ReadByte()
Select l_PacketId
Case TDataUpdate.Id
l_ReadLength = DataSocket.Recv(NetPacketBuffer._buf, NetPacketBufferSize)
Local l_DataUpdate:TDataUpdate = TDataUpdate(TDataUpdate.Read(NetPacketBufferStream))
Local l_Player:TPlayer = TPlayer.UIDToPlayer[l_DataUpdate.m_UniqueId]
If l_Player And l_Player.m_DataSocket Then ' Player exists and is logged in.
If DataSocket.RemoteIp() = l_Player.m_DataSocket.RemoteIp() And DataSocket.RemotePort() = l_Player.m_DataSocket.RemotePort() Then ' It is the same player.
If l_DataUpdate.m_Changed & TPlayer.CHANGED_POSX <> 0 Then l_Player.m_Position[0] = l_DataUpdate.m_Position[0]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_POSY <> 0 Then l_Player.m_Position[1] = l_DataUpdate.m_Position[1]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_POSZ <> 0 Then l_Player.m_Position[2] = l_DataUpdate.m_Position[2]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_ROTX <> 0 Then l_Player.m_Rotation[0] = l_DataUpdate.m_Rotation[0]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_ROTY <> 0 Then l_Player.m_Rotation[1] = l_DataUpdate.m_Rotation[1]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_ROTZ <> 0 Then l_Player.m_Rotation[2] = l_DataUpdate.m_Rotation[1]
If l_DataUpdate.m_Changed & TPlayer.CHANGED_VEL <> 0 Then
l_Player.m_Velocity[0] = l_DataUpdate.m_Velocity[0]
l_Player.m_Velocity[1] = l_DataUpdate.m_Velocity[1]
l_Player.m_Velocity[2] = l_DataUpdate.m_Velocity[2]
EndIf
Else
Print "Server: Recieved update for another player from " + DottedIP(DataSocket.RemoteIp()) + ":" + DataSocket.RemotePort() + "."
EndIf
EndIf
EndSelect
EndIf
Wend
' }
' Check if an ingame client sent packets or packets need sending. {
For Local l_IGPlayer:TPlayer = EachIn TPlayer.InGame
Local l_Skip:Byte = False
If l_IGPlayer = Null Then Print "Fatal Error: Ran into ingame client, which apparently doesn't exist. Skipping."; Continue
' Check if the Player still has his TCP Socket open, otherwise drop him.
If l_IGPlayer.m_InfoSocket.Connected() = False Then
Print RSet(l_IGPlayer.m_UniqueId, 6) + ": Closed connection."
' Create InfoLogout packet.
Local l_InfoLogout:TInfoLogout = New TInfoLogout
l_InfoLogout.m_UniqueId = l_IGPlayer.m_UniqueId
' Remove the player from nearby other players.
NetPacketBufferStream.Seek(0)
Local l_Size:Int = l_InfoLogout.Write(NetPacketBufferStream)
For Local l_IGPlayerKnown:TPlayer = EachIn l_IGPlayer.__KnownPlayers:TList
l_IGPlayerKnown.m_InfoSocket.Send(NetPacketBuffer._buf, l_Size)
l_IGPlayerKnown.__KnownPlayers.Remove(l_IGPlayer)
Next
l_IGPlayer.Destroy();Continue
EndIf
' TCP: Do we have any incoming data from this player?
While l_IGPlayer.m_InfoSocket.ReadAvail() > 0
Local l_ReadLength:Int = l_IGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, 1);NetPacketBufferStream.Seek(0)
If l_ReadLength = 1
Local l_PacketId:Byte = NetPacketBufferStream.ReadByte()
NetPacketBufferStream.Seek(0)
Select l_PacketId
Case TInfoLogin.Id
l_IGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, TInfoLogin.Size)
Case TInfoLogout.Id
l_IGPlayer.m_InfoSocket.Recv(NetPacketBuffer._buf, TInfoLogout.Size)
Local l_InfoLogout:TInfoLogout = TInfoLogout(TInfoLogout.Read(NetPacketBufferStream))
l_InfoLogout.m_UniqueId = l_IGPlayer.m_UniqueId
' Send information to other clients.
NetPacketQueueTCPSwap.AddLast(l_InfoLogout)
Print RSet(l_IGPlayer.m_UniqueId, 6) + ": Logged out."
l_IGPlayer.Destroy();l_Skip = True;Exit
EndSelect
EndIf
Wend
If l_Skip = True Then Continue
' TCP: Do we have any data for this player? If so then send it out.
If NetPacketQueueTCP.Count() > 0 Then
For Local l_Packet:TNetPacket = EachIn NetPacketQueueTCP
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_Packet.Write(NetPacketBufferStream))
Next
EndIf
' UDP: If a DataUpdate is needed, send it.
If l_IGPlayer.m_TicksOnline Mod DataTicks Then
For Local l_IGPlayer2:TPlayer = EachIn TPlayer.InGame
If l_IGPlayer2 = l_IGPlayer Then Continue
If l_IGPlayer.IsInRange(l_IGPlayer2) Then ' Is this player even in range? If yes, continue
If Not l_IGPlayer.IsKnown(l_IGPlayer2) Then ' This client is new to him, need to introduce him first.
Local l_InfoLogin:TInfoLogin = (New TInfoLogin)
l_InfoLogin.m_UniqueId = l_IGPlayer2.m_UniqueId
l_InfoLogin.m_Name = l_IGPlayer2.m_Name
l_InfoLogin.m_Position[0] = l_IGPlayer2.m_Position[0]
l_InfoLogin.m_Position[1] = l_IGPlayer2.m_Position[1]
l_InfoLogin.m_Position[2] = l_IGPlayer2.m_Position[2]
l_InfoLogin.m_Rotation[0] = l_IGPlayer2.m_Rotation[0]
l_InfoLogin.m_Rotation[1] = l_IGPlayer2.m_Rotation[1]
l_InfoLogin.m_Rotation[2] = l_IGPlayer2.m_Rotation[2]
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_InfoLogin.Write(NetPacketBufferStream))
EndIf
Local l_DataUpdate:TDataUpdate = l_IGPlayer.GetDataUpdate(l_IGPlayer)
If l_DataUpdate Then
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_DataSocket.Send(NetPacketBuffer._buf, l_DataUpdate.Write(NetPacketBufferStream))
EndIf
Else
If l_IGPlayer.IsKnownEx(l_IGPlayer2) Then ' This client is known to him, need to remove him.
Local l_InfoLogout:TInfoLogout = (New TInfoLogout)
l_InfoLogout.m_UniqueId = l_IGPlayer2.m_UniqueId
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_InfoSocket.Send(NetPacketBuffer._buf, l_InfoLogout.Write(NetPacketBufferStream))
EndIf
EndIf
Next
EndIf
' UDP: Do we have any data for this player? If so then send it out.
If NetPacketQueueUDP.Count() > 0 Then
For Local l_Packet:TNetPacket = EachIn NetPacketQueueUDP
NetPacketBufferStream.Seek(0)
l_IGPlayer.m_DataSocket.Send(NetPacketBuffer._buf, l_Packet.Write(NetPacketBufferStream))
Next
EndIf
l_IGPlayer.m_TicksOnline :+ 1
Next
' }
' }
' Swap Network Packet Queue.
NetPacketQueueTCP.Swap(NetPacketQueueTCPSwap)
NetPacketQueueUDP.Swap(NetPacketQueueUDPSwap)
NetPacketQueueTCPSwap.Clear()
NetPacketQueueUDPSwap.Clear()
l_LoopTimer.Wait()
Until False
DataSocket.Close()
InfoSocket.Close()
End
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
Type TPlayer
'! Array that tells us if an Id is in use. Toggle the bit you were using if an object is created or dies.
Global UniqueIds:Byte[] = (New Byte[8192])
Global UIDToPlayer:TPlayer[] = (New TPlayer[65536])
'! List of active players
Global PreGame:TList = (New TList)
Global InGame:TList = (New TList)
' Constants {
Const NAME_LENGTH:Int = 16
Const CHANGED_POSX:Byte = $00000001
Const CHANGED_POSY:Byte = $00000010
Const CHANGED_POSZ:Byte = $00000100
Const CHANGED_ROTX:Byte = $00001000
Const CHANGED_ROTY:Byte = $00010000
Const CHANGED_ROTZ:Byte = $00100000
Const CHANGED_VEL:Byte = $01000000
Const CHANGED_SHOOT:Byte = $10000000
' }
' Identification
Field m_UniqueId:Short
Field m_Name:Byte[]
' Ship Data
Field m_Changed:Byte
Field m_Position:Float[]
Field m_Rotation:Short[]
Field m_Velocity:Short[]
' Network Data
Field m_InfoSocket:TSocket
Field m_DataSocket:TSocket
Field m_Time:Int
Field m_TicksOnline:Int
' Initialize and Create new Players {
Method New()
' Some Network Data
m_Time = MilliSecs()
m_TicksOnline = 0
' Identification
m_Name = New Byte[TPlayer.NAME_Length]
m_UniqueID = 0
' Ship Data
m_Position = New Float[3]
m_Rotation = New Short[3]
m_Velocity = New Short[3]
TPlayer.PreGame.AddLast(Self)
EndMethod
Function Create:TPlayer(p_InfoSocket:TSocket)
' Make sure the Socket is still alive.
If p_InfoSocket <> Null And p_InfoSocket.Connected() Then
Local l_Player:TPlayer = (New TPlayer)
' Find a Unique ID that is not yet in use.
Local l_UniqueId:Int = 0
While l_UniqueId < 8192
Local l_SubUniqueId:Byte = 0
While l_SubUniqueId < 8
If (TPlayer.UniqueIds[l_UniqueId] & (1 shl l_SubUniqueId)) = 0 Then
' Mark UniqueId as used.
TPlayer.UniqueIds[l_UniqueId] :| (1 shl l_SubUniqueId)
l_Player.m_UniqueId = l_UniqueId * 8 + l_SubUniqueId
' Exit Loops.
l_UniqueId = 65535;l_SubUniqueId = 7
EndIf
l_SubUniqueId :+ 1
Wend
l_UniqueId :+ 1
Wend
If l_UniqueId = 65536 Then ' We have a Unique Id if we hit the unsigned limit for Short.
TPlayer.UIDToPlayer[l_Player.m_UniqueId] = l_Player
l_Player.m_InfoSocket = p_InfoSocket
Return l_Player
EndIf
EndIf
EndFunction
' }
' Deinitalize and Destroy old Players {
Method Destroy()
' Mark UniqueId as unused.
TPlayer.UniqueIds[Int(m_UniqueId / 8)] :& ~(1 Shl (m_UniqueId Mod 8))
TPlayer.UIDToPlayer[m_UniqueId] = Null
' Try and remove from both Player lists.
TPlayer.PreGame.Remove(Self)
TPlayer.InGame.Remove(Self)
' Close remaining Sockets.
If m_InfoSocket Then m_InfoSocket.Close()
If m_DataSocket Then m_DataSocket.Close()
' Destroy Data
m_Name = Null
m_Position = Null
m_Rotation = Null
m_Velocity = Null
m_InfoSocket = Null
m_DataSocket = Null
EndMethod
' }
' Update {
Method Update(p_Multiplier:Float)
Local m_OPositionX:Float = m_Position[0]
Local m_OPositionY:Float = m_Position[1]
Local m_OPositionZ:Float = m_Position[2]
m_Position[0] :+ m_Velocity[0] * p_Multiplier
m_Position[1] :+ m_Velocity[1] * p_Multiplier
m_Position[2] :+ m_Velocity[2] * p_Multiplier
If m_Position[0] <> m_OPositionX Then m_Changed :| TPlayer.CHANGED_POSX
If m_Position[1] <> m_OPositionY Then m_Changed :| TPlayer.CHANGED_POSY
If m_Position[2] <> m_OPositionZ Then m_Changed :| TPlayer.CHANGED_POSZ
EndMethod
' }
' Packets {
Const Range:Int = 3000
Method IsInRange:Byte(p_Player:TPlayer)
Local l_Distance:Float = Abs(p_Player.m_Position[0] - m_Position[0]) + Abs(p_Player.m_Position[1] - m_Position[1]) + Abs(p_Player.m_Position[2] - m_Position[2])
If l_Distance < TPlayer.Range Then Return True
Return False
EndMethod
Field __KnownPlayers:TList = New TList
Method IsKnown:Byte(p_Player:TPlayer)
If Not __KnownPlayers.Contains(p_Player) Then
__KnownPlayers.AddLast(p_Player)
Return False
EndIf
Return True
EndMethod
Method IsKnownEx:Byte(p_Player:TPlayer)
If __KnownPlayers.Contains(p_Player) Then
__KnownPlayers.Remove(p_Player)
Return True
EndIf
Return False
EndMethod
Method GetDataUpdate:TDataUpdate(p_Player:TPlayer)
Local l_Distance:Float = Abs(p_Player.m_Position[0] - m_Position[0]) + Abs(p_Player.m_Position[1] - m_Position[1]) + Abs(p_Player.m_Position[2] - m_Position[2])
If l_Distance < TPlayer.Range And m_Changed Then
Local l_DataUpdate:TDataUpdate = New TDataUpdate
Local l_Changed:Byte = $00000000
l_Changed = m_Changed & (TPlayer.CHANGED_POSX | TPlayer.CHANGED_POSY | TPlayer.CHANGED_POSZ)
If l_Distance < 2000 Then l_Changed = m_Changed & (TPlayer.CHANGED_ROTX | TPlayer.CHANGED_ROTY | TPlayer.CHANGED_ROTZ)
If l_Distance < 1000 Then l_Changed = m_Changed & TPlayer.CHANGED_VEL
l_DataUpdate.m_UniqueId = m_UniqueId
l_DataUpdate.m_Changed = m_Changed
l_DataUpdate.m_Position[0] = m_Position[0]
l_DataUpdate.m_Position[1] = m_Position[1]
l_DataUpdate.m_Position[2] = m_Position[2]
l_DataUpdate.m_Rotation[0] = m_Rotation[0]
l_DataUpdate.m_Rotation[1] = m_Rotation[1]
l_DataUpdate.m_Rotation[2] = m_Rotation[2]
l_DataUpdate.m_Velocity[0] = m_Velocity[0]
l_DataUpdate.m_Velocity[1] = m_Velocity[1]
l_DataUpdate.m_Velocity[2] = m_Velocity[2]
Return l_DataUpdate
EndIf
Return Null
EndMethod
' }
EndType
' Basic Network Packet
Type TNetPacket
Field m_UniqueId:Short
Function Read:TNetPacket(p_Stream:TStream)
EndFunction
Method Write(p_Stream:TStream)
EndMethod
EndType
Type TInfoLogin Extends TNetPacket
Const Id:Byte = 0
Const Size:Int = 34
Global Version:Short = Net_VersionMajor Shl 8 + Net_VersionMinor
Field m_Name:Byte[] = New Byte[TPlayer.NAME_LENGTH]
Field m_Position:Float[] = New Float[3]
Field m_Rotation:Float[] = New Float[3]
Field m_PunchPort:Short
Function Read:TNetPacket(p_Stream:TStream)
Local l_UPDPort:Short = p_Stream.ReadShort()
Local l_Version:Short = p_Stream.ReadShort()
If l_Version = TInfoLogin.Version Then
Local l_Packet:TInfoLogin = New TInfoLogin
p_Stream.ReadBytes(l_Packet.m_Name, TPlayer.NAME_LENGTH)
l_Packet.m_Position[0] = p_Stream.ReadFloat()
l_Packet.m_Position[1] = p_Stream.ReadFloat()
l_Packet.m_Position[2] = p_Stream.ReadFloat()
l_Packet.m_Rotation[0] = p_Stream.ReadFloat()
l_Packet.m_Rotation[1] = p_Stream.ReadFloat()
l_Packet.m_Rotation[2] = p_Stream.ReadFloat()
l_Packet.m_PunchPort = l_UDPPort
Return l_Packet
EndIf
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TInfoLogin.Id)
p_Stream.WriteShort(m_UniqueId)
p_Stream.WriteShort(TInfoLogin.Version)
p_Stream.WriteBytes(m_Name, TPlayer.NAME_LENGTH)
p_Stream.WriteFloat(m_Position[0])
p_Stream.WriteFloat(m_Position[1])
p_Stream.WriteFloat(m_Position[2])
p_Stream.WriteFloat(m_Rotation[0])
p_Stream.WriteFloat(m_Rotation[1])
p_Stream.WriteFloat(m_Rotation[2])
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
Type TInfoLogout Extends TNetPacket
Const Id:Byte = 1
Const Size:Int = 2
Function Read:TNetPacket(p_Stream:TStream)
Local l_Packet:TInfoLogout = New TInfoLogout
Return l_Packet
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TInfoLogout.Id)
p_Stream.WriteShort(m_UniqueId)
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
Type TInfoUpdate Extends TNetPacket
Const Id:Byte = 2
Const Size:Int = 18
Field m_Name:Byte[] = New Byte[TPlayer.NAME_LENGTH]
Function Read:TNetPacket(p_Stream:TStream)
Local l_Packet:TInfoUpdate = New TInfoUpdate
l_Packet.m_UniqueId = p_Stream.ReadShort() ~ p_Stream.ReadShort()
p_Stream.ReadBytes(l_Packet.m_Name, TPlayer.NAME_LENGTH)
Return l_Packet
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TInfoUpdate.Id)
p_Stream.WriteShort(m_UniqueId)
p_Stream.WriteBytes(m_Name, TPlayer.NAME_LENGTH)
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
Type TDataUpdate Extends TNetPacket
Const Id:Byte = 3
Const Size:Int = 3
Field m_Changed:Byte
Field m_Position:Float[] = New Float[3]
Field m_Rotation:Float[] = New Float[3]
Field m_Velocity:Float[] = New Float[3]
Function Read:TNetPacket(p_Stream:TStream)
Local l_Packet:TDataUpdate = New TDataUpdate
l_Packet.m_UniqueId = p_Stream.ReadShort()
l_Packet.m_Changed = p_Stream.ReadByte()
If l_Packet.m_Changed & TPlayer.CHANGED_POSX <> 0 Then l_Packet.m_Position[0] = p_Stream.ReadFloat()
If l_Packet.m_Changed & TPlayer.CHANGED_POSY <> 0 Then l_Packet.m_Position[1] = p_Stream.ReadFloat()
If l_Packet.m_Changed & TPlayer.CHANGED_POSZ <> 0 Then l_Packet.m_Position[2] = p_Stream.ReadFloat()
If l_Packet.m_Changed & TPlayer.CHANGED_ROTX <> 0 Then l_Packet.m_Rotation[0] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 180.0
If l_Packet.m_Changed & TPlayer.CHANGED_ROTY <> 0 Then l_Packet.m_Rotation[1] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 180.0
If l_Packet.m_Changed & TPlayer.CHANGED_ROTZ <> 0 Then l_Packet.m_Rotation[2] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 180.0
If l_Packet.m_Changed & TPlayer.CHANGED_VEL <> 0 Then
l_Packet.m_Velocity[0] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 128.0
l_Packet.m_Velocity[1] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 128.0
l_Packet.m_Velocity[2] = Min(Max(p_Stream.ReadShort() / 32767.0, -1.0), 1.0) * 128.0
EndIf
Return l_Packet
EndFunction
Method Write:Int(p_Stream:TStream)
Local l_Pos:Int = p_Stream.Pos()
p_Stream.WriteByte(TDataUpdate.Id)
p_Stream.WriteShort(m_UniqueId)
p_Stream.WriteByte(m_Changed)
If m_Changed & TPlayer.CHANGED_POSX <> 0 Then p_Stream.WriteFloat(m_Position[0])
If m_Changed & TPlayer.CHANGED_POSY <> 0 Then p_Stream.WriteFloat(m_Position[1])
If m_Changed & TPlayer.CHANGED_POSZ <> 0 Then p_Stream.WriteFloat(m_Position[2])
If m_Changed & TPlayer.CHANGED_ROTX <> 0 Then p_Stream.WriteShort(Min(Max(m_Rotation[0] / 180.0, -1), 1) * 32767)
If m_Changed & TPlayer.CHANGED_ROTY <> 0 Then p_Stream.WriteShort(Min(Max(m_Rotation[1] / 180.0, -1), 1) * 32767)
If m_Changed & TPlayer.CHANGED_ROTZ <> 0 Then p_Stream.WriteShort(Min(Max(m_Rotation[2] / 180.0, -1), 1) * 32767)
If m_Changed & TPlayer.CHANGED_VEL <> 0 Then
p_Stream.WriteShort(Min(Max(m_Velocity[0] / 128.0, -1.0), 1.0) * 32767)
p_Stream.WriteShort(Min(Max(m_Velocity[1] / 128.0, -1.0), 1.0) * 32767)
p_Stream.WriteShort(Min(Max(m_Velocity[2] / 128.0, -1.0), 1.0) * 32767)
EndIf
Return p_Stream.Pos() - l_Pos
EndMethod
EndType
'--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
EndRem
+9
View File
@@ -0,0 +1,9 @@
xaymar.config
=======================
An easy way to load configurations from so called 'DataPaks'. DataPaks were inspired by Minecraft's NBT format and were able to store any arbitrary data. It's still more efficient to have a dedicated format instead of DataPaks, but it helps with compatability across versions. As far as I remember, this is thread-safe.
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=388595#388595
License
=======
xaymar.config by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+366
View File
@@ -0,0 +1,366 @@
SuperStrict
Import xaymar.datapak
Module xaymar.config
ModuleInfo "License: Public Domain"
ModuleInfo "Original Author: Michael Dirks <support@levelnull.de>"
ModuleInfo "Purpose: Easily read and write configuration files by using xaymar.datapak."
Type TConfig
Field __MainDP:TDataPak
Field __CurrentDP:TDataPak
Method CreateConfig(name:String="Master")
__CurrentDP = Null
If __MainDP <> Null
__MainDP.Destroy()
__MainDP = Null
End If
__MainDP = TDataPak.Create(name)
End Method
Method OpenConfig(url:String,pwd:String="")
__CurrentDP = Null
If __MainDP <> Null
__MainDP.Destroy()
__MainDP = Null
End If
__MainDP = TDataPak.FromFile(url,pwd)
End Method
Method SaveConfig(url:String,pwd:String="")
__MainDP.ToFile(url, TDP_FLAG_COMPRESSED | TDP_FLAG_PASSWORDED, pwd)
End Method
Method CloseConfig()
__CurrentDP = Null
__MainDP.Destroy()
__MainDP = Null
End Method
Method IsConfigOpen:Int()
Return (__MainDP <> Null)
End Method
Method CreateGroup(name:String)
If __MainDP <> Null
Local TVarDP:TDataPakType[] = Null
If __MainDP.GetDataByName(name) <> Null Then
TVarDP = __MainDP.GetDataByName(name)
End If
If TVarDP <> Null And TVarDP[0].GetType() = TDP_CONTAINER
__CurrentDP = TDataPak(TVarDP[0])
Else
__CurrentDP = __MainDP.AddDataContainer(name)
End If
Else
Throw TConfigException.Create("No Config open.")
End If
End Method
Method OpenGroup(name:String)
If __MainDP <> Null
Local TVarDP:TDataPakType[] = Null
If __MainDP.GetDataByName(name) <> Null Then
TVarDP = __MainDP.GetDataByName(name)
End If
If TVarDP <> Null And TVarDP[0].GetType() = TDP_CONTAINER
__CurrentDP = TDataPak(TVarDP[0])
Else
Throw TConfigException.Create("Group '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Config open.")
End If
End Method
Method CloseGroup()
__CurrentDP = Null
End Method
Method IsGroupOpen:Int()
Return (__CurrentDP <> Null)
End Method
Method GetGroupByte:Byte(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_BYTE
Return TDataPakByte(TVarDP).GetData()
Else
Throw TConfigException.Create("Byte '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupShort:Short(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_SHORT
Return TDataPakShort(TVarDP).GetData()
Else
Throw TConfigException.Create("Short '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupInt:Int(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_INT
Return TDataPakInt(TVarDP).GetData()
Else
Throw TConfigException.Create("Int '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupLong:Long(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_LONG
Return TDataPakLong(TVarDP).GetData()
Else
Throw TConfigException.Create("Long '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupFloat:Float(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_FLOAT
Return TDataPakFloat(TVarDP).GetData()
Else
Throw TConfigException.Create("Float '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupDouble:Double(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_DOUBLE
Return TDataPakDouble(TVarDP).GetData()
Else
Throw TConfigException.Create("Double '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupString:String(name:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_STRING
Return TDataPakString(TVarDP).GetData()
Else
Throw TConfigException.Create("String '"+name+"' does not exist.")
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupByteEx:Byte(name:String, def:Byte)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_BYTE
Return TDataPakByte(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupShortEx:Short(name:String, def:Short)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_SHORT
Return TDataPakShort(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupIntEx:Int(name:String, def:Int)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_INT
Return TDataPakInt(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupLongEx:Long(name:String, def:Long)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_LONG
Return TDataPakLong(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupFloatEx:Float(name:String, def:Float)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_FLOAT
Return TDataPakFloat(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupDoubleEx:Double(name:String, def:Double)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_DOUBLE
Return TDataPakDouble(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method GetGroupStringEx:String(name:String, def:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_STRING
Return TDataPakString(TVarDP).GetData()
Else
Return def
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupByte(name:String,data:Byte)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_BYTE
TDataPakByte(TVarDP).SetData(data)
Else
__CurrentDP.AddDataByte(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupShort(name:String,data:Short)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_SHORT
TDataPakShort(TVarDP).SetData(data)
Else
__CurrentDP.AddDataShort(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupInt(name:String,data:Int)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_INT
TDataPakInt(TVarDP).SetData(data)
Else
__CurrentDP.AddDataInt(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupLong(name:String,data:Long)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_LONG
TDataPakLong(TVarDP).SetData(data)
Else
__CurrentDP.AddDataLong(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupFloat(name:String,data:Float)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_FLOAT
TDataPakFloat(TVarDP).SetData(data)
Else
__CurrentDP.AddDataFloat(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupDouble(name:String,data:Double)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_DOUBLE
TDataPakDouble(TVarDP).SetData(data)
Else
__CurrentDP.AddDataDouble(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
Method SetGroupString(name:String,data:String)
If __CurrentDP <> Null
Local TVarDP:TDataPakType = Null, TVarDPA:TDataPakType[] = __CurrentDP.GetDataByName(name)
If TVarDPA.Length > 0 Then TVarDP = TVarDPA[0]
If TVarDP <> Null And TVarDP.GetType() = TDP_STRING
TDataPakString(TVarDP).SetData(data)
Else
__CurrentDP.AddDataString(name,data)
End If
Else
Throw TConfigException.Create("No Group selected.")
End If
End Method
End Type
Type TConfigException
Field Error:String
Method ToString:String()
Return Error
End Method
Function Create:TConfigException(Error:String)
Local TCE:TConfigException = New TConfigException
TCE.Error = Error
Return TCE
End Function
End Type
+11
View File
@@ -0,0 +1,11 @@
xaymar.datapak
=======================
A newer iteration of DataCollector, named DataPaks. It was inspired by Minecraft's NBT format and as such has similar features. It supports many types, as well as arrays of such types (in case you don't want to name each entry, useful for inventories). Saved and loaded archives can be passworded and compressed, it is up to you to use that feature. The project includes two examples, which just show how to use the module.
First iteration at: http://www.blitzforum.de/forum/viewtopic.php?t=36694
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=388429#388429
License
=======
xaymar.datapak by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
File diff suppressed because it is too large Load Diff
+35
View File
@@ -0,0 +1,35 @@
Framework brl.retro
Import xaymar.datapak
'Advanced: Create a new Container
Local DPCnt:TDataPak = New TDataPak
DPCnt.SetName("MyContainer")
'Advanced: Add A new String (or any other Type: Byte, Short, Int, Long, Float, Double, Container)
Local DPStr:TDataPakString = New TDataPakString
DPStr.SetName("MyString")
DPStr.SetData("Hello :D")
DPCnt.AddData(DPStr)
'Easy: Add A new String (or any other Type: Byte, Short, Int, Long, Float, Double, Container)
DPCnt.AddDataString("MyString2", "Hallo :D")
'Easy: Safe to File
'Uncompressed & Unpassworded [sdp = Standard Data Pak]
DPCnt.ToFile("Test.sdp")
'Compressed & Unpassworded [cdp = Compressed Data Pak]
DPCnt.ToFile("Test.cdp", TDP_FLAG_COMPRESSED)
'Uncompressed & Passworded [pdp = Passworded Data Pak]
DPCnt.ToFile("Test.pdp", TDP_FLAG_PASSWORDED, "MyPassword")
'Compressed & Passworded [mdp = Merged Data Pak]
DPCnt.ToFile("Test.mdp", TDP_FLAG_PASSWORDED | TDP_FLAG_COMPRESSED, "MyPassword")
'Easy: Loading from File
'Uncompressed & Unpassworded [sdp = Standard Data Pak]
Local DPCntS:TDataPak = TDataPak.FromFile("Test.sdp")
'Compressed & Unpassworded [cdp = Compressed Data Pak]
Local DPCntC:TDataPak = TDataPak.FromFile("Test.cdp")
'Uncompressed & Passworded [pdp = Passworded Data Pak]
Local DPCntP:TDataPak = TDataPak.FromFile("Test.pdp", "MyPassword")
'Compressed & Passworded [mdp = Merged Data Pak]
Local DPCntM:TDataPak = TDataPak.FromFile("Test.mdp", "MyPassword")
+27
View File
@@ -0,0 +1,27 @@
Framework brl.retro
Import xaymar.datapak
'Testing consistency of DataPaks
Local DPCnt:TDataPak = New TDataPak
DPCnt.SetName("My Container")
DPCnt.AddDataByte("My Byte", 127)
DPCnt.AddDataShort("My Short", 256)
DPCnt.AddDataInt("My Int", 65536)
DPCnt.AddDataLong("My Long", 618317896391:Long)
DPCnt.AddDataFloat("My Float", 1.23456789)
DPCnt.AddDataDouble("My Double", 1.2345678912345:Double)
DPCnt.AddDataString("My String", "Totally not yours!")
Local DPSCnt:TDataPak = DPCnt.AddDataContainer("My SubContainer")
DPSCnt.AddDataByte("Sub Byte", 127)
DPSCnt.AddDataShort("Sub Short", 256)
DPSCnt.AddDataInt("Sub Int", 65536)
DPSCnt.AddDataLong("Sub Long", 618317896391:Long)
DPSCnt.AddDataFloat("Sub Float", 1.23456789)
DPSCnt.AddDataDouble("Sub Double", 1.2345678912345:Double)
DPSCnt.AddDataString("Sub String", "Totally not hub!")
DPCnt.ToFile("Consistency.sdp")
DPCnt.ToFile("Consistency.cdp", TDP_FLAG_COMPRESSED)
DPCnt.ToFile("Consistency.pdp", TDP_FLAG_PASSWORDED, "ThisIsATotallyUnsecurePasswordWithUnknownLengthToYouBecauseIDidn'tTellYouItsLength!")
DPCnt.ToFile("Consistency.mdp", TDP_FLAG_COMPRESSED | TDP_FLAG_PASSWORDED, "ThisIsATotallyUnsecurePasswordWithUnknownLengthToYouBecauseIDidn'tTellYouItsLength!")
+8
View File
@@ -0,0 +1,8 @@
xaymar.desktop
=======================
An attempt at rendering to the desktop. Failed, mind you. The module it references no longer exists, no idea what it even added.
License
=======
xaymar.desktop by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+104
View File
@@ -0,0 +1,104 @@
SuperStrict
Framework BRL.StandardIO
Import Xaymar.Desktop
Import Pub.DirectX
Import Pub.Win32
Import MaxGUI.Win32MaxGUIEx
Extern "win32"
Function GetLastError() = "GetLastError@0"
EndExtern
Global d3dx9Lib:Int = LoadLibraryA( "d3dx9" )
DebugLog GetLastError()
If d3dx9Lib Then
Global D3DXAssembleShader:Int(pSrcData:Byte Ptr, SrcDataLen:Int, pDefines:Byte Ptr, pInclude:Byte Ptr, FLAGS:Int, ppShader:ID3DXBuffer Var, ppErrorMsgs:ID3DXBuffer Var)"win32"=GetProcAddress( d3dx9Lib,"D3DXAssembleShader" )
Global D3DXSaveSurfaceToFile:Int(pConstString:Byte Ptr, DestFormat:Int, pSurface:Byte Ptr, pSrcPalette:Byte Ptr, pSrcRect:Byte Ptr)"win32"=GetProcAddress( d3dx9Lib, "D3DXSaveSurfaceToFile" )
EndIf
Local l_Displays:TList = GetDisplayList()
For Local l_Display:Rect = EachIn l_Displays
Print "[" + l_Display.Left + ", " + l_Display.Top + "]:[" + l_Display.Right + ", " + l_Display.Bottom + "]"
Next
Local l_Display:Rect = Rect(l_Displays.ValueAtIndex(0))
Local l_D3D:IDirect3D9 = Direct3DCreate9( 32 )
If Not l_D3D Then
Print "0x00000001"
Else
Local l_D3DCaps:D3DCAPS9 = New D3DCAPS9
If l_D3D.GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, l_D3DCaps) < 0
Print "0x00000002"
Else
Local l_D3DPresentParam:D3DPRESENT_PARAMETERS = New D3DPRESENT_PARAMETERS
l_D3DPresentParam.BackBufferWidth = (l_Display.Right - l_Display.Left)
l_D3DPresentParam.BackBufferHeight = (l_Display.Bottom - l_Display.Top)
l_D3DPresentParam.BackBufferCount = 1
l_D3DPresentParam.BackBufferFormat = D3DFMT_UNKNOWN
l_D3DPresentParam.MultiSampleType = D3DMULTISAMPLE_NONE
l_D3DPresentParam.SwapEffect = D3DSWAPEFFECT_DISCARD
l_D3DPresentParam.hDeviceWindow = Null
l_D3DPresentParam.Windowed = True
l_D3DPresentParam.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER | D3DPRESENTFLAG_VIDEO
l_D3DPresentParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE
Local l_WindowName:String = "Null"
Local l_hWnd:Int = CreateWindowExW(0, TWindowsGUIDriver.ClassName(), l_WindowName, 0, 0, 0, 1, 1, Null, Null, Null, Null)
If l_hWnd = 0 Then
Print GetLastError()
Print "0x00000003"
Else
Local l_D3DDevice:IDirect3DDevice9 = Null
If l_D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, l_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, l_D3DPresentParam, l_D3DDevice) < 0
Print "0x00000004"
Else
Local l_DesktopRT:IDirect3DSurface9 = Null
Local l_RecordRT:IDirect3DSurface9 = Null
If l_D3DDevice.GetRenderTarget(0, l_DesktopRT) < 0
Print "0x00000005"
Else
Local l_D3DDisplayMode:D3DDISPLAYMODE = New D3DDISPLAYMODE
If l_D3D.GetAdapterDisplayMode(D3DADAPTER_DEFAULT, l_D3DDisplayMode) < 0
Print "0x00000006"
Else
If l_D3DDevice.CreateOffscreenPlainSurface(l_D3DDisplayMode.Width, l_D3DDisplayMode.Height, l_D3DDisplayMode.Format, D3DPOOL_SYSTEMMEM, l_RecordRT, Null) < 0
Print "0x00000007"
Else
If l_D3DDevice.GetRenderTargetData(l_DesktopRT, l_RecordRT) < 0
Print "0x00000008"
Else
Local File:String = "C:\Dokumente und Einstellungen\Teilnehmer\Desktop\" + MilliSecs() + ".png"
Local FileCStr:Byte Ptr = File.ToCString()
Print D3DXSaveSurfaceToFile(FileCStr, 3, Byte Ptr(l_RecordRT), Null, Null)
If D3DXSaveSurfaceToFile(FileCStr, 3, Byte Ptr(l_RecordRT), Null, Null) <> 0
Print "0x00000009"
Else
Print "Success?"
EndIf
MemFree FileCStr
EndIf
l_RecordRT.Release_
EndIf
l_D3DDisplayMode = Null
EndIf
l_DesktopRT.Release_
EndIf
EndIf
DestroyWindow l_hWnd
EndIf
EndIf
l_D3D.Release_
EndIf
Rem
//copy the render target to the destination surface.
hr = Device->GetRenderTargetData(pRenderTarget, pDestTarget);
//save its contents to a bitmap file.
hr = D3DXSaveSurfaceToFile(file,
D3DXIFF_BMP,
pDestTarget,
NULL,
NULL);
+11
View File
@@ -0,0 +1,11 @@
xaymar.resource
=======================
I created this back when multi-threading was highly praised for the features it could give you. This allows you to load anything asynchronous and still know how far the loading process is. Easily extendable as it was designed to work flawlessly with as many types as possible. Requires threading, otherwise it will just be synchronous.
Supports both basic BRL modules as well as xaymar.datapak, which allows you to load large files without the program hanging up for a while. Thank god for threading!
Documentation at: http://www.blitzforum.de/forum/viewtopic.php?p=390021#390021
License
=======
xaymar.resource by Michael Fabian Dirks is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
+166
View File
@@ -0,0 +1,166 @@
'!BRL.Audio + AudioSample
Import brl.audio
Import brl.audiosample
Type TSoundResource Extends TResource
Field Flags:Int
Method SetSound(Name:String, File:String, Flags:Int=-1)
Self.Flags = Flags
Set(Name,File)
EndMethod
Method _Load()
Self.Resource = LoadSound(Self.File, Self.Flags)
EndMethod
End Type
Type TAudioSampleResource Extends TResource
Method _Load()
Self.Resource = LoadAudioSample(Self.File)
End Method
End Type
'!BRL.Bank + BRL.BankStream
Import brl.bank
Type TBankResource Extends TResource
Method _Load()
Self.Resource = LoadBank(Self.File)
End Method
Method _Save()
SaveBank(TBank(Self.Resource), Self.File)
End Method
End Type
'!BRL.Font
Import brl.font
Type TFontResource Extends TResource
Field Size:Int
Field Style:Int
Method SetFont(Name:String, File:String, Size:Int, Style:Int=SMOOTHFONT)
Self.Size = Size
Self.Style = Style
Set(Name,File)
EndMethod
Method _Load()
Self.Resource = LoadFont(Self.File, Self.Size, Self.Style)
End Method
End Type
'BRL.Max2D
Import brl.max2d
Type TImageResource Extends TResource
Field Flags:Int = -1
Field Animated:Int = False
Field CellWidth:Int = 0
Field CellHeight:Int = 0
Field FirstCell:Int = 0
Field CellCount:Int = 0
Method SetImage(Name:String, File:String, Flags:Int=-1)
Self.Flags = Flags
Self.Animated = False
Set(Name,File)
End Method
Method SetAnimImage(Name:String, File:String, CellWidth:Int, CellHeight:Int, FirstCell:Int, CellCount:Int, Flags:Int=-1)
Self.Flags = Flags
Self.Animated = True
Self.CellWidth = CellWidth
Self.CellHeight = CellHeight
Self.FirstCell = FirstCell
Self.CellCount = CellCount
Set(Name,File)
EndMethod
Method _Load()
If Self.Animated = False
Self.Resource = LoadImage(Self.File, Self.Flags)
Else
Self.Resource = LoadAnimImage(Self.File, Self.CellWidth, Self.CellHeight, Self.FirstCell, Self.CellCount, Self.Flags)
EndIf
EndMethod
End Type
'BRL.Pixmap
Import brl.pixmap
Import brl.bmploader
Import brl.jpgloader
Import brl.pngloader
Import brl.tgaloader
Type TPixmapResource Extends TResource
Field IsPNG:Int
Field Parameter:Int
Method SetPixmapJPG(Name:String, File:String, Quality:Int=75)
Self.IsPNG = False
Self.Parameter = Quality
Set(Name, File)
End Method
Method SetPixmapPNG(Name:String, File:String, Compression:Int=5)
Self.IsPNG = True
Self.Parameter = Compression
Set(Name, File)
End Method
Method _Load()
Self.Resource = LoadPixmap(Self.File)
End Method
Method _Save()
If IsPNG = True
SavePixmapPNG(TPixmap(Self.Resource), Self.File, Self.Parameter)
Else
SavePixmapJPeg(TPixmap(Self.Resource), Self.File, Self.Parameter)
EndIf
End Method
End Type
'BRL.Stream
Import brl.stream
Type TByteArrayResource Extends TResource
Method _Load()
Self.Resource = LoadByteArray(Self.File)
End Method
Method _Save()
SaveByteArray(Byte[](Self.Resource), Self.File)
End Method
End Type
Type TObjectResource Extends TResource
Method _Load()
Self.Resource = LoadObject(Self.File)
End Method
Method _Save()
SaveObject(Self.Resource, Self.File)
End Method
End Type
Type TStringResource Extends TResource
Method _Load()
Self.Resource = LoadString(Self.File)
End Method
Method _Save()
SaveString(String(Self.Resource), Self.File)
End Method
End Type
Type TStreamResource Extends TResource
Field Readable:Int = False
Field Writeable:Int = False
Method SetStream(Name:String, File:String, Readable:Int, Writeable:Int)
Readable = Readable
Writeable = Writeable
Set(Name, File)
End Method
Method _Load()
Self.Resource = OpenStream(Self.File, Self.Readable, Self.Writeable)
End Method
Method _Save()
FlushStream(TStream(Self.Resource))
End Method
End Type
'BRL.TextStream
Import brl.textstream
Type TTextResource Extends TResource
Method _Load()
Self.Resource = LoadText(Self.File)
End Method
End Type
@@ -0,0 +1,37 @@
'Xaymar.DataPak
Import xaymar.datapak
Type TDataPakResource Extends TResource
Field Password:String
Field Compressed:Int
Field Stream:TStream
Method SetDataPak(Name:String, URL:Object, Password:String="", Compressed:Int=False)
Self.Password = Password
Self.Compressed = Compressed
If TStream(URL) <> Null Then
Self.Stream = TStream(URL)
Set(Name, "")
ElseIf String(URL) <> Null Then
Self.Stream = Null
Set(Name, String(URL))
EndIf
End Method
Method _Load()
If Stream = Null
Self.Resource = TDataPak.FromFile(Self.File, Self.Password)
Else
Self.Resource = TDataPak.FromStream(Self.Stream)
End If
End Method
Method _Save()
Local _Flags:Byte
If Self.Password <> "" Then _Flags :+ TDP_FLAG_PASSWORDED
If Self.Compressed <> 0 Then _Flags :+ TDP_FLAG_COMPRESSED
If Stream = Null
TDataPak(Self.Resource).ToFile(Self.File, _Flags, Self.Password)
Else
TDataPak(Self.Resource).ToStream(Self.Stream)
End If
End Method
End Type
@@ -0,0 +1,106 @@
'Xaymar.Resource: Test 01
' Loading of Images and Sounds
SuperStrict
Import xaymar.resource
Import xaymar.brlaudio
Import xaymar.brlmax2d
Import brl.audio
Import brl.max2d
Graphics(800,600,0,60)
SetVirtualResolution(100,100)
Global MyResource:TResourceManager = New TResourceManager
Local imgDir:String[] = LoadDir("data/img/")
For Local fileImg:String = EachIn imgDir
Local _Res:TImageResource = New TImageResource
_Res.SetImage(fileImg, "data/img/"+fileImg)
MyResource.AddResource(_Res)
Next
Local sndDir:String[] = LoadDir("data/snd/")
For Local fileSnd:String = EachIn sndDir
Local _Res:TSoundResource = New TSoundResource
_Res.SetSound(fileSnd, "data/snd/"+fileSnd)
MyResource.AddResource(_Res)
Next
Local _ExitLoad:Int = False
Repeat
Cls
Local _BarPerc:Float = Float(MyResource.GetCount(TRM_LOADED)) / Float(MyResource.GetCount(TRM_ALL))
Local _BarPercLoad:Float = Float(MyResource.GetCount(TRM_LOADING)) / Float(MyResource.GetCount(TRM_ALL))
Local _BarPercError:Float = Float(MyResource.GetCount(TRM_ERROR)) / Float(MyResource.GetCount(TRM_ALL))
Local _BarColorMod:Float = 0.5+Sin( Float(MilliSecs()) / Float(1000/360) )*0.5
SetBlend ALPHABLEND
SetColor 102+153*_BarColorMod, 102+153*_BarColorMod, 102+153*_BarColorMod
DrawLine( 5, 90, 95, 90)
DrawLine( 5, 90, 5, 95)
DrawLine( 5, 95, 95, 95)
DrawLine(95, 90, 95, 95)
SetAlpha 0.9+0.1*_BarColorMod
SetColor 51, 255, 51
DrawRect( 6, 91, 89*_BarPerc, 4)
SetAlpha 0.8+0.2*_BarColorMod
SetColor 255, 255, 51
DrawRect( 6+89*_BarPerc, 91, 89*_BarPercLoad, 4)
SetAlpha 0.7+0.3*_BarColorMod
SetColor 255, 51, 51
DrawRect( 6+89*_BarPerc+89*_BarPercLoad, 91, 89*_BarPercError, 4)
SetColor 255,255,255
SetAlpha 1.0*_BarColorMod*_BarPerc
DrawRect( 5.5, 90.5, 90, 5)
SetAlpha 0.8
SetVirtualResolution(GraphicsWidth(),GraphicsHeight())
DrawText("Complete %:"+Int(_BarPerc*100),0,0)
DrawText("Loading %:"+Int(_BarPercLoad*100),0,15)
DrawText("Errored %:"+Int(_BarPercError*100),0,30)
If MyResource.GetResource(TRM_NONE) <> Null
DrawText(MyResource.GetResource(TRM_NONE).File,800*0.05,600*0.80)
Else
DrawText("Done, Press any key to continue...",800*0.05,600*0.80)
EndIf
SetVirtualResolution(100,100)
Flip
Local LRCode:Int = MyResource.LoadResource()
MyResource.Update() 'Update Count
If AppTerminate()
End
End If
If LRCode = TRM_LS_NORESOURCE
For Local I:Int = 0 To 255
If KeyDown(I) = True
_ExitLoad = True
End If
Next
End If
Until _ExitLoad = True
SetVirtualResolution(GraphicsWidth(),GraphicsHeight())
Print "Resource List:"
For Local _Res:TResource = EachIn MyResource.GetResources(TRM_ALL)
Select _Res._State
Case TRM_LOADED, TRM_SAVED
Print " SUCCESS: ["+_Res.Name+"]"+_Res.File
Case TRM_LOADING, TRM_SAVING
Print " STUCK: ["+_Res.Name+"]"+_Res.File
Case TRM_ERROR, TRM_NONE
Print " FAILED: ["+_Res.Name+"]"+_Res.File + " //"+_Res.Exception.ToString()
End Select
Next
End
+299
View File
@@ -0,0 +1,299 @@
SuperStrict
?Threaded
Import brl.threads
?
Import brl.linkedlist
Module xaymar.resource
ModuleInfo "License: Public Domain"
ModuleInfo "Original Author: Michael Dirks <support@levelnull.de>"
ModuleInfo "Purpose: Load your Files the better way! (Threading supported)"
Const TRM_SAVED:Int = -2
Const TRM_SAVING:Int = -1
Const TRM_NONE:Int = +0
Const TRM_LOADING:Int = +1
Const TRM_LOADED:Int = +2
Const TRM_ERROR:Int = $FF
Const TRM_ALL:Int = $FE
Const TRM_LS_ERROR:Int = 0
Const TRM_LS_SUCCESS:Int = 1
Const TRM_LS_NORESOURCE:Int = 2
Type TRLException
Method ToString:String()
Return "An Error appeared during Loading/Saving the Object."
End Method
End Type
Type TResourceManager
'Members
Field _ResList:TList = New TList
Field _ResourceLoaderFunc(Res:TResource)
Field _ResourceSaverFunc(Res:TResource)
'Members: Stats
Field _SavingRes:Int, _SavedRes:Int
Field _TotalRes:Int, _ErrorRes:Int
Field _LoadingRes:Int, _LoadedRes:Int
'Threaded Members
?Threaded Field _ResMutex:TMutex = CreateMutex()
?
'Methods
Method New();SetLoaderFunc(TResourceLoaderFunc);SetSaverFunc(TResourceSaverFunc);End Method
Method Remove()
?Threaded _ResMutex.Lock()
?
_ResList.Clear()
_ResList = Null
?Threaded _ResMutex.Unlock()
_ResMutex.Close()
_ResMutex = Null
?
End Method
Method SetLoaderFunc(LoaderFunc:Byte Ptr)
_ResourceLoaderFunc = LoaderFunc
End Method
Method SetSaverFunc(SaverFunc:Byte Ptr)
_ResourceSaverFunc = SaverFunc
End Method
Method Update()
?Threaded _ResMutex.Lock()
?
_TotalRes = _ResList.Count()
_LoadingRes = 0;_SavingRes = 0
_LoadedRes = 0;_SavedRes = 0
_ErrorRes = 0;
For Local _Res:TResource = EachIn _ResList
Select _Res._State
Case TRM_LOADING
_LoadingRes :+ 1
Case TRM_LOADED
_LoadedRes :+ 1
Case TRM_SAVING
_SavingRes :+ 1
Case TRM_SAVED
_SavedRes :+ 1
Case TRM_NONE
Default
_ErrorRes :+ 1
End Select
Next
?Threaded _ResMutex.Unlock()
?
End Method
Method GetCount:Int(Which:Int)
Select Which
Case TRM_NONE
Return _TotalRes-_LoadedRes-_LoadingRes-_SavedRes-_SavingRes-_ErrorRes
Case TRM_LOADING
Return _LoadingRes
Case TRM_LOADED
Return _LoadedRes
Case TRM_SAVING
Return _SavingRes
Case TRM_SAVED
Return _SavedRes
Case TRM_ERROR
Return _ErrorRes
Case TRM_ALL
Return _TotalRes
Default
Return 0
End Select
EndMethod
Method AddResource(Res:TResource)
?Threaded _ResMutex.Lock()
?
_ResList.AddLast(Res)
Res._State = TRM_NONE
?Threaded _ResMutex.Unlock()
?
End Method
Method RemoveResourceName(Name:String)
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If _Res.Name = Name Then
_ResList.Remove(_Res)
_Res = Null
End If
Next
?Threaded _ResMutex.Unlock()
?
End Method
Method RemoveResource(Res:TResource)
?Threaded _ResMutex.Lock()
?
_ResList.Remove(Res)
?Threaded _ResMutex.Unlock()
?
End Method
Method ClearResource(Which:Int=TRM_ALL)
?Threaded _ResMutex.Lock()
?
_ResList.Clear()
?Threaded _ResMutex.Unlock()
?
End Method
Method GetResourceName:TResource(Name:String, Which:Int=TRM_ALl)
Local _rRes:TResource
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If _Res.Name = Name And (_Res._State = Which Or Which = TRM_ALL)
_rRes = _Res
Exit
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return _rRes
End Method
Method GetResourcesName:TResource[](Name:String, Which:Int=TRM_ALL)
Local _rList:TList = New TList
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If _Res.Name = Name And (_Res._State = Which Or Which = TRM_ALL)
_rList.AddLast(_Res)
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return TResource[](_rList.ToArray())
End Method
Method GetResource:TResource(Which:Int=TRM_ALl)
Local _rRes:TResource
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If (_Res._State = Which Or Which = TRM_ALL)
_rRes = _Res
Exit
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return _rRes
End Method
Method GetResources:TResource[](Which:Int=TRM_ALL)
Local _rList:TList = New TList
?Threaded _ResMutex.Lock()
?
For Local _Res:TResource = EachIn _ResList
If (_Res._State = Which Or Which = TRM_ALL)
_rList.AddLast(_Res)
EndIf
Next
?Threaded _ResMutex.Unlock()
?
Return TResource[](_rList.ToArray())
End Method
Method LoadResource:Int(Which:Int=TRM_NONE)
Local _Res:TResource = GetResource(Which), _rVal:Int
If _Res = Null
Return TRM_LS_NORESOURCE
Else
?Threaded _ResMutex.Lock()
?
_Res._State = TRM_LOADING
?Threaded _ResMutex.Unlock()
?
_ResourceLoaderFunc(_Res)
?Threaded _ResMutex.Lock()
?
If _Res.Exception = Null And _Res.Resource <> Null
_Res._State = TRM_LOADED
_rVal = TRM_LS_SUCCESS
Else
If _Res.Exception = Null
_Res.Exception = New TRLException
End If
_Res._State = TRM_ERROR
_rVal = TRM_LS_ERROR
End If
?Threaded _ResMutex.Unlock()
?
Return _rVal
End If
End Method
Method SaveResource:Int(Which:Int=TRM_NONE)
Local _Res:TResource = GetResource(Which), _rVal:Int
If _Res = Null
Return TRM_LS_NORESOURCE
Else
?Threaded _ResMutex.Lock()
?
_Res._State = TRM_SAVING
?Threaded _ResMutex.Unlock()
?
_ResourceSaverFunc(_Res)
?Threaded _ResMutex.Lock()
?
If _Res.Exception = Null
_Res._State = TRM_SAVED
_rVal = TRM_LS_SUCCESS
Else
_Res._State = TRM_ERROR
_rVal = TRM_LS_ERROR
End If
?Threaded _ResMutex.Unlock()
?
Return _rVal
End If
End Method
End Type
Type TResource
Field _State:Int
Field Name:String, File:String
Field Resource:Object, Exception:Object
Method New();EndMethod
Method Set(Name:String, File:String)
Self.Name = Name
Self.File = File
Self.Resource = Null
Self.Exception = Null
End Method
Method Remove()
Self.Resource = Null
Self.Exception = Null
Self.File = Null
Self.Name = Null
End Method
Method _Load();End Method
Method _Save();End Method
End Type
Function TResourceLoaderFunc(Res:TResource)
Try
Res._Load()
Catch E:Object
Res.Exception = E
Res.Resource = Null
EndTry
End Function
Function TResourceSaverFunc(Res:TResource)
Try
Res._Save()
Catch E:Object
Res.Exception = E
Res.Resource = Null
EndTry
End Function