initial
This commit is contained in:
commit
68c8e3cfb8
3 changed files with 294 additions and 0 deletions
1
config.nims
Normal file
1
config.nims
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
setCommand "cpp"
|
||||||
16
magicmissile.nimble
Normal file
16
magicmissile.nimble
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "Failure"
|
||||||
|
description = "foul-magics launcher"
|
||||||
|
license = "GPL-3.0-or-later"
|
||||||
|
srcDir = "src"
|
||||||
|
bin = @["magicmissile"]
|
||||||
|
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 2.2.0"
|
||||||
|
|
||||||
|
requires "nimgl >= 1.3.2"
|
||||||
|
requires "zippy >= 0.10.16"
|
||||||
277
src/magicmissile.nim
Normal file
277
src/magicmissile.nim
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
# Copyright 2018, NimGL contributors.
|
||||||
|
|
||||||
|
import nimgl/imgui, nimgl/imgui/[impl_opengl, impl_glfw]
|
||||||
|
import nimgl/[opengl, glfw]
|
||||||
|
import std/[times, os, math, asyncdispatch, httpclient, strformat, strutils, paths, dirs, osproc]
|
||||||
|
from zippy/ziparchives import nil
|
||||||
|
from zippy/tarballs import nil
|
||||||
|
|
||||||
|
|
||||||
|
const zeroPos* = ImVec2(x: 0, y: 0)
|
||||||
|
|
||||||
|
proc `or`(a, b: ImGuiWindowFlags): ImGuiWindowFlags =
|
||||||
|
(a.int or b.int).ImGuiWindowFlags
|
||||||
|
|
||||||
|
removeDir("cache")
|
||||||
|
createdir("cache")
|
||||||
|
var cache = unixToNativePath("cache")
|
||||||
|
|
||||||
|
createDir("user")
|
||||||
|
var userDir = unixToNativePath("user")
|
||||||
|
var clientDir = unixToNativePath("client")
|
||||||
|
var javaDir = unixToNativePath("java")
|
||||||
|
|
||||||
|
|
||||||
|
var javaExists = dirExists("java")
|
||||||
|
var clientExists = dirExists("client")
|
||||||
|
|
||||||
|
proc superUnsafeSet(variable: var string, content: string, internalLen: int) =
|
||||||
|
zeroMem(variable[0].addr, internalLen)
|
||||||
|
copyMem(variable[0].addr, content[0].addr, content.len)
|
||||||
|
|
||||||
|
var javaStatus = newString(255)
|
||||||
|
var clientStatus = newString(255)
|
||||||
|
|
||||||
|
if javaExists: superUnsafeSet(javaStatus, "Java: good to go", 255)
|
||||||
|
else: superUnsafeSet(javaStatus, "Java: needs download", 255)
|
||||||
|
|
||||||
|
if clientExists: superUnsafeSet(clientStatus, "Client: checking for update...", 255)
|
||||||
|
else: superUnsafeSet(clientStatus, "Client: needs download", 255)
|
||||||
|
|
||||||
|
var downloadingClient = false
|
||||||
|
var downloadingJava = false
|
||||||
|
var checkingForUpdate = true
|
||||||
|
var clientVersion = "???"
|
||||||
|
|
||||||
|
var headers = newHttpHeaders()
|
||||||
|
headers["User-Agent"] = "MAGIC MISSILE/1.0"
|
||||||
|
|
||||||
|
proc getFoulUrl(): Future[string] {.async.} =
|
||||||
|
var client = newAsyncHttpClient(headers=headers, maxRedirects=0)
|
||||||
|
var redir = await client.head("https://git.cef.icu/Failure/foul-magics/actions/runs/latest")
|
||||||
|
return redir.headers["location"]
|
||||||
|
|
||||||
|
proc getFoulVersion(): Future[string] {.async.} =
|
||||||
|
result = (await getFoulUrl()).split("/")[^1]
|
||||||
|
|
||||||
|
proc onClientChange(total, progress, speed: BiggestInt) {.async.} =
|
||||||
|
{.cast(gcsafe).}:
|
||||||
|
var status = &"{(progress / 1000).int}K/{(total / 1000).int}k ({speed div 1000} kbps)"
|
||||||
|
superUnsafeSet(clientStatus, status, 255)
|
||||||
|
|
||||||
|
proc mergeDirectory(source, dest: string) =
|
||||||
|
createDir(dest)
|
||||||
|
for file in walkDirRec(source, {PathComponent.pcDir}, relative=true):
|
||||||
|
createDir(dest.Path / file.Path)
|
||||||
|
|
||||||
|
for file in walkDirRec(source, {PathComponent.pcFile}, relative=true):
|
||||||
|
copyFile($(source.Path / file.Path), $(dest.Path / file.Path))
|
||||||
|
|
||||||
|
|
||||||
|
proc getClient() {.async.} =
|
||||||
|
removeDir("client")
|
||||||
|
# clean up versioned files
|
||||||
|
removeDir(unixToNativePath("client") / "lib")
|
||||||
|
downloadingClient = true
|
||||||
|
var client = newAsyncHttpClient(headers=headers, maxRedirects=0)
|
||||||
|
var baseUrl = await getFoulUrl()
|
||||||
|
|
||||||
|
var url = baseUrl & "/artifacts/client.zip"
|
||||||
|
var path: string = cache / "baseclient.zip"
|
||||||
|
|
||||||
|
client.onProgressChanged = onClientChange
|
||||||
|
|
||||||
|
try:
|
||||||
|
await client.downloadFile(url, path)
|
||||||
|
finally:
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
|
||||||
|
superUnsafeSet(clientStatus, "Client: extracting...", 255)
|
||||||
|
ziparchives.extractAll(path, cache / "client")
|
||||||
|
ziparchives.extractAll(cache / "client" / "mage-client.zip", clientDir)
|
||||||
|
superUnsafeSet(clientStatus, "Client: good to go", 255)
|
||||||
|
|
||||||
|
mergeDirectory(clientDir / "sounds", userDir / "sounds")
|
||||||
|
mergeDirectory(clientDir / "sample-decks", userDir / "sample-decks")
|
||||||
|
mergeDirectory(clientDir / "backgrounds", userDir / "backgrounds")
|
||||||
|
|
||||||
|
clientExists = true
|
||||||
|
writeFile("version", baseUrl.split("/")[^1])
|
||||||
|
|
||||||
|
|
||||||
|
mergeDirectory(clientDir / "sounds", userDir / "sounds")
|
||||||
|
mergeDirectory(clientDir / "sample-decks", userDir / "sample-decks")
|
||||||
|
mergeDirectory(clientDir / "backgrounds", userDir / "backgrounds")
|
||||||
|
|
||||||
|
proc onJavaChange(total, progress, speed: BiggestInt) {.async.} =
|
||||||
|
{.cast(gcsafe).}:
|
||||||
|
var status = &"{(progress / 1000).int}K/{(total / 1000).int}k ({speed div 1000} kbps)"
|
||||||
|
superUnsafeSet(javaStatus, status, 255)
|
||||||
|
|
||||||
|
proc getJava() {.async.} =
|
||||||
|
removeDir("java")
|
||||||
|
downloadingJava = true
|
||||||
|
var client = newAsyncHttpClient(headers=headers)
|
||||||
|
|
||||||
|
client.onProgressChanged = onJavaChange
|
||||||
|
var url: string
|
||||||
|
var filename: string
|
||||||
|
|
||||||
|
when defined(windows):
|
||||||
|
url = "https://api.adoptium.net/v3/binary/latest/11/ga/windows/x64/jre/hotspot/normal/adoptium"
|
||||||
|
filename = "java.zip"
|
||||||
|
elif defined(linux):
|
||||||
|
url = "https://api.adoptium.net/v3/binary/latest/11/ga/linux/x64/jre/hotspot/normal/adoptium"
|
||||||
|
filename = "java.tar.gz"
|
||||||
|
var path = unixToNativePath("cache") / filename
|
||||||
|
|
||||||
|
try:
|
||||||
|
await client.downloadFile(url, path)
|
||||||
|
finally:
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
superUnsafeSet(javaStatus, "Java: extracting...", 255)
|
||||||
|
when defined(windows):
|
||||||
|
ziparchives.extractAll(path, cache / "java")
|
||||||
|
else:
|
||||||
|
tarballs.extractAll(path, cache / "java")
|
||||||
|
for item in walkDir(cache / "java", true, false, true):
|
||||||
|
if item.kind == pcDir:
|
||||||
|
moveDir(cache / "java" / item.path, "java")
|
||||||
|
break
|
||||||
|
superUnsafeSet(javaStatus, "Java: good to go", 255)
|
||||||
|
javaExists = true
|
||||||
|
|
||||||
|
|
||||||
|
proc checkForUpdates() {.async.} =
|
||||||
|
defer:
|
||||||
|
checkingForUpdate = false
|
||||||
|
if fileExists("version"):
|
||||||
|
clientVersion = await getFoulVersion()
|
||||||
|
|
||||||
|
if readFile("version") == clientVersion:
|
||||||
|
superUnsafeSet(clientStatus, "Client: good to go", 255)
|
||||||
|
else:
|
||||||
|
superUnsafeSet(clientStatus, "Client: needs update", 255)
|
||||||
|
clientExists = false
|
||||||
|
else:
|
||||||
|
superUnsafeSet(clientStatus, "Client: needs download", 255)
|
||||||
|
clientExists = false
|
||||||
|
|
||||||
|
proc getJarPath(): string =
|
||||||
|
for item in walkDir(clientDir / "lib", true, false, true):
|
||||||
|
if item.path.startswith("mage-client"):
|
||||||
|
return clientDir / "lib" / item.path
|
||||||
|
|
||||||
|
proc main() =
|
||||||
|
asyncCheck checkForUpdates()
|
||||||
|
doAssert glfwInit()
|
||||||
|
|
||||||
|
glfwWindowHint(GLFWContextVersionMajor, 3)
|
||||||
|
glfwWindowHint(GLFWContextVersionMinor, 3)
|
||||||
|
glfwWindowHint(GLFWOpenglForwardCompat, GLFW_TRUE)
|
||||||
|
glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE)
|
||||||
|
glfwWindowHint(GLFWResizable, GLFW_FALSE)
|
||||||
|
|
||||||
|
var w: GLFWWindow = glfwCreateWindow(300, 120, "MAGIC MISSILE")
|
||||||
|
if w == nil:
|
||||||
|
quit(-1)
|
||||||
|
|
||||||
|
w.makeContextCurrent()
|
||||||
|
|
||||||
|
doAssert glInit()
|
||||||
|
|
||||||
|
let context = igCreateContext()
|
||||||
|
let io = igGetIO()
|
||||||
|
io[].iniFilename = nil
|
||||||
|
|
||||||
|
doAssert igGlfwInitForOpenGL(w, true)
|
||||||
|
doAssert igOpenGL3Init()
|
||||||
|
|
||||||
|
igStyleColorsCherry()
|
||||||
|
|
||||||
|
var frameTimer = cpuTime() + 0.016666
|
||||||
|
var javaBuf {.global.} = newString(2048)
|
||||||
|
if fileExists("javaArgs"):
|
||||||
|
superUnsafeSet(javaBuf, readFile("javaArgs"), 2048)
|
||||||
|
else:
|
||||||
|
superUnsafeSet(javaBuf, "-Xmx1024m -Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true", 2048)
|
||||||
|
|
||||||
|
while not w.windowShouldClose:
|
||||||
|
frameTimer = cpuTime() + 0.016
|
||||||
|
glfwPollEvents()
|
||||||
|
|
||||||
|
igOpenGL3NewFrame()
|
||||||
|
igGlfwNewFrame()
|
||||||
|
igNewFrame()
|
||||||
|
|
||||||
|
igSetNextWindowPos(zeroPos)
|
||||||
|
|
||||||
|
igBegin("MAGIC MISSILE", flags=ImGuiWindowFlags.NoResize or ImGuiWindowFlags.NoBringToFrontOnFocus or ImGuiWindowFlags.NoCollapse)
|
||||||
|
var mainWinX, mainWinY: int32
|
||||||
|
w.getFramebufferSize(addr mainWinX, addr mainWinY)
|
||||||
|
igSetWindowSize(ImVec2(x: mainWinX.float32, y: mainwinY.float32))
|
||||||
|
|
||||||
|
igText(javaStatus.cstring)
|
||||||
|
if not javaExists:
|
||||||
|
igPushId(1)
|
||||||
|
if not downloadingJava:
|
||||||
|
igSameLine(igGetWindowWidth() - 70)
|
||||||
|
if igButton("Download", ImVec2(x: 0, y: 0)):
|
||||||
|
asyncCheck getJava()
|
||||||
|
igPopId()
|
||||||
|
|
||||||
|
igPushId(2)
|
||||||
|
if not clientExists:
|
||||||
|
igText(clientStatus.cstring)
|
||||||
|
if not downloadingClient:
|
||||||
|
igSameLine(igGetWindowWidth() - 70)
|
||||||
|
if igButton("Download", ImVec2(x: 0, y: 0)):
|
||||||
|
asyncCheck getClient()
|
||||||
|
else:
|
||||||
|
igText(clientStatus.cstring)
|
||||||
|
igPopId()
|
||||||
|
|
||||||
|
igText("Client version:")
|
||||||
|
igSameLine()
|
||||||
|
igText(clientVersion)
|
||||||
|
|
||||||
|
if clientExists and javaExists:
|
||||||
|
igText("Java args:")
|
||||||
|
igSameLine()
|
||||||
|
igPushItemWidth(211)
|
||||||
|
igInputText("", javaBuf, 2048)
|
||||||
|
|
||||||
|
if igButton("Run", ImVec2(x: 288, y: 0)):
|
||||||
|
w.hideWindow()
|
||||||
|
var command = absolutePath(javaDir / "bin" / "java") & " " & (javaBuf.strip(chars={'\x00'}).split(" ") & @["-jar", absolutePath(getJarPath())]).join(" ")
|
||||||
|
var process = execCmdEx(command, workingDir=userDir)
|
||||||
|
w.showWindow()
|
||||||
|
igEnd()
|
||||||
|
# End simple window
|
||||||
|
|
||||||
|
igRender()
|
||||||
|
|
||||||
|
glClearColor(0.45f, 0.55f, 0.60f, 1.00f)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT)
|
||||||
|
|
||||||
|
igOpenGL3RenderDrawData(igGetDrawData())
|
||||||
|
|
||||||
|
w.swapBuffers()
|
||||||
|
|
||||||
|
try:
|
||||||
|
while frameTimer - cpuTime() > 0:
|
||||||
|
poll(((max(0, frameTimer - cpuTime())) * 1000).int)
|
||||||
|
|
||||||
|
except:
|
||||||
|
sleep(((max(0, frameTimer - cpuTime())) * 1000).int)
|
||||||
|
|
||||||
|
igOpenGL3Shutdown()
|
||||||
|
igGlfwShutdown()
|
||||||
|
context.igDestroyContext()
|
||||||
|
|
||||||
|
w.destroyWindow()
|
||||||
|
glfwTerminate()
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue