diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a672f32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +build +.build +.DS_Store +.gradle +gradle-daemon-jvm.properties +.idea +.kotlin +local.properties +Package.resolved +*.xcodeproj diff --git a/0000 b/0000 deleted file mode 100644 index e9cb6da..0000000 --- a/0000 +++ /dev/null @@ -1,5 +0,0 @@ -Привет | Hello -1.0.0 - -/привет|hello.череда -x /привет|hello.js diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..61fa521 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,151 @@ +# OGS Mahjong (`mj`) + +A macOS SwiftUI app for **OGS Mahjong**, built on the **Dialect v4** declarative +reactive engine (see the sibling `../dialect` repo — this project is a +downstream consumer of its code generator). + +Business logic lives in `dialect.yml` (YAML). A generator turns it into +`game/ver-mac/src/dialect.swift` (the runtime engine + `struct F` field +constants + component/should/effect registration). The Swift app shell +(`GameApp`/`AppDelegate`) and the SwiftUI views live outside the generated file +and talk to the engine through generated functions like `rootSet(...)`. + +Remote: `https://git.opengamestudio.org/mahjong/mahjong` · Version: `2.0.0` + +> Current `dialect.yml` is still the "Root / counter" template inherited from the +> dialect example — the Mahjong game logic has not been written yet. The app +> shell, packaging and symlink wiring are in place. + +## Structure + +``` +dialect.yml Single source of truth for the reactive logic. + Generates game/ver-mac/src/dialect.swift + +components/ SHARED source-of-truth for all components. + other/other.swift Shared helpers (otherPrintStderr, otherWriteFile, + otherSetupConsoleLogging, ...) + root/root.swift RootComponent (owns DialectController, registers + effects + shoulds, sets didSetup on setup()) + root/rootVM.swift RootVM (ObservableObject / @Published countText) + root/mac/view/RootView.swift Per-platform SwiftUI view + +game/ver-mac/ macOS app (SPM executable target "ogs-mahjong") + Package.swift SPM manifest (macOS 13+, swift-tools 5.9) + Info.plist Bundle id org.opengamestudio.Mahjong, exec ogs-mahjong + Resources/AppIcon.icns App icon + src/ + GameApp.swift @main SwiftUI App entry + AppDelegate.swift Creates RootComponent + RootVM, calls root.setup() + dialect.swift GENERATED — do not hand-edit (see chicken-egg below) + other/other.swift -> symlink components/other/other.swift + root/root.swift -> symlink components/root/root.swift + root/rootVM.swift -> symlink components/root/rootVM.swift + root/view/RootView.swift-> symlink components/root/mac/view/RootView.swift + +ref/swiftraylib Symlink to ../../swiftraylib — the raylib/SwiftUI + renderer sample the game will use for 3D rendering. + +util/ Build/run scripts (see Build & Run) + paths APP_MAC = .build/OGS Mahjong.app + build-mac generateDialect -> buildMac -> packageMac + run-mac runMac + rm-mac-geom Resets saved window geometry + step/ Sourced steps: generateDialect, buildMac, + packageMac, runMac + +history/gitjs/ GitJS "Glavred" history + the original JS source of the + web Mahjong, kept for reference — not part of the build. +``` + +## Symlink parity rule + +`components/` is the source of truth; `game/ver-mac/src/` contains real +directories whose files are **relative symlinks** back into `components/`: + +``` +src/other/other.swift -> ../../../../components/other/other.swift (4 up) +src/root/root.swift -> ../../../../components/root/root.swift (4 up) +src/root/rootVM.swift -> ../../../../components/root/rootVM.swift (4 up) +src/root/view/RootView.swift-> ../../../../../components/root/mac/view/RootView.swift (5 up) +``` + +SPM silently **skips** a dangling symlink (no error), so after moving +`components/` or a subdir, audit for broken links: + +```bash +find . -type l ! -exec test -e {} \; -not -path './.build/*' +``` + +## Prerequisite: the generator + +`util/step/generateDialect` calls the **sibling** dialect repo: + +```bash +$SDIR/../../dialect/util/run-generator --file=$SDIR/../dialect.yml +``` + +So `/Volumes/MOE/p/dialect` must exist and its generator must be built before +`util/build-mac` can regenerate: + +```bash +(cd ../dialect && util/build-generator) # once, or after dialect core changes +``` + +The generator resolves the `output:` path **relative to `dialect.yml`'s +directory**, which is why `dialect.yml` says `game/ver-mac/src/dialect.swift`. + +## Build & Run + +```bash +util/build-mac # generateDialect + swift build + package OGS Mahjong.app +util/run-mac # runs .build/OGS Mahjong.app/Contents/MacOS/ogs-mahjong +util/rm-mac-geom # reset the app's saved window geometry +``` + +`build-mac` sources `util/paths` then the `util/step/*` scripts in order: + +1. `generateDialect` — runs the sibling generator, writes `src/dialect.swift` +2. `buildMac` — `cd game/ver-mac && swift build` +3. `packageMac` — assembles `.build/OGS Mahjong.app` (binary `ogs-mahjong`, + `Info.plist`, `Resources/AppIcon.icns`) + +## Editing the dialect + +- Add/modify contexts and components in `dialect.yml`, then run + `util/build-mac` to regenerate `dialect.swift`. +- **Chicken-egg**: `struct F` (field-name constants) lives only in the + generated `dialect.swift`. Adding a new field to a context in `dialect.yml` + requires hand-patching its `static let = ""` into `struct F` + in `dialect.swift` (ASCII-alphabetical order) if you cannot regenerate first, + otherwise the build fails on `F.` being unresolved. +- `dialect.swift` is generated — edits there are overwritten on the next + `util/build-mac`. Change the source (`dialect.yml` / `components/`) instead. +- **Validate `dialect.yml` after edits** (e.g. `ruby -ryaml -e 'YAML.load_file("dialect.yml")'`). + Every should-branch label (`1. Upon each ...`) MUST end with a colon — the + parser (`components/yml/ymlFun.swift`) blindly `dropLast()`s it, so a missing + colon silently eats the label's last character in the generated `about` + comment. Note the file can never pass a *strict* YAML parser: condition and + reaction lines (under `if:` / `then:`) contain unquoted `: ` (e.g. + `c.countText = "Count: '\(c.count)'"`), which standard YAML rejects. So treat + a parser complaint pointing *inside* an `if:`/`then:` block as expected; any + complaint elsewhere (like a missing branch-label colon) is a real bug. + +## Swift 6 + +The project currently builds in Swift 5 language mode +(`util/step/buildMac` has the Swift 6 flag commented out). Enabling +`-Xswiftc -swift-version -Xswiftc 6` fails today on the singleton/`@MainActor` +concurrency errors (`RootComponent.singleton`, `RootVM.shared` in +`components/root/`, and the `RootVM.shared!.countText = ...` oneliner in the +generated `dialect.swift`). Do not flip it on without addressing those. + +## Conventions + +- `game/ver-mac/.build/`, `build/`, `.DS_Store`, Xcode/Gradle artifacts are + git-ignored. +- Prefer editing files in `components/` (the real files); the `src/` entries are + symlinks. +- The generated UI callback plumbing is nonisolated; UI singletons are weak + (`RootComponent.singleton`, `RootVM.shared`) and are accessed from the + generated oneliners with force-unwrap (`RootVM.shared!.countText = ...`). diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..34b3cf7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +Copyright (c) 2026 OpenGameStudio + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +=== +Third parties +=== + +raylib - Copyright (c) 2013-2026 Ramon Santamaria (@raysan5) diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..227cea2 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +2.0.0 diff --git a/components/other/other.swift b/components/other/other.swift new file mode 100644 index 0000000..a4f2737 --- /dev/null +++ b/components/other/other.swift @@ -0,0 +1,70 @@ +import Foundation + +/// Decode a base64 string back into a regular string +func otherBase64ToString(_ encoded: String) -> String { + guard + let data = Data(base64Encoded: encoded), + let str = String(data: data, encoding: .utf8) + else { + return "" + } + return str +} + +/// Capitalize the first letter of a string +func otherCapitalize(_ s: String) -> String { + guard let first = s.first else { + return s + } + return String(first).uppercased() + String(s.dropFirst()) +} + +/// Launch to wait for asynchrnous actions +func otherLaunch() { + RunLoop.current.run() +} + +/// Count leading spaces in a line +func otherLineIndent(_ line: String) -> Int { + var count = 0 + for ch in line { + if ch == " " { + count += 1 + } else { + break + } + } + return count +} + +/// Print to stderr +func otherPrintStderr(_ txt: String) { + if let dat = "\(txt)\n".data(using: .utf8) { + FileHandle.standardError.write(dat) + } +} + +/// Print each key/value processed by a controller into stderr +func otherSetupConsoleLogging( + _ ctrl: DialectController, + _ prefix: String +) { + ctrl.registerCallback { c -> Void in + let value = c.fieldAny(c.recentField) + let line = "ИГР \(prefix) k/v: '\(c.recentField)'/'\(value)'" + otherPrintStderr(line) + } +} + +/// Write output text to a file +func otherWriteFile( + _ path: String, + _ content: String +) { + try? content.write(toFile: path, atomically: true, encoding: .utf8) +} + +/// Terminate the main RunLoop +func otherShutdown() { + exit(0) +} diff --git a/components/root/mac/view/RootView.swift b/components/root/mac/view/RootView.swift new file mode 100644 index 0000000..ccd1ea7 --- /dev/null +++ b/components/root/mac/view/RootView.swift @@ -0,0 +1,24 @@ +import SwiftUI + +struct RootView: View { + @ObservedObject var vm: RootVM + + init(_ vm: RootVM) { + self.vm = vm + } + + var body: some View { + VStack(spacing: 16) { + Text("Hello, World!") + .font(.largeTitle) + + Text(vm.countText) + .font(.title3.monospacedDigit()) + + Button("Increment") { + rootSet(F.didClickIncrement, true) + } + } + .padding(40) + } +} diff --git a/components/root/root.swift b/components/root/root.swift new file mode 100644 index 0000000..97647f9 --- /dev/null +++ b/components/root/root.swift @@ -0,0 +1,14 @@ +class RootComponent { + let ctrl = DialectController(RootContext()) + static private(set) weak var singleton: RootComponent? + + init() { + Self.singleton = self + rootRegisterEffects(ctrl) + rootRegisterShoulds(ctrl) + } + + func setup() { + rootSet(F.didSetup, true) + } +} diff --git a/components/root/rootVM.swift b/components/root/rootVM.swift new file mode 100644 index 0000000..5823662 --- /dev/null +++ b/components/root/rootVM.swift @@ -0,0 +1,11 @@ +import Combine + +final class RootVM: ObservableObject { + @Published var countText = "" + + static private(set) weak var shared: RootVM? + + init() { + Self.shared = self + } +} diff --git a/dialect.yml b/dialect.yml new file mode 100644 index 0000000..fbf003b --- /dev/null +++ b/dialect.yml @@ -0,0 +1,51 @@ +version: 4 + +output: + game/ver-mac/src/dialect.swift: + type: swift + +RootComponent: + type: component + oneliners: + - countText: print(c.countText) + - countText: RootVM.shared!.countText = c.countText + shoulds: + count: + 1. Upon hitting 10 the first time: + if: + c.recentField == F.didClickIncrement && + c.count == 7 + then: + c.count += 10 + 2. Upon each button click: + if: + c.recentField == F.didClickIncrement + then: + c.count += 1 + countText: + 1. Upon each count change: + if: + c.recentField == F.count + then: + c.countText = "Count: '\(c.count)'" + 2. Upon launch: + if: + c.recentField == F.didLaunch + then: + c.countText = "Press the button to count" + didLaunch: + 1. Only once during the first setup: + if: + c.recentField == F.didSetup && + c.didLaunch == false + then: + c.didLaunch = true + +RootContext: + type: context + fields: + count: Int + countText: String + didClickIncrement: Bool + didLaunch: Bool + didSetup: Bool diff --git a/game/ver-mac/Info.plist b/game/ver-mac/Info.plist new file mode 100644 index 0000000..dc46284 --- /dev/null +++ b/game/ver-mac/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleName + OGS Mahjong + CFBundleDisplayName + OGS Mahjong + CFBundleIdentifier + org.opengamestudio.Mahjong + CFBundleExecutable + ogs-mahjong + CFBundleIconFile + AppIcon + CFBundlePackageType + APPL + CFBundleShortVersionString + 2.0.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + 11.0 + NSHighResolutionCapable + + + diff --git a/game/ver-mac/Package.swift b/game/ver-mac/Package.swift new file mode 100644 index 0000000..e2b4221 --- /dev/null +++ b/game/ver-mac/Package.swift @@ -0,0 +1,15 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "OGSMahjong", + platforms: [ + .macOS(.v13) + ], + targets: [ + .executableTarget( + name: "ogs-mahjong", + path: "src" + ) + ] +) diff --git a/game/ver-mac/Resources/AppIcon.icns b/game/ver-mac/Resources/AppIcon.icns new file mode 100644 index 0000000..0fb5686 Binary files /dev/null and b/game/ver-mac/Resources/AppIcon.icns differ diff --git a/game/ver-mac/src/AppDelegate.swift b/game/ver-mac/src/AppDelegate.swift new file mode 100644 index 0000000..9d214e6 --- /dev/null +++ b/game/ver-mac/src/AppDelegate.swift @@ -0,0 +1,22 @@ +import AppKit + +final class AppDelegate: + NSObject, + NSApplicationDelegate +{ + let root = RootComponent() + let rootVM = RootVM() + + func applicationDidFinishLaunching(_ notification: Notification) { + // Bring the app to the foreground + NSApp.setActivationPolicy(.regular) + NSApp.activate(ignoringOtherApps: true) + + otherSetupConsoleLogging(root.ctrl, "Root") + root.setup() + } + + func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + true + } +} diff --git a/game/ver-mac/src/GameApp.swift b/game/ver-mac/src/GameApp.swift new file mode 100644 index 0000000..65825ae --- /dev/null +++ b/game/ver-mac/src/GameApp.swift @@ -0,0 +1,14 @@ +import AppKit +import SwiftUI + +@main +struct GameApp: App { + @NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate + + var body: some Scene { + WindowGroup { + RootView(appDelegate.rootVM) + } + .defaultSize(width: 640, height: 480) + } +} diff --git a/game/ver-mac/src/dialect.swift b/game/ver-mac/src/dialect.swift new file mode 100644 index 0000000..4b69471 --- /dev/null +++ b/game/ver-mac/src/dialect.swift @@ -0,0 +1,276 @@ + +// Reusable "none" constant +public let DIALECT_CONTEXT_RECENT_FIELD_NONE = "none" + +// Base protocol for each component's state +public protocol DialectContext { + var recentField: String { get set } + + func field(_ name: String) -> T + func fieldAny(_ name: String) -> Any + mutating func setField(_ name: String, _ value: Any) +} + +// Default implementation of `fieldAny` method for the protocol +public extension DialectContext { + func fieldAny(_ name: String) -> Any { + return field(name) + } +} + +// The engine of the dialect components +public class DialectController { + var callbacks = [(DialectContext) -> Void]() + var context: DialectContext + var functions = [(DialectContext) -> DialectContext]() + var isProcessingQueue = false + var queue = [DialectContext]() + + public init(_ context: DialectContext) { + self.context = context + } + + func executeFunctions() { + let c = queue.removeFirst() + // Keep SSOT: Only allow single field change per should-function + context.recentField = c.recentField + context.setField(c.recentField, c.fieldAny(c.recentField)) + + for f in functions { + let ctx = f(context) + if ctx.recentField != DIALECT_CONTEXT_RECENT_FIELD_NONE { + queue.append(ctx) + } + } + + reportContext() + } + + func processQueue() { + // Prevent recursion. + if isProcessingQueue { + return + } + + isProcessingQueue = true + + while (queue.count > 0) { + executeFunctions() + } + + isProcessingQueue = false + } + + public func registerCallback(_ cb: @escaping (DialectContext) -> Void) { + callbacks.append(cb) + } + + public func registerFieldCallback( + _ fieldName: String, + _ cb: @escaping (DialectContext) -> Void + ) { + callbacks.append({ c in + if c.recentField == fieldName { + cb(c) + } + }) + } + + public func registerFunction(_ f: @escaping (DialectContext) -> DialectContext) { + functions.append(f) + } + + func reportContext() { + for cb in callbacks { + cb(context) + } + } + + public func set( + _ fieldName: String, + _ value: Any + ) { + var c = context + c.setField(fieldName, value) + c.recentField = fieldName + queue.append(c) + processQueue() + } +} + +// Register several oneliner callbacks to a controller +func registerOneliners( + _ ctrl: DialectController, + _ items: [Any] +) -> T? { + let halfCount = items.count / 2 + for i in 0.. Void + ctrl.registerFieldCallback(field) { cc in + let c = cc as! T + callback(c) + } + } + + // A hack for generics to operate + return nil +} + +// Context field names for static type check +public struct F { + public static let count = "count" + public static let countText = "countText" + public static let didClickIncrement = "didClickIncrement" + public static let didLaunch = "didLaunch" + public static let didSetup = "didSetup" + +} +public struct RootContext: DialectContext { + public var count = Int() + public var countText = String() + public var didClickIncrement = Bool() + public var didLaunch = Bool() + public var didSetup = Bool() + + public var recentField = "" + + public func field(_ name: String) -> T { + if (name == "count") { + return count as! T + } + else if (name == "countText") { + return countText as! T + } + else if (name == "didClickIncrement") { + return didClickIncrement as! T + } + else if (name == "didLaunch") { + return didLaunch as! T + } + else if (name == "didSetup") { + return didSetup as! T + } + + return "unknown-field-name" as! T + } + + public mutating func setField( + _ name: String, + _ value: Any + ) { + if (name == "count") { + count = value as! Int + } + else if (name == "countText") { + countText = value as! String + } + else if (name == "didClickIncrement") { + didClickIncrement = value as! Bool + } + else if (name == "didLaunch") { + didLaunch = value as! Bool + } + else if (name == "didSetup") { + didSetup = value as! Bool + } + + } +} + +public func rootSet( + _ key: String, + _ value: Any +) { + RootComponent.singleton!.ctrl.set(key, value) +} + +func rootShouldResetCount(_ c: RootContext) -> RootContext { + var c = c + + /* 1. Upon hitting 10 the first time */ + if + c.recentField == F.didClickIncrement && + c.count == 7 + { + c.count += 10 + c.recentField = F.count + return c + } + + /* 2. Upon each button click */ + if + c.recentField == F.didClickIncrement + { + c.count += 1 + c.recentField = F.count + return c + } + + + c.recentField = DIALECT_CONTEXT_RECENT_FIELD_NONE + return c +} + +func rootShouldResetCountText(_ c: RootContext) -> RootContext { + var c = c + + /* 1. Upon each count change */ + if + c.recentField == F.count + { + c.countText = "Count: '\(c.count)'" + c.recentField = F.countText + return c + } + + /* 2. Upon launch */ + if + c.recentField == F.didLaunch + { + c.countText = "Press the button to count" + c.recentField = F.countText + return c + } + + + c.recentField = DIALECT_CONTEXT_RECENT_FIELD_NONE + return c +} + +func rootShouldResetDidLaunch(_ c: RootContext) -> RootContext { + var c = c + + /* 1. Only once during the first setup */ + if + c.recentField == F.didSetup && + c.didLaunch == false + { + c.didLaunch = true + c.recentField = F.didLaunch + return c + } + + + c.recentField = DIALECT_CONTEXT_RECENT_FIELD_NONE + return c +} + +func rootRegisterShoulds(_ ctrl: DialectController) { + [ + rootShouldResetCount, + rootShouldResetCountText, + rootShouldResetDidLaunch, + + ].forEach { f in + ctrl.registerFunction { c in f(c as! RootContext) } + } +} + +func rootRegisterEffects(_ ctrl: DialectController) { + let _: RootContext? = registerOneliners(ctrl, [ + F.countText, { (c: RootContext) in print(c.countText) }, + F.countText, { (c: RootContext) in RootVM.shared!.countText = c.countText }, + + ]) +} diff --git a/game/ver-mac/src/other/other.swift b/game/ver-mac/src/other/other.swift new file mode 120000 index 0000000..f91488c --- /dev/null +++ b/game/ver-mac/src/other/other.swift @@ -0,0 +1 @@ +../../../../components/other/other.swift \ No newline at end of file diff --git a/game/ver-mac/src/root/root.swift b/game/ver-mac/src/root/root.swift new file mode 120000 index 0000000..5f11ed3 --- /dev/null +++ b/game/ver-mac/src/root/root.swift @@ -0,0 +1 @@ +../../../../components/root/root.swift \ No newline at end of file diff --git a/game/ver-mac/src/root/rootVM.swift b/game/ver-mac/src/root/rootVM.swift new file mode 120000 index 0000000..adfc760 --- /dev/null +++ b/game/ver-mac/src/root/rootVM.swift @@ -0,0 +1 @@ +../../../../components/root/rootVM.swift \ No newline at end of file diff --git a/game/ver-mac/src/root/view/RootView.swift b/game/ver-mac/src/root/view/RootView.swift new file mode 120000 index 0000000..c81285e --- /dev/null +++ b/game/ver-mac/src/root/view/RootView.swift @@ -0,0 +1 @@ +../../../../../components/root/mac/view/RootView.swift \ No newline at end of file diff --git a/history/gitjs/0000 b/history/gitjs/0000 new file mode 100644 index 0000000..16437e2 --- /dev/null +++ b/history/gitjs/0000 @@ -0,0 +1,7 @@ +Маджонг | Mahjong +0.2.0 +https://git.opengamestudio.org/mahjong/mahjong + +x /пуск|run.js +/пуск|run.череда +/📦 \ No newline at end of file diff --git a/history/gitjs/пуск|run.js b/history/gitjs/пуск|run.js new file mode 100644 index 0000000..113f74c --- /dev/null +++ b/history/gitjs/пуск|run.js @@ -0,0 +1,69 @@ + +const ИМЯ = "Маджонг | Mahjong"; + + +// // // // + + +ЗапуститьМаджонг = мир => +{ + мир.уведомить("ручной пуск"); + мир.уведомить("пуск маджонга"); +}; + + +// // // // + + +ЗадатьВерсиюМаджонга = мир => +{ + var модуль = мир.модули.модульПоИмени(ИМЯ); + мир.версия = модуль.версия; +}; + + +// // // // + + +ОчиститьСтраницу = мир => +{ + document.body.innerHTML = ""; +}; + + +// // // // + + +ЗагрузитьБиблиотекиМаджонга = мир => +{ + var указатели = []; + var модуль = мир.модули.модульПоИмени(ИМЯ); + var содержимое = модуль.содержимое["/📦"]; + var строки = содержимое.split(/\n/); + for (var номер in строки) + { + var строка = строки[номер]; + if (!строка.startsWith("#") && строка.length) + { + указатели.push(строка); + } + } + + var сообщение = "Загрузка библиотек Маджонга | Loading Mahjong libraries"; + console.debug(сообщение, указатели); + + var html = ""; + for (var номер in указатели) + { + var указатель = указатели[номер]; + html += `
  • ${указатель}
  • `; + } + document.body.innerHTML += `

    ${сообщение}

      ${html}
    `; + + мир.модули.использовали.подписатьРаз(function() { + мир.уведомить("загрузили библиотеки маджонга"); + }); + + мир.модули.использовать(указатели); +}; + diff --git a/history/gitjs/пуск|run.череда b/history/gitjs/пуск|run.череда new file mode 100644 index 0000000..6a17b20 --- /dev/null +++ b/history/gitjs/пуск|run.череда @@ -0,0 +1,6 @@ +пуск + загрузить библиотеки маджонга +загрузили библиотеки маджонга + очистить страницу + задать версию маджонга + запустить маджонг \ No newline at end of file diff --git a/history/gitjs/📦 b/history/gitjs/📦 new file mode 100644 index 0000000..3ad003e --- /dev/null +++ b/history/gitjs/📦 @@ -0,0 +1,12 @@ +https://bitbucket.org/gitjs/jquery/raw/3.5.1/0000 +https://bitbucket.org/gitjs/uikit/raw/3.2.0/0000 +https://git.opengamestudio.org/mahjong/threejs/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/base64/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/mahjong-osnova-base/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/mahjong-res/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/mahjong-otl-fishki-dbg-tiles/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/mahjong-raskladka-layout/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/mahjong-otl-raskladki-dbg-layouts/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/povtorniy-repeating-ui/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/mahjong-ui/raw/branch/master/0000 +https://git.opengamestudio.org/mahjong/mahjong-scena/raw/branch/master/0000 \ No newline at end of file diff --git a/ref/swiftraylib b/ref/swiftraylib new file mode 120000 index 0000000..012b5c7 --- /dev/null +++ b/ref/swiftraylib @@ -0,0 +1 @@ +../../swiftraylib \ No newline at end of file diff --git a/util/build-mac b/util/build-mac new file mode 100755 index 0000000..872a9f5 --- /dev/null +++ b/util/build-mac @@ -0,0 +1,10 @@ +#!/bin/bash -e +SDIR=$(cd "$(dirname "$0")" ; pwd -P) + +T=$SDIR/step +source $SDIR/paths + +STEP=0 +source $T/generateDialect +source $T/buildMac +source $T/packageMac diff --git a/util/paths b/util/paths new file mode 100644 index 0000000..9b43d63 --- /dev/null +++ b/util/paths @@ -0,0 +1 @@ +APP_MAC="$SDIR/../game/ver-mac/.build/OGS Mahjong.app" diff --git a/util/rm-mac-geom b/util/rm-mac-geom new file mode 100755 index 0000000..6b96fe6 --- /dev/null +++ b/util/rm-mac-geom @@ -0,0 +1,9 @@ +#!/bin/bash -e + +killall cfprefsd 2>/dev/null || true +sleep 1 + +rm -f $HOME/Library/Preferences/OGS\ Mahjong.plist \ + $HOME/Library/Preferences/org.opengamestudio.Mahjong.plist + +echo "removed app preferences (window geometry)" diff --git a/util/run-mac b/util/run-mac new file mode 100755 index 0000000..4a795e9 --- /dev/null +++ b/util/run-mac @@ -0,0 +1,8 @@ +#!/bin/bash -e +SDIR=$(cd "$(dirname "$0")" ; pwd -P) + +T=$SDIR/step +source $SDIR/paths + +STEP=0 +source $T/runMac diff --git a/util/step/buildMac b/util/step/buildMac new file mode 100755 index 0000000..19e41fb --- /dev/null +++ b/util/step/buildMac @@ -0,0 +1,7 @@ +#!/bin/bash -e + +STEP=$((STEP+1)) +echo -e "\n> > > > Step №$STEP. Build for macOS" + +cd $SDIR/../game/ver-mac +swift build # -Xswiftc -swift-version -Xswiftc 6 diff --git a/util/step/generateDialect b/util/step/generateDialect new file mode 100755 index 0000000..65357f5 --- /dev/null +++ b/util/step/generateDialect @@ -0,0 +1,6 @@ +#!/bin/bash -e + +STEP=$((STEP+1)) +echo -e "\n> > > > Step №$STEP. Generate Dialect" + +$SDIR/../../dialect/util/run-generator --file=$SDIR/../dialect.yml diff --git a/util/step/packageMac b/util/step/packageMac new file mode 100755 index 0000000..50d668a --- /dev/null +++ b/util/step/packageMac @@ -0,0 +1,15 @@ +#!/bin/bash -e + +STEP=$((STEP+1)) +echo -e "\n> > > > Step №$STEP. Make an app package for macOS" + +rm -rf "$APP_MAC" + +APP_DAT="$APP_MAC/Contents" + +mkdir -p "$APP_DAT/MacOS" +mkdir -p "$APP_DAT/Resources" + +cp "$SDIR/../game/ver-mac/.build/debug/ogs-mahjong" "$APP_DAT/MacOS/ogs-mahjong" +cp "$SDIR/../game/ver-mac/Info.plist" "$APP_DAT/Info.plist" +cp "$SDIR/../game/ver-mac/Resources/AppIcon.icns" "$APP_DAT/Resources/AppIcon.icns" diff --git a/util/step/runMac b/util/step/runMac new file mode 100755 index 0000000..93edc86 --- /dev/null +++ b/util/step/runMac @@ -0,0 +1,6 @@ +#!/bin/bash -e + +STEP=$((STEP+1)) +echo -e "\n> > > > Step №$STEP. Run macOS app" + +"$APP_MAC/Contents/MacOS/ogs-mahjong" diff --git a/привет|hello.js b/привет|hello.js deleted file mode 100644 index 14b90ca..0000000 --- a/привет|hello.js +++ /dev/null @@ -1,7 +0,0 @@ -ПоприветствоватьМир = function() -{ - console.log("Привет, мир!"); - console.log("Hello, world!"); - document.body.innerHTML += "

    Привет, мир!

    "; - document.body.innerHTML += "

    Hello, world!

    "; -}; diff --git a/привет|hello.череда b/привет|hello.череда deleted file mode 100644 index 278573b..0000000 --- a/привет|hello.череда +++ /dev/null @@ -1,2 +0,0 @@ -пуск - поприветствовать мир