Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2215482c2 | ||
|
|
59dae0f601 | ||
|
|
4d70e13629 | ||
|
|
83bc17970a | ||
|
|
72078e4fec | ||
|
|
f5bd835496 | ||
|
|
f2fe179109 | ||
|
|
b1d91ab5d8 | ||
|
|
f09e89e324 | ||
|
|
3c8f7c08ec |
@@ -7,6 +7,11 @@ on:
|
||||
types:
|
||||
- opened
|
||||
|
||||
# Ensure only one task can execute for a given PR at a time.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref }}
|
||||
queue: max
|
||||
|
||||
|
||||
jobs:
|
||||
# Apply `status: pending triage` to newly created pull requests
|
||||
|
||||
@@ -13,6 +13,10 @@ name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
# Ensure only one task can execute for a given PR at a time.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref }}
|
||||
queue: max
|
||||
|
||||
jobs:
|
||||
# Apply labels to pull requests based on which files were edited
|
||||
|
||||
+13
-3
@@ -4,19 +4,29 @@ All notable changes will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.8.7] - 2026-08-23
|
||||
|
||||
### Fixed
|
||||
|
||||
- [ANDROID] Fixed a crash when opening an FNFC chart file.
|
||||
- [ANDROID] Fixed errors and crashes related to the lime backend.
|
||||
- [ANDROID] Fixed a shader not displaying correctly in some places.
|
||||
|
||||
|
||||
|
||||
## [0.8.6] - 2026-08-12
|
||||
|
||||
### Added
|
||||
|
||||
- Added the ability to toggle Discord RPC statuses and hide song info.
|
||||
- (Linux) Added support for Wayland, which the game now defaults to. (Thanks Starexify!)
|
||||
- [LINUX] Added support for Wayland, which the game now defaults to. (Thanks Starexify!)
|
||||
- Added the game version as a compilation flag for modders to access. ([e51ae10](https://github.com/FunkinCrew/Funkin/commit/e51ae1098a9392c7ec3a903543f3aa4fc4220da1)) - by @zxcksharks in [#7659](https://github.com/FunkinCrew/Funkin/pull/7659)
|
||||
- Added a shouldBop property to HealthIconData to allow animated icons to bop. ([cc91faa](https://github.com/FunkinCrew/Funkin/commit/cc91faaccc63d2050270723bd49477f8b518ab6f)) - by @Starexify in [#6901](https://github.com/FunkinCrew/Funkin/pull/6901)
|
||||
- Added album and sticker pack fields to the Chart Editor Metadata window. ([790e3fb](https://github.com/FunkinCrew/Funkin/commit/790e3fb097b7054e7cf4010d6b588264414d283a)) - by @Starexify in [#6266](https://github.com/FunkinCrew/Funkin/pull/6266)
|
||||
|
||||
### Changed
|
||||
|
||||
- (HTML5) The “Touch To Play” sprite now smoothly scales when hovered.
|
||||
- [HTML5] The “Touch To Play” sprite now smoothly scales when hovered.
|
||||
- Made some improvements to width/height and cliprect functionality for FunkinGroup.
|
||||
- The Chart Editor now consistently exports chart data in the same order. (Thanks TechnikTil!)
|
||||
- Discord RPC images can now be configured in the album and song data files.
|
||||
@@ -33,7 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Preprocessors that span the entire file no longer throw an error. (Thanks KoloInDaCrib!)
|
||||
- Scripted class extending no longer breaks with multiple scripted layers. (Thanks TechnikTil!)
|
||||
- Imports with module names (ex. `funkin.play.character.BaseCharacter.CharacterType`) no longer throw an import error. (Thanks NotHyper-474!)
|
||||
- (iOS) Connecting a keyboard no longer freezes the game.
|
||||
- [iOS] Connecting a keyboard no longer freezes the game.
|
||||
- The Darken blend mode no longer renders with black boxes, fixing the Boyfriend Freeplay DJ Dad animation.
|
||||
- The Open File dialog now opens from the latest directory, not the root directory.
|
||||
- The Chart Editor now exports charts with correct suffixes for vocal tracks.
|
||||
|
||||
+1
-1
Submodule assets updated: 9300719cb2...724eba9de9
@@ -9,6 +9,10 @@
|
||||
"asset": "assets/preload/images/NOTE_assets.png",
|
||||
"blocksize": "4x4"
|
||||
},
|
||||
{
|
||||
"asset": "assets/shared/images/characters/darnell/spritemap1.png",
|
||||
"blocksize": "4x4"
|
||||
},
|
||||
{
|
||||
"asset": "assets/preload/images/NOTE_hold_assets.png",
|
||||
"blocksize": "4x4"
|
||||
|
||||
@@ -60,7 +60,7 @@ This section provides guidelines to follow when [opening an issue](https://githu
|
||||
|
||||
## Requirements
|
||||
Make sure you're playing:
|
||||
- the latest version of the game (currently v0.8.6) or a public playtest version (v0.9 Feature Preview builds)
|
||||
- the latest version of the game (currently v0.8.6, or v0.8.7 for Android) or a public playtest version (v0.9 Feature Preview builds)
|
||||
- without any mods (unless the issue involves mods)
|
||||
- on [Newgrounds](https://www.newgrounds.com/portal/view/770371) or downloaded from [itch.io](https://ninja-muffin24.itch.io/funkin)
|
||||
|
||||
@@ -86,6 +86,7 @@ Here's a list of commonly suggested features and the reasons why they won't be a
|
||||
| Importing Charts from Psych Engine (and other mod content) | https://github.com/FunkinCrew/Funkin/issues/2586#issuecomment-2125733327 |
|
||||
| Backwards Compatibility for Modding | https://github.com/FunkinCrew/Funkin/issues/3949#issuecomment-2608391329 |
|
||||
| Lua Support | https://github.com/FunkinCrew/Funkin/issues/2643#issuecomment-2143718093 |
|
||||
| Note Hitsounds | https://github.com/FunkinCrew/Funkin/pull/4112#issuecomment-5347549977 |
|
||||
|
||||
## Issue Types
|
||||
Choose the issue template that best suits your needs!
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
{
|
||||
"name": "lime",
|
||||
"type": "git",
|
||||
"ref": "ad0080e7e1df97d06060ea6cf5ce8f8088c3b872",
|
||||
"ref": "268dacfb2609766e14bef9ea5b669e91501852d2",
|
||||
"url": "https://github.com/FunkinCrew/lime"
|
||||
},
|
||||
{
|
||||
@@ -201,7 +201,7 @@
|
||||
{
|
||||
"name": "openfl",
|
||||
"type": "git",
|
||||
"ref": "2e5fc2062fb07b40f81b45268085a2efdb2eb9ae",
|
||||
"ref": "74a51908a116d6df74be1083e219abb9fa057636",
|
||||
"url": "https://github.com/FunkinCrew/openfl"
|
||||
},
|
||||
{
|
||||
|
||||
+8
-14
@@ -32,13 +32,13 @@ class Project extends HXProject
|
||||
* REMEMBER TO CHANGE THIS WHEN THE GAME UPDATES!
|
||||
* You only have to change it here, the rest of the game will query this value.
|
||||
*/
|
||||
static final VERSION:String = "0.8.6";
|
||||
static final VERSION:String = "0.8.7";
|
||||
|
||||
/**
|
||||
* The build's number and version code.
|
||||
* Used when publishing the game to mobile app stores. Should increment with each patch.
|
||||
*/
|
||||
static final BUILD_NUMBER:Int = 100;
|
||||
static final BUILD_NUMBER:Int = 102;
|
||||
|
||||
/**
|
||||
* The game's name. Used as the default window title.
|
||||
@@ -105,16 +105,13 @@ class Project extends HXProject
|
||||
//
|
||||
|
||||
/**
|
||||
* The app's minimal Android SDK version.
|
||||
* The app's lime Android java extensions.
|
||||
*/
|
||||
static final ANDROID_MINIMUM_SDK_VERSION:Int = 28;
|
||||
|
||||
/**
|
||||
* The app's target Android SDK version.
|
||||
*/
|
||||
static final ANDROID_TARGET_SDK_VERSION:Int = 35;
|
||||
|
||||
static final ANDROID_EXTENSIONS:Array<String> = ["funkin.extensions.CallbackUtil", "funkin.extensions.FNFCExtension", "funkin.extensions.AudioSession"];
|
||||
static final ANDROID_EXTENSIONS:Array<String> = [
|
||||
"funkin.extensions.CallbackUtil",
|
||||
"funkin.extensions.FNFCExtension",
|
||||
"funkin.extensions.AudioSession"
|
||||
];
|
||||
|
||||
/**
|
||||
* The team ID to use for the iOS app. Configured in XCode.
|
||||
@@ -693,9 +690,6 @@ class Project extends HXProject
|
||||
this.excludeArchitectures.push(Architecture.ARMV7);
|
||||
}
|
||||
|
||||
config.set("android.minimum-sdk-version", ANDROID_MINIMUM_SDK_VERSION);
|
||||
config.set("android.target-sdk-version", ANDROID_TARGET_SDK_VERSION);
|
||||
|
||||
if (isRelease())
|
||||
{
|
||||
if (envConfig != null)
|
||||
|
||||
@@ -2,23 +2,26 @@ package funkin.extensions;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Build;
|
||||
import android.os.FileUtils;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.util.Base64;
|
||||
|
||||
import funkin.extensions.CallbackUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import org.haxe.extension.Extension;
|
||||
|
||||
import org.haxe.lime.HaxeObject;
|
||||
|
||||
public class FNFCExtension extends Extension
|
||||
{
|
||||
public static final String LOG_TAG = "FNFCExtension";
|
||||
@@ -69,61 +72,74 @@ public class FNFCExtension extends Extension
|
||||
}
|
||||
|
||||
public static String copyFNFCToCache(Uri uri) throws IOException
|
||||
{
|
||||
if (uri != null)
|
||||
{
|
||||
if (uri == null) return null;
|
||||
|
||||
File output = null;
|
||||
|
||||
try
|
||||
{
|
||||
String fileName = new File(uri.getPath()).getName();
|
||||
|
||||
// Clean some Uri leftovers
|
||||
if (fileName.contains(":"))
|
||||
fileName = fileName.split(":")[1];
|
||||
|
||||
File cacheFNFC = new File(mainContext.getCacheDir(), "fnfc");
|
||||
File output = new File(cacheFNFC, fileName);
|
||||
if (!cacheFNFC.exists() && !cacheFNFC.mkdirs())
|
||||
throw new IOException("Failed to create FNFC cache dir at: " + cacheFNFC.getAbsolutePath());
|
||||
|
||||
if (!cacheFNFC.exists())
|
||||
cacheFNFC.mkdir();
|
||||
output = new File(cacheFNFC, fnfcCacheName(uri));
|
||||
|
||||
if (output.exists())
|
||||
output.delete();
|
||||
|
||||
ParcelFileDescriptor parcelFileDescriptor = null;
|
||||
FileInputStream fileInputStream = null;
|
||||
OutputStream out = null;
|
||||
InputStream in = null;
|
||||
OutputStream out = null;
|
||||
|
||||
try
|
||||
{
|
||||
parcelFileDescriptor = mainContext.getContentResolver().openFileDescriptor(uri, "r");
|
||||
fileInputStream = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
|
||||
in = mainContext.getContentResolver().openInputStream(uri);
|
||||
if (in == null)
|
||||
throw new IOException("Failed to get input stream for Uri: " + uri.toString());
|
||||
|
||||
byte[] fileBytes = new byte[(int) parcelFileDescriptor.getStatSize()];
|
||||
fileInputStream.read(fileBytes);
|
||||
out = new FileOutputStream(output);
|
||||
|
||||
out = new FileOutputStream(output);
|
||||
out.write(fileBytes);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
{
|
||||
FileUtils.copy(in, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
Files.copy(in, output.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
if (output.exists())
|
||||
output.deleteOnExit(); // makes the file get deleted when the app closes ig?
|
||||
out.flush();
|
||||
}
|
||||
catch (IOException e)
|
||||
finally
|
||||
{
|
||||
Log.e(LOG_TAG, e.getMessage());
|
||||
if (in != null)
|
||||
in.close();
|
||||
if (out != null)
|
||||
out.close();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fileInputStream != null)
|
||||
fileInputStream.close();
|
||||
|
||||
if (parcelFileDescriptor != null)
|
||||
parcelFileDescriptor.close();
|
||||
if (output.length() <= 0)
|
||||
throw new IOException("The copied Uri file (" + uri.toString() + ") ended empty at: " + output.getAbsolutePath());
|
||||
|
||||
if (out != null)
|
||||
out.close();
|
||||
}
|
||||
return output.getAbsolutePath();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
Log.e("trace", "Failed to copy FNFC from " + uri.toString() + ". Error message: " + t.getMessage());
|
||||
if (output != null) output.delete();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return output.getAbsolutePath();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
private static String fnfcCacheName(Uri uri)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] digest = MessageDigest.getInstance("SHA-256")
|
||||
.digest(uri.toString().getBytes(StandardCharsets.UTF_8));
|
||||
return Base64.encodeToString(digest,
|
||||
Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING) + ".fnfc";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Integer.toHexString(uri.toString().hashCode()) + ".fnfc";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,14 +39,20 @@ class ChartPlaytestMenu extends MusicBeatState
|
||||
|
||||
playtestCam = new FunkinCamera('playtestCam');
|
||||
playtestCam.bgColor = 0x0;
|
||||
// playtestCam.alpha = 0;
|
||||
FlxG.cameras.add(playtestCam, false);
|
||||
cameras = [playtestCam];
|
||||
FlxG.cameras.reset(playtestCam);
|
||||
|
||||
subStateClosed.add((_) ->
|
||||
{
|
||||
FlxG.cameras.reset(playtestCam = new FunkinCamera('playtestCam'));
|
||||
playtestCam.bgColor = 0x0;
|
||||
cameras = [playtestCam];
|
||||
});
|
||||
|
||||
var blackBG:FunkinSprite = new FunkinSprite(0, 0);
|
||||
blackBG.makeSolidColor(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK);
|
||||
blackBG.scrollFactor.set();
|
||||
blackBG.alpha = 0.4;
|
||||
blackBG.cameras = [playtestCam];
|
||||
add(blackBG);
|
||||
|
||||
this.filePath = filePath;
|
||||
@@ -54,7 +60,6 @@ class ChartPlaytestMenu extends MusicBeatState
|
||||
songName = new FlxText(0, FlxG.height * 0.1, 0, 'Loaded Song: ${targetSong.songName}',
|
||||
30).setFormat(Paths.font('vcr.ttf'), 50, FlxColor.WHITE, FlxTextAlign.CENTER);
|
||||
songName.screenCenter(X);
|
||||
songName.cameras = [playtestCam];
|
||||
add(songName);
|
||||
|
||||
variationButton = new ChartPlaytestMenuButtonListToggle(0, FlxG.height * 0.55, "Variation", targetSong.variations, function(value:String)
|
||||
@@ -63,7 +68,6 @@ class ChartPlaytestMenu extends MusicBeatState
|
||||
variationButton.screenCenter(X);
|
||||
});
|
||||
variationButton.screenCenter(X);
|
||||
variationButton.cameras = [playtestCam];
|
||||
add(variationButton);
|
||||
|
||||
difficultyButton = new ChartPlaytestMenuButtonListToggle(0, FlxG.height * 0.45, "Difficulty",
|
||||
@@ -73,7 +77,6 @@ class ChartPlaytestMenu extends MusicBeatState
|
||||
difficultyButton.screenCenter(X);
|
||||
});
|
||||
difficultyButton.screenCenter(X);
|
||||
difficultyButton.cameras = [playtestCam];
|
||||
add(difficultyButton);
|
||||
|
||||
playtestButton = new ChartPlaytestMenuButton(0, FlxG.height * 0.8, "Playtest Song", function()
|
||||
@@ -88,7 +91,6 @@ class ChartPlaytestMenu extends MusicBeatState
|
||||
}
|
||||
});
|
||||
playtestButton.screenCenter(X);
|
||||
playtestButton.cameras = [playtestCam];
|
||||
add(playtestButton);
|
||||
|
||||
FlxTween.tween(playtestCam, {alpha: 1}, 0.5);
|
||||
|
||||
@@ -93,9 +93,8 @@ class TouchUtil
|
||||
if (object == null || touch == null) return false;
|
||||
|
||||
if (camera == null) camera = object.cameras[0];
|
||||
|
||||
@:privateAccess
|
||||
return object.overlapsPoint(touch.getWorldPosition(camera, object._point), true, camera);
|
||||
if (object._point != null) return object.overlapsPoint(touch.getWorldPosition(camera, object._point), true, camera);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user