Skip to content

Commit

Permalink
Merge pull request #25 from tashcan/feature/macos
Browse files Browse the repository at this point in the history
Add macOS support
  • Loading branch information
tashcan authored Mar 25, 2024
2 parents 2355e09 + c7803a3 commit dfcdcf9
Show file tree
Hide file tree
Showing 87 changed files with 2,442 additions and 629 deletions.
14 changes: 14 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
root = true

[*]
end_of_line = lf
insert_final_newline = true

[*.{h,cc}]
charset = utf-8
indent_style = space
indent_size = 4

[*.lua]
indent_style = space
indent_size = 4
44 changes: 38 additions & 6 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ on:
branches:
- "**"
pull_request:
branches: [ "main", "dev" ]
branches: ["main", "dev"]

jobs:
build:
build-win:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
submodules: "recursive"

- uses: seanmiddleditch/gha-setup-ninja@master
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: amd64

- uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: latest
Expand All @@ -29,12 +29,44 @@ jobs:

- name: Build
run: xmake -y

- name: Package
run: |
mv build/windows/x64/releasedbg/stfc-community-patch.dll version.dll
- uses: actions/upload-artifact@v2
with:
name: stfc-community-patch
path: version.dll

build-mac:
runs-on: macos-13
steps:
- uses: actions/checkout@v4
with:
submodules: "recursive"

- uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: latest

- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master

- name: Configure
run: xmake f -m release -y -a x86_64 -v

- name: Build
run: xmake -y

- name: Install brew things
run: brew install create-dmg

- name: Create App Bundle
run: scripts/create-mac-dmg.sh

- uses: actions/upload-artifact@v2
with:
name: stfc-community-patch-installer.dmg
path: STFC-Community-Patch-Installer.dmg
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ version.aps
debug.log
/app/
/.xmake/
/vsxmake*/
/vsxmake*/
.DS_Store
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "macos-launcher/deps/PLzmaSDK"]
path = macos-launcher/deps/PLzmaSDK
url = https://github.com/OlehKulykov/PLzmaSDK.git
Binary file added assets/launcher.icns
Binary file not shown.
Binary file added assets/launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mac_installer_background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions macos-dylib/src/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <unistd.h>

#include "patches/patches.h"

__attribute__((constructor))
void myconstructor(int argc, const char **argv)
{
syslog(LOG_ERR, "[+] dylib injected in %s\n", argv[0]);
ApplyPatches();
}

void* operator new[](size_t size, const char* /*name*/, int /*flags*/, unsigned /*debugFlags*/, const char* /*file*/,
int /*line*/)
{
return malloc(size);
}

void* operator new[](size_t size, size_t /*alignment*/, size_t /*alignmentOffset*/, const char* /*name*/, int /*flags*/,
unsigned /*debugFlags*/, const char* /*file*/, int /*line*/)
{
return malloc(size);
}
8 changes: 8 additions & 0 deletions macos-dylib/xmake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
target("stfc-community-patch")
do
set_kind("shared")
add_files("src/*.cc")
add_deps("mods")
set_exceptions("cxx")
set_policy("build.optimization.lto", true)
end
1 change: 1 addition & 0 deletions macos-launcher/deps/PLzmaSDK
Submodule PLzmaSDK added at 9f48b9
254 changes: 254 additions & 0 deletions macos-launcher/src/ActionView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
import Foundation
import SwiftUI

struct ActionView: View, XSollaUpdaterDelegate {

@StateObject var gameUpdater = GameUpdaterViewModel()
@State private var gameVersion: Int = 0
@State private var gameUpdateAvailable: Bool = false
@State private var updating: Bool = false
@State private var updateAction: String = ""
@State private var updateSubAction: String = ""
@State private var updateProgress: Float = 0.0
@State private var gameInstalled: Bool = false
@State private var gameRunning: Bool = false
private var model = PulsatingViewModel()

func updateProgress(progress: XsollaUpdateProgress) {
switch progress {
case .Start(_):
break
case .Progress(let currentAction, let totalActions):
updateAction = "Updating \(currentAction) of \(totalActions)"
updateProgress = Float(currentAction) / Float(totalActions)
break
case .Extracting(_):
updateSubAction = "Extracting"
break
case .ExtractComplete(_):
break
case .Downloading(_):
updateSubAction = "Downloading"
break
case .DownloadComplete(_):
break
case .Patching(_):
updateSubAction = "Patching"
break
case .PatchingProgress(_, _):
break
case .PatchStepComplete:
break
case .PatchComplete:
break
case .Waiting:
updateSubAction = "Waiting"
break
case .ApplyVersion:
break
case .VersionApplied:
break
case .Finalizing:
updateSubAction = "Finalizing"
break
case .CleaningUp:
updateSubAction = "Cleaning Up"
break
case .Complete:
updateSubAction = "Complete"
break
}
}

var body: some View {
GeometryReader { geo in
Grid {
GridRow {
if gameInstalled {
Button {
} label: {
commonButton()
.foregroundColor(.lcarViolet)
}.buttonStyle(PlainButtonStyle())
Button {
withAnimation {
if gameUpdateAvailable && !updating {
Task {
do {
updating = true
updateAction = "Starting"
updateSubAction = "Planning"
try await gameUpdater.updateGame(delegate: self)
} catch {
print("Error updating game: \(error)")
}
updating = false
gameVersion = gameUpdater.getInstalledGameVersion()
gameUpdateAvailable = await gameUpdater.checkForGameUpdate()
}
}
}
} label: {
if gameUpdateAvailable {
commonButton(text: "Update Game!")
.foregroundColor(.lcarTan)
} else {
commonButton()
.foregroundColor(.lcarTan)
}
}.buttonStyle(PlainButtonStyle())
Button {
withAnimation {
launchGame()
}
} label: {
commonButton(text: "Engage!")
.foregroundColor(.lcarOrange)
}.buttonStyle(PlainButtonStyle())
} else {
Text("Game not installed")
.font(.custom("HelveticaNeue-CondensedBold", size: 40))
.foregroundColor(.lcarTan)
.offset(x: -45)
//Button {
// withAnimation {
// }
//} label: {
// commonButton(text: "Install Game!")
// .foregroundColor(.lcarTan)
//}.buttonStyle(PlainButtonStyle())
}

}
.opacity(updating || gameRunning ? 0.5 : 1.0)
.allowsHitTesting(!updating && !gameRunning)
}
.frame(width: geo.size.width, height: 150)
.offset(x: 85, y: 20)
.task {
repeat {
gameVersion = gameUpdater.getInstalledGameVersion()
gameInstalled = gameVersion > 0
gameVersion = gameUpdater.getInstalledGameVersion()
gameUpdateAvailable = await gameUpdater.checkForGameUpdate()
try? await Task.sleep(for: .seconds(60))
} while !Task.isCancelled

}
.overlay(alignment: .bottomTrailing) {
Text("Game Version: \(String(format: "%02d", gameVersion))")
.font(.custom("HelveticaNeue-CondensedBold", size: 17))
.foregroundColor(.lcarTan)
.offset(x: -10)
}
.overlay(alignment: .bottomLeading) {
if updating {
HStack {
PulsatingView(viewModel: model)
Text("\(updateAction) (\(updateSubAction))")
.font(.custom("HelveticaNeue-CondensedBold", size: 17))
.foregroundColor(.lcarTan)
.offset(x: -10)
}
.offset(x: 115, y: 10)
}
}
}
}

private func commonButton(text: String = "") -> some View {
RoundedRectangle(cornerRadius: 20)
.frame(width: 125, height: 50)
.overlay(alignment: .bottomTrailing) {
HStack {
Spacer()
Text(text.count > 0 ? text : "\(randomDigits(4))-\(randomDigits(3))")
.font(.custom("HelveticaNeue-CondensedBold", size: 17))
.foregroundColor(.black)
}
.scaleEffect(x: 0.7, anchor: .trailing)
.padding(.bottom, 5)
.padding(.trailing, 20)
}
}

private func randomDigits(_ count: Int) -> String {
(1...count)
.map { _ in "\(Int.random(in: 0...9))" }
.joined()
}

private func launchGame() {
DispatchQueue.global().async {
DispatchQueue.main.async {
gameRunning = true
}
let process = Process()
let helper = Bundle.main.path(forAuxiliaryExecutable: "stfc-community-patch-loader")
process.executableURL = URL(fileURLWithPath: helper!)
DispatchQueue.global().async {
do {
try process.run()
} catch {
DispatchQueue.main.async {
gameRunning = false
}
return
}
process.waitUntilExit()
DispatchQueue.main.async {
gameRunning = false
}
}
}
}
}

class PulsatingViewModel: ObservableObject {
@Published var colorIndex = 1
}

struct PulsatingView: View {

@ObservedObject var viewModel: PulsatingViewModel

func colourToShow() -> Color {
switch viewModel.colorIndex {
case 0:
return Color.lcarOrange
case 1:
return Color.lcarTan
case 2:
return Color.lcarViolet
default:
return Color.lcarPink
}
}

@State var animate = false
var body: some View {
VStack {
ZStack {
Circle().fill(colourToShow().opacity(0.25)).frame(width: 40, height: 40).scaleEffect(
self.animate ? 1 : 0)
Circle().fill(colourToShow().opacity(0.35)).frame(width: 30, height: 30).scaleEffect(
self.animate ? 1 : 0)
Circle().fill(colourToShow().opacity(0.45)).frame(width: 15, height: 15).scaleEffect(
self.animate ? 1 : 0)
Circle().fill(colourToShow()).frame(width: 16.25, height: 16.25)
}
.onAppear { self.animate = true }
.animation(
animate ? Animation.easeInOut(duration: 1.5).repeatForever(autoreverses: true) : .default,
value: animate
)
.onChange(of: viewModel.colorIndex) { _ in
self.animate = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.animate = true
}
}

}
}
}
Loading

0 comments on commit dfcdcf9

Please sign in to comment.