diff --git a/.gitignore b/.gitignore index d10344d..b66e2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .direnv .envrc +result shimmering/data shimmering/logs diff --git a/README.md b/README.md index 89c235a..eea1ebd 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ SHIMMERING_CONFIG_DIR=shimmering/config SHIMMERING_LOG_DIR=shimmering/logs ``` -## Binaries +### Binaries The project currently exposes two binaries: @@ -44,26 +44,27 @@ The project currently exposes two binaries: - The `prepare-jackets` command prepares the provided jackets for running the bot (see the section below for more details) - The `analyse <...paths>` command is a command-line version of the `score magic` discord command. This is useful for debugging things like the OCR implementation, without having to transmit files over the network. -## Future binaries +### Work in progress -3. `shimmering-server` will be a server providing scoring data over HTTP. -4. `shimmering-discord-presence` will be a client application that talks to `shimmering-server` in order to update your discord "currently playing" status in order to reflect the charts you are currently playing. +These binaries are unstable at best, and broken at worst. + +3. `shimmering-server` provides functionality over HTTP +4. `shimmering-discord-presence` is a client application that talks to `shimmering-server` in order to update your discord "currently playing", showing off the scores you are getting. ### Fonts -The following fonts must be present in `$SHIMMERING_ASSET_DIR/fonts`: +The following fonts must be present in `$SHIMMERING_FONTS_DIR`: ``` -arial.ttf -exo-variable.ttf -geosans-light.ttf -kazesawa-bold.ttf -kazesawa-regular.ttf -noto-sans.ttf -saira-variable.ttf +Exo[wght].ttf +GeosansLight.ttf +Kazesawa-Bold.ttf +Kazesawa-Regular.ttf unifont.otf ``` +The `shimmering-fonts` derivation of the nix flake builds the aforementioned directory. + ### Assets Most of the assets in this repo have been drawn by me. You need to bring in your own song jackets and place them at `$SHIMMERING_ASSET_DIR/songs`. This directory must contain a subdirectory for each song in the game, with each subdirectory containing a default jacket at `base_256.jpg`. Different files can be created to override the jacket for each difficulty. For more details, check out the implementation in [./src/arcaea/jacket.rs](./src/arcaea/jacket.rs). diff --git a/flake.nix b/flake.nix index 7c91921..d56310d 100644 --- a/flake.nix +++ b/flake.nix @@ -21,24 +21,29 @@ # }; # toolchain = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default); # toolchain = pkgs.rust-bin.stable.latest.default; - toolchain = inputs.fenix.packages.${system}.complete.toolchain; + # toolchain = inputs.fenix.packages.${system}.complete.toolchain; + spkgs = inputs.self.packages.${system}; inherit (pkgs) lib; in { - packages.shimmeringmoon = pkgs.rustPlatform.buildRustPackage { - pname = "shimmeringmoon"; - version = "unstable-2024-09-06"; + packages = { + kazesawa = pkgs.callPackage ./nix/kazesawa.nix { }; + exo = pkgs.callPackage ./nix/exo.nix { }; + geosans-light = pkgs.callPackage ./nix/geosans-light.nix { }; - src = lib.cleanSource ./.; + shimmering-fonts = pkgs.callPackage ./nix/fonts.nix { + # Pass custom-packaged fonts + inherit (spkgs) exo kazesawa geosans-light; + }; - cargoLock = { - lockFile = ./Cargo.lock; - outputHashes = { - "hypertesseract-0.1.0" = "sha256-G0dos5yvvcfBKznAo1IIzLgXqRDxmyZwB93QQ6hVZSo="; - "plotters-0.4.0" = "sha256-9wtd7lig1vQ2RJVaEHdicfPZy2AyuoNav8shPMZ1EuE="; - }; + default = spkgs.shimmeringmoon; + shimmeringmoon = pkgs.callPackage ./nix/shimmeringmoon.nix { + # Pass the directory of fonts + inherit (spkgs) shimmering-fonts; }; }; + + # {{{ Devshell devShell = pkgs.mkShell rec { nativeBuildInputs = with pkgs; [ cargo @@ -50,24 +55,20 @@ ruff imagemagick pkg-config - - # clang - # llvmPackages.clang ]; + buildInputs = with pkgs; [ freetype fontconfig leptonica tesseract - # openssl sqlite ]; LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs; - - # compilation of -sys packages requires manually setting LIBCLANG_PATH - # LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; + SHIMMERING_FONTS_DIR = spkgs.shimmering-fonts; }; + # }}} } ); diff --git a/nix/exo.nix b/nix/exo.nix new file mode 100644 index 0000000..63f7cf3 --- /dev/null +++ b/nix/exo.nix @@ -0,0 +1,30 @@ +{ + stdenvNoCC, + fetchFromGitHub, + lib, +}: +stdenvNoCC.mkDerivation { + pname = "exo-1.0"; + version = "unstable-2021-08-26"; + src = fetchFromGitHub { + owner = "NDISCOVER"; + repo = "Exo-1.0"; + rev = "3be4f55b626129f17a3b82677703e48c03dc2052"; + sha256 = "1l6k8q20anjcl3x7piwakgkdajkcjw70r6vfqxl8vycr0fra104d"; + }; + + dontBuild = true; + + installPhase = '' + runHook preInstall + install -Dm644 $src/fonts/variable/*.ttf -t $out/share/fonts/truetype + runHook postInstall + ''; + + meta = { + description = "Exo 1.0 Font Family "; + homepage = "https://fonts.google.com/specimen/Exo"; + platforms = with lib.platforms; all; + license = lib.licenses.ofl; + }; +} diff --git a/nix/fonts.nix b/nix/fonts.nix new file mode 100644 index 0000000..a12bd77 --- /dev/null +++ b/nix/fonts.nix @@ -0,0 +1,25 @@ +{ + unifont, + exo, + kazesawa, + geosans-light, + stdenvNoCC, +}: +stdenvNoCC.mkDerivation { + name = "shimmering-fonts"; + + dontUnpack = true; + + installPhase = '' + mkdir -p $out + cp "${unifont}/share/fonts/opentype/unifont.otf" $out + cp "${exo}/share/fonts/truetype/Exo[wght].ttf" $out + cp "${kazesawa}/share/fonts/truetype/Kazesawa-Regular.ttf" $out + cp "${kazesawa}/share/fonts/truetype/Kazesawa-Bold.ttf" $out + cp "${geosans-light}/share/fonts/truetype/GeosansLight.ttf" $out + ''; + + meta = { + description = "Collection of fonts required by `shimmeringmoon` at runtime"; + }; +} diff --git a/nix/geosans-light.nix b/nix/geosans-light.nix new file mode 100644 index 0000000..082a48c --- /dev/null +++ b/nix/geosans-light.nix @@ -0,0 +1,27 @@ +{ + stdenvNoCC, + fetchzip, + lib, +}: +stdenvNoCC.mkDerivation { + name = "geosans-light"; + + src = fetchzip { + url = "https://dl.dafont.com/dl/?f=geo_sans_light"; + sha256 = "sha256-T4N+c8pNaak2cC9WQqj8iezqVs47COIrUJv5yvpEBH4="; + extension = "zip"; # The build otherwise fails because of the query param + stripRoot = false; + }; + + installPhase = '' + runHook preInstall + install -Dm644 $src/*.ttf -t $out/share/fonts/truetype + runHook postInstall + ''; + + meta = { + description = "Exo 1.0 Font Family "; + homepage = "https://www.dafont.com/geo-sans-light.font"; + platforms = with lib.platforms; all; + }; +} diff --git a/nix/kazesawa.nix b/nix/kazesawa.nix new file mode 100644 index 0000000..9d70cc3 --- /dev/null +++ b/nix/kazesawa.nix @@ -0,0 +1,27 @@ +{ + stdenvNoCC, + fetchzip, + lib, +}: +stdenvNoCC.mkDerivation rec { + pname = "kazesawa"; + version = "alpha-v1"; + src = fetchzip { + url = "https://github.com/kazesawa/kazesawa/releases/download/${version}/kazesawa.zip"; + sha256 = "JM6QfpsoWFQh4jUODflLOwoGoRaq8UqFnaGElzkT/H4="; + stripRoot = false; + }; + + installPhase = '' + runHook preInstall + install -Dm644 *.ttf -t $out/share/fonts/truetype + runHook postInstall + ''; + + meta = { + description = "Kazesawa Font: M+ with Source Sans Pro"; + homepage = "https://kazesawa.github.io/"; + platforms = with lib.platforms; all; + license = lib.licenses.ofl; + }; +} diff --git a/nix/shimmeringmoon.nix b/nix/shimmeringmoon.nix new file mode 100644 index 0000000..16ac519 --- /dev/null +++ b/nix/shimmeringmoon.nix @@ -0,0 +1,55 @@ +{ + rustPlatform, + lib, + + pkg-config, + makeWrapper, + + freetype, + fontconfig, + leptonica, + tesseract, + openssl, + sqlite, + shimmering-fonts, +}: +rustPlatform.buildRustPackage { + pname = "shimmeringmoon"; + version = "unstable-2024-09-06"; + + nativeBuildInputs = [ + pkg-config + makeWrapper + ]; + + buildInputs = [ + freetype + fontconfig + leptonica + tesseract + openssl + sqlite + shimmering-fonts + ]; + + # Tell the binary where to find the fonts + # postBuild = '' + # wrapProgram $out/bin/shimmering-discord-bot \ + # --set SHIMMERING_FONTS_DIR ${shimmering-fonts} + # ''; + + checkFlags = [ + # disable all tests + "--skip" + ]; + + src = lib.cleanSource ../.; + + cargoLock = { + lockFile = ../Cargo.lock; + outputHashes = { + "hypertesseract-0.1.0" = "sha256-G0dos5yvvcfBKznAo1IIzLgXqRDxmyZwB93QQ6hVZSo="; + "plotters-0.4.0" = "sha256-9wtd7lig1vQ2RJVaEHdicfPZy2AyuoNav8shPMZ1EuE="; + }; + }; +} diff --git a/src/assets.rs b/src/assets.rs index 8c9d5ee..9b47c02 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -43,8 +43,9 @@ pub fn get_asset_dir() -> PathBuf { // {{{ Font helpers #[inline] fn get_font(name: &str) -> RefCell { + let fonts_dir = get_path("SHIMMERING_FONTS_DIR"); let face = FREETYPE_LIB.with(|lib| { - lib.new_face(get_asset_dir().join("fonts").join(name), 0) + lib.new_face(fonts_dir.join(name), 0) .unwrap_or_else(|_| panic!("Could not load {} font", name)) }); RefCell::new(face) @@ -55,25 +56,17 @@ pub fn with_font( primary: &'static LocalKey>, f: impl FnOnce(&mut [&mut Face]) -> T, ) -> T { - UNI_FONT.with_borrow_mut(|uni| { - // NOTO_SANS_FONT.with_borrow_mut(|noto| { - // ARIAL_FONT.with_borrow_mut(|arial| { - primary.with_borrow_mut(|primary| f(&mut [primary, uni])) - // }) - // }) - }) + UNI_FONT.with_borrow_mut(|uni| primary.with_borrow_mut(|primary| f(&mut [primary, uni]))) } // }}} // {{{ Font loading +// TODO: I might want to embed those into the binary 🤔 thread_local! { pub static FREETYPE_LIB: Library = Library::init().unwrap(); -pub static SAIRA_FONT: RefCell = get_font("saira-variable.ttf"); -pub static EXO_FONT: RefCell = get_font("exo-variable.ttf"); -pub static GEOSANS_FONT: RefCell = get_font("geosans-light.ttf"); -pub static KAZESAWA_FONT: RefCell = get_font("kazesawa-regular.ttf"); -pub static KAZESAWA_BOLD_FONT: RefCell = get_font("kazesawa-bold.ttf"); -pub static NOTO_SANS_FONT: RefCell = get_font("noto-sans.ttf"); -pub static ARIAL_FONT: RefCell = get_font("arial.ttf"); +pub static EXO_FONT: RefCell = get_font("Exo[wght].ttf"); +pub static GEOSANS_FONT: RefCell = get_font("GeosansLight.ttf"); +pub static KAZESAWA_FONT: RefCell = get_font("Kazesawa-Regular.ttf"); +pub static KAZESAWA_BOLD_FONT: RefCell = get_font("Kazesawa-Bold.ttf"); pub static UNI_FONT: RefCell = get_font("unifont.otf"); } // }}}