Compare commits

...

1 Commits

Author SHA1 Message Date
sindoring 6693fb5306 добавил сборку под наш сервер 2026-10-03 11:17:51 +04:00
6 changed files with 302 additions and 3 deletions
Generated
+55 -3
View File
@@ -543,7 +543,7 @@ dependencies = [
"sha1",
"smithay-clipboard",
"symphonia",
"toml",
"toml 0.8.23",
"wgpu",
"windows-sys 0.59.0",
"winit",
@@ -4382,6 +4382,18 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "moonwell"
version = "0.2.0"
dependencies = [
"benilla-app",
"benilla-buildstamp",
"bevy",
"image",
"winit",
"winresource",
]
[[package]]
name = "moxcms"
version = "0.8.1"
@@ -5901,6 +5913,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_spanned"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
dependencies = [
"serde_core",
]
[[package]]
name = "sha1"
version = "0.10.6"
@@ -6487,11 +6508,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
"serde_spanned 0.6.9",
"toml_datetime 0.6.11",
"toml_edit 0.22.27",
]
[[package]]
name = "toml"
version = "1.1.3+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c"
dependencies = [
"indexmap",
"serde_core",
"serde_spanned 1.1.1",
"toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"toml_writer",
"winnow 1.0.3",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
@@ -6527,7 +6563,7 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"serde_spanned 0.6.9",
"toml_datetime 0.6.11",
"toml_write",
"winnow 0.7.15",
@@ -6572,6 +6608,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "toml_writer"
version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
[[package]]
name = "tracing"
version = "0.1.44"
@@ -7899,6 +7941,16 @@ dependencies = [
"memchr",
]
[[package]]
name = "winresource"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0986a8b1d586b7d3e4fe3d9ea39fb451ae22869dcea4aa109d287a374d866087"
dependencies = [
"toml 1.1.3+spec-1.1.0",
"version_check",
]
[[package]]
name = "wit-bindgen"
version = "0.51.0"
+32
View File
@@ -0,0 +1,32 @@
[package]
name = "moonwell"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "The MoonWell launcher: platform branding on top of benilla"
[lints]
workspace = true
[features]
default = ["dev"]
dev = ["benilla-app/dev"]
tracy = ["benilla-app/tracy"]
trace_chrome = ["benilla-app/trace_chrome"]
[dependencies]
benilla-app = { path = "../benilla-app", default-features = false }
bevy.workspace = true
[target.'cfg(windows)'.dependencies]
image = { version = "0.25", default-features = false, features = ["ico"] }
winit = { version = "0.30", default-features = false }
[build-dependencies]
benilla-buildstamp = { path = "../benilla-buildstamp" }
winresource = "0.1.31"
[[bin]]
name = "MoonWell"
path = "src/main.rs"
test = false
+40
View File
@@ -0,0 +1,40 @@
# MoonWell
MoonWell starts benilla through `run_with` and adds its own window title and platform
branding. The client build banner identifies it as `extended`.
Build the player executable on Windows:
```powershell
cargo build -p moonwell --release --no-default-features
```
The executable is `target/release/MoonWell.exe`. Provide your own WoW 1.12.1
`Data/` or `WoW/Data/` beside it, or set `WOW_DATA` to your install's Data folder.
Local client state is in `benilla-config/` beside the executable.
For development, run `cargo run -p moonwell --profile play`. The `dev` feature
forwards benilla's instruments; disable it for a player build.
Replace `assets/moonwell.ico` with your own multi-resolution Windows icon and
rebuild to update both the executable's icon and the running window's icons.
The icon is embedded; the player does not need the source `.ico` file.
On macOS, build and package a player app from the repository root (Python 3.11+):
```sh
cargo build -p moonwell --release --no-default-features
python3 crates/moonwell/package_macos.py \
--binary target/release/MoonWell \
--icon /path/to/MoonWell.icns
```
This creates `target/release/bundle/MoonWell.app` with the MoonWell name and app
icon. Packaging requires a macOS executable and an ICNS icon; it does not convert a
Windows EXE into a Mac application. Build natively on each target Mac architecture.
Pass `--output` to choose a different destination and `--bundle-id` to set your
application identifier. An existing destination is never overwritten.
Launch the `.app` from Finder. Its launcher finds your own `Data/` or `WoW/Data/`
beside `MoonWell.app` and keeps `benilla-config/` there too, outside the bundle.
Explicit `WOW_DATA` and `BENILLA_HOME` values take priority.
+17
View File
@@ -0,0 +1,17 @@
//! Stamp the build and embed MoonWell's Windows icon and product metadata.
fn main() {
benilla_buildstamp::emit();
println!("cargo::rerun-if-changed=assets/moonwell.ico");
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
winresource::WindowsResource::new()
.set_icon("assets/moonwell.ico")
.set("ProductName", "MoonWell")
.set("FileDescription", "MoonWell")
.set("InternalName", "MoonWell")
.set("OriginalFilename", "MoonWell.exe")
.compile()
.expect("compile MoonWell's Windows resources");
}
}
+89
View File
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""Package a macOS player build and an ICNS icon as MoonWell.app."""
import argparse
import os
from pathlib import Path
import plistlib
import shutil
import struct
import tomllib
# Keep the install and writable client state beside the app, outside the bundle.
LAUNCHER = '''#!/bin/sh
set -eu
macos_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
player_dir=$(CDPATH= cd -- "$macos_dir/../../.." && pwd)
if [ "${BENILLA_HOME+x}" != x ]; then
export BENILLA_HOME="$player_dir/benilla-config"
fi
if [ "${WOW_DATA+x}" != x ]; then
for data_dir in "$player_dir/Data" "$player_dir/WoW/Data"; do
if [ -d "$data_dir" ]; then
export WOW_DATA="$data_dir"
break
fi
done
fi
exec "$macos_dir/MoonWell" "$@"
'''
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--binary", type=Path, required=True,
help="MoonWell binary built on macOS without default features")
parser.add_argument("--icon", type=Path, required=True, help="application icon in .icns format")
parser.add_argument("--output", type=Path, default=Path("target/release/bundle/MoonWell.app"))
parser.add_argument("--bundle-id", default="org.moonwell.client")
args = parser.parse_args()
with args.binary.open("rb") as binary:
magic = binary.read(4)
if magic not in (b"\xfe\xed\xfa\xce", b"\xce\xfa\xed\xfe",
b"\xfe\xed\xfa\xcf", b"\xcf\xfa\xed\xfe",
b"\xca\xfe\xba\xbe", b"\xbe\xba\xfe\xca",
b"\xca\xfe\xba\xbf", b"\xbf\xba\xfe\xca"):
parser.error("--binary must be a macOS Mach-O executable, not a Windows EXE")
with args.icon.open("rb") as icon:
header = icon.read(8)
if len(header) != 8 or header[:4] != b"icns" or struct.unpack(">I", header[4:])[0] != args.icon.stat().st_size:
parser.error("--icon must be an ICNS file with a valid container header")
if args.output.suffix != ".app":
parser.error("--output must end in .app")
if args.output.exists():
parser.error("--output already exists; choose a new path or remove the old bundle first")
root = Path(__file__).resolve().parents[2]
with (root / "Cargo.toml").open("rb") as manifest:
version = tomllib.load(manifest)["workspace"]["package"]["version"]
contents = args.output / "Contents"
macos = contents / "MacOS"
resources = contents / "Resources"
macos.mkdir(parents=True)
resources.mkdir()
shutil.copyfile(args.binary, macos / "MoonWell")
(macos / "MoonWell").chmod(0o755)
(macos / "launch").write_text(LAUNCHER, encoding="utf-8", newline="\n")
(macos / "launch").chmod(0o755)
shutil.copyfile(args.icon, resources / "MoonWell.icns")
with (contents / "Info.plist").open("wb") as plist:
plistlib.dump({
"CFBundleName": "MoonWell",
"CFBundleDisplayName": "MoonWell",
"CFBundleExecutable": "launch",
"CFBundleIconFile": "MoonWell.icns",
"CFBundleIdentifier": args.bundle_id,
"CFBundleInfoDictionaryVersion": "6.0",
"CFBundlePackageType": "APPL",
"CFBundleShortVersionString": version,
"CFBundleVersion": version,
"NSHighResolutionCapable": True,
}, plist)
print(os.fspath(args.output.resolve()))
if __name__ == "__main__":
main()
+69
View File
@@ -0,0 +1,69 @@
//! MoonWell's branding lives in this launcher, on top of the stock client.
use benilla_app::BuildId;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;
struct MoonWellPlugin;
impl Plugin for MoonWellPlugin {
fn build(&self, app: &mut App) {
let world = app.world_mut();
for mut window in world
.query_filtered::<&mut Window, With<PrimaryWindow>>()
.iter_mut(world)
{
window.title = "MoonWell".into();
window.name = Some("MoonWell".into());
}
#[cfg(windows)]
app.add_systems(Startup, set_window_icon);
}
}
/// An exclusive system keeps winit's thread-local window access on the main thread.
#[cfg(windows)]
fn set_window_icon(world: &mut World) {
use winit::platform::windows::WindowExtWindows;
let image = image::load_from_memory_with_format(
include_bytes!("../assets/moonwell.ico"),
image::ImageFormat::Ico,
)
.expect("decode MoonWell's embedded icon")
.into_rgba8();
let (width, height) = image.dimensions();
let icon = winit::window::Icon::from_rgba(image.into_raw(), width, height)
.expect("create MoonWell's window icon");
let entity = world
.query_filtered::<Entity, With<PrimaryWindow>>()
.single(world)
.expect("the client has one primary window");
bevy::winit::WINIT_WINDOWS.with_borrow(|windows| {
let window = windows
.get_window(entity)
.expect("the primary window exists before Startup");
window.set_window_icon(Some(icon.clone()));
window.set_taskbar_icon(Some(icon));
});
}
fn main() -> benilla_app::AppExit {
benilla_app::run_with(
BuildId {
version: env!("CARGO_PKG_VERSION"),
describe: env!("BENILLA_GIT_DESCRIBE"),
sha: env!("BENILLA_GIT_SHA"),
short: env!("BENILLA_GIT_SHORT"),
date: env!("BENILLA_GIT_DATE"),
profile: env!("BENILLA_PROFILE"),
project_dir: env!("BENILLA_PROJECT_DIR"),
..Default::default()
},
|app| {
app.add_plugins(MoonWellPlugin);
},
)
}