Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
448f50e
chore(release): 7.0.1-alpha.1 [skip ci]
semantic-release-bot Sep 4, 2023
3edbce7
:sparkles: feat: ConstantSpeedPropeller
esnya Sep 6, 2023
c09ab17
Merge commit '5a0c2ba11da4ab76b286062aabe7dad1426ccf25' into alpha
esnya Sep 6, 2023
d26e2e1
chore(release): 7.1.0-alpha.1 [skip ci]
semantic-release-bot Sep 6, 2023
29ea5ad
:sparkles: feat: Add animation driver
esnya Sep 7, 2023
ad2fc19
:sparkles: feat: Failures for constant speed propeller
esnya Sep 8, 2023
49671d8
:bento: chore: Add tag
esnya Sep 8, 2023
52124ae
:bento: chore: Prefab upgrade
esnya Sep 9, 2023
8f77009
:sparkles: feat(dfunc-slider): Add value scaler
esnya Sep 9, 2023
46e220b
:sprakles: feat(sfext-constant-speed-propeller): Stop engine on airVe…
esnya Sep 9, 2023
e7fc935
:bug: fix: Fix rudder brake
esnya Sep 10, 2023
2bd5950
:bug: fix: Fix reset broken flags
esnya Sep 13, 2023
220918e
:sparkle: feat: Player-Strike for constant speed propeller
esnya Sep 13, 2023
dd2ac73
bugfix: Fix rudder break
tokitzkaze Nov 4, 2023
58ddfad
Merge pull request #23 from tokitzkaze/alpha
esnya Nov 5, 2023
677a05f
chore: upgrade to latest environment
Copilot Apr 7, 2026
4554592
security: remove com.unity.textmeshpro dependency (all versions flagg…
Copilot Apr 7, 2026
5dcc13f
chore: remove UdonToolkit (incompatible with latest VRChat SDK)
Copilot Apr 7, 2026
68f6a81
Merge pull request #40 from esnya/master
esnya Apr 7, 2026
4bfcfa7
Update Packages/com.nekometer.esnya.esnya-sf-addons/package.json
esnya Apr 7, 2026
f83d06c
Merge branch 'alpha' of https://github.com/esnya/EsnyaSFAddons into c…
Copilot Apr 7, 2026
8b63400
fix: pin Node to 22.14.0 and remove com.unity.textmeshpro dependency
Copilot Apr 7, 2026
19e5fcb
chore: upgrade InariUdon to 10.0.1, update README requirements, clean…
Copilot Apr 8, 2026
9449ee9
fix: add null/empty guards for onChange/onMin/onMax and fix typo in p…
Copilot Apr 8, 2026
0d52f92
feat: add custom Inspector editors for DFUNC_Slider and DFUNC_SendCus…
Copilot Apr 8, 2026
8257d2e
fix: use Array.CreateInstance for array injection and add .meta files…
Copilot Apr 8, 2026
954f10d
fix: show Force Update button for array-typed UdonSharpComponentInjec…
Copilot Apr 8, 2026
c59c1e3
chore: introduce udonsharp-lint with dotnet tool manifest and CI work…
Copilot Apr 8, 2026
c636ff2
Changes before error encountered
Copilot Apr 8, 2026
2e780ee
fix: address remaining review comments for drawer height and NotNull
esnya Apr 8, 2026
001a111
Merge pull request #39 from esnya/copilot/upgrade-to-latest-environment
esnya Apr 8, 2026
3b0d12a
add alpha prerelease release config
esnya Apr 9, 2026
1328c8e
fix: address propeller review feedback
esnya Apr 9, 2026
e6752eb
fix: keep propeller engine state in sync
esnya Apr 9, 2026
be130b6
fix: handle respawn and zero gear ratio
esnya Apr 9, 2026
b0d35de
ci: add reusable static and UdonSharp checks
esnya Apr 9, 2026
2e03928
fix: guard propeller failure arrays
esnya Apr 9, 2026
be0fb1b
fix: align ucs dependency with packaged prerelease
esnya Apr 9, 2026
a64dd85
fix: guard constant-speed propeller divisor inputs
esnya Apr 9, 2026
ec68421
chore: follow alpha dependencies
esnya Apr 9, 2026
0008774
fix: harden constant speed propeller failures
esnya Apr 9, 2026
9344f77
fix: adapt sf addons to current saccflight APIs
esnya Apr 9, 2026
d441f51
fix: move scene setup build hooks into editor assembly
esnya Apr 9, 2026
542c8c5
fix: restore sf addons editor scene setup hooks
esnya Apr 9, 2026
7e9bff6
fix: decouple esfascene setup editor assembly
esnya Apr 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"tktco.udonsharplinter": {
"version": "0.3.1",
"commands": [
"udonsharp-lint"
]
}
}
}
39 changes: 39 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Check

on:
push:
pull_request:

jobs:
static-checks:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: "22"
- uses: reviewdog/action-actionlint@v1
with:
fail_level: error
- name: Run static checks
run: bash scripts/run-static-checks.sh

udonsharp-lint:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
6.0.x
- name: Restore dotnet tools
run: dotnet tool restore
- name: Run UdonSharp Linter
run: dotnet tool run udonsharp-lint Packages
23 changes: 23 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: UdonSharp Lint

on:
push:
pull_request:

permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest
env:
DOTNET_ROLL_FORWARD: LatestMajor
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.x"
- name: Install UdonSharp Linter
run: dotnet tool restore
- name: Run UdonSharp Linter
run: dotnet tool run udonsharp-lint Packages
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
node-version: 22.14.0
- run: npm ci
- run: npx semantic-release
env:
Expand Down
6 changes: 6 additions & 0 deletions .releaserc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
branches:
- master
- main
- name: alpha
Comment thread
esnya marked this conversation as resolved.
prerelease: true

plugins:
- semantic-release-gitmoji
- "@semantic-release/npm"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void SFEXT_O_Explode()

public void SFEXT_G_Explode()
{
if (!EntityControl.LastAttacker || !EntityControl.LastAttacker.Using || Time.time - airVehicle.LastHitTime >= 5) return;
if (!EntityControl.LastAttacker || !EntityControl.LastAttacker.Using || Time.time - EntityControl.PilotExitTime >= 5) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore recent-hit window check for kill rewards

SFEXT_G_Explode() now gates reward payout on Time.time - EntityControl.PilotExitTime < 5, but PilotExitTime tracks seat exit, not when damage was dealt; after a vehicle has been occupied for more than ~5 seconds, this early return suppresses onKilled payouts even for legitimate kills. This is a behavior regression from the previous recent-hit guard and will cause attackers to miss kill rewards in normal combat sessions.

Useful? React with 👍 / 👎.


if (onKilled <= 0 || !airVehicle.Taxiing && (airVehicle.Occupied || Time.time - EntityControl.PilotExitTime < 5))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@
"name": "com.nekometer.esnya.esnya-sf-addons-ucs",
"references": [
"GUID:99835874ee819da44948776e0df4ff1d",
"GUID:823e7b1dbeb8b2a4c9d5014bf2a39093",
"GUID:30028048dda6a584cacbcdacfa19980d",
"GUID:5733a420a738f014796e614c37f22eca",
"GUID:c06a60146d220a445a50a3e2fdd223a6",
"GUID:80a8b162ac804404bae7b5fdc3041428",
"GUID:3c1bc1267eab5884ebe7f232c09ee0d9"
"SaccFlightAndVehicles.Runtime",
"InariUdonRuntime",
"UdonChips-fork",
"EsnyaSFAddons.Runtime",
"UdonSharp.Runtime",
"VRC.Udon"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [
"UDON"
],
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
}
13 changes: 8 additions & 5 deletions Packages/com.nekometer.esnya.esnya-sf-addons-ucs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
"name": "esnya"
},
"dependencies": {
"com.nekometer.esnya.esnya-sf-addons": "5.0.0",
"com.nekometer.esnya.inari-udon": "9.1.0",
"com.nekometer.esnya.udonchips-fork": "3.0.0",
"sh.orels.udontoolkit": "1.1.2"
"com.nekometer.esnya.esnya-sf-addons": "5.0.0-beta.49",
"com.nekometer.esnya.inari-udon": "https://github.com/esnya/InariUdon.git?path=/Packages/com.nekometer.esnya.inari-udon#alpha",
"com.nekometer.esnya.udonchips-fork": "3.0.0"
},
"unity": "2022.3",
"vpmDependencies": {
"com.vrchat.worlds": "3.7.0"
"com.vrchat.worlds": "3.10.2",
"com.nekometer.esnya.inari-udon": ">=10.0.0-alpha",
"com.nekometer.esnya.esnya-sf-addons": ">=5.0.0-beta.49",
"com.nekometer.esnya.udonchips-fork": ">=1.0.2",
"io.github.sacchan-vrc.sacc-flight-and-vehicles": ">=1.8.1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ private void OnGUI()

if (GUILayout.Button("Respawn"))
{
foreach (var airVehicle in entity.GetComponentsInChildren<SaccAirVehicle>(true)) UdonSharpEditorUtility.GetBackingUdonBehaviour(airVehicle).SendCustomEvent(nameof(SaccAirVehicle.SFEXT_O_RespawnButton));
entity.SendEventToExtensions("SFEXT_O_RespawnButton");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#if UNITY_EDITOR
using System.Linq;
using UdonSharp;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using SaccFlightAndVehicles;
using VRC.SDKBase.Editor.BuildPipeline;

namespace EsnyaSFAddons
{
public static class ESFASceneSetupEditorUtility
{
public static void SetupAll()
{
foreach (var setup in SceneManager.GetActiveScene().GetRootGameObjects()
.SelectMany(o => o.GetComponentsInChildren<ESFASceneSetup>(true)))
{
Setup(setup);
}
}

public static void Setup(ESFASceneSetup setup)
{
if (!setup) return;

var rootObjects = setup.gameObject.scene.GetRootGameObjects();
var killsBoard = rootObjects.SelectMany(o => o.GetComponentsInChildren<SaccScoreboard_Kills>(true)).FirstOrDefault();

foreach (var entity in rootObjects.SelectMany(o => o.GetComponentsInChildren<SaccEntity>(true)))
{
var airVehicle = entity.ExtensionUdonBehaviours.FirstOrDefault(e => e is SaccAirVehicle);
var extensions = setup.injectExtentions.Select(template =>
{
var obj = Object.Instantiate(template.gameObject, entity.transform);
var extension = obj.GetComponent(template.GetType()) as UdonSharpBehaviour;
obj.name = template.gameObject.name;

extension.SetProgramVariable("EntityControl", entity);
extension.SetProgramVariable("AirVehicle", airVehicle);

EditorUtility.SetDirty(extension);

return extension;
});

if (killsBoard)
{
var killTracker = entity.GetExtention(UdonSharpBehaviour.GetUdonTypeName<SAV_KillTracker>()) as SAV_KillTracker;
if (killTracker)
{
killTracker.KillsBoard = killsBoard;
EditorUtility.SetDirty(killTracker);
}

var killPenalty = entity.GetExtention(UdonSharpBehaviour.GetUdonTypeName<SFEXT_KillPenalty>()) as SFEXT_KillPenalty;
if (killPenalty)
{
killPenalty.KillsBoard = killsBoard;
EditorUtility.SetDirty(killPenalty);
}
}

if (setup.injectExtentions.Length > 0)
{
entity.ExtensionUdonBehaviours = entity.ExtensionUdonBehaviours.Concat(extensions).ToArray();
}

EditorUtility.SetDirty(entity);
}

foreach (var airVehicle in rootObjects.SelectMany(o => o.GetComponentsInChildren<SaccAirVehicle>(true)))
{
airVehicle.SeaLevel = setup.seaLevel;
airVehicle.RepeatingWorld = setup.repeatingWorld;
airVehicle.RepeatingWorldDistance = setup.repeatingWorldDistance;
EditorUtility.SetDirty(airVehicle);
}

var windchanger = rootObjects.Select(o => o.GetComponentInChildren<SAV_WindChanger>()).FirstOrDefault(c => c);
foreach (var windsock in rootObjects.SelectMany(o => o.GetComponentsInChildren<Windsock>(true)))
{
windsock.windChanger = windchanger;
EditorUtility.SetDirty(windsock);
}

Object.DestroyImmediate(setup, true);
}
}

public class ESFASceneSetupBuildCallback : IVRCSDKBuildRequestedCallback
{
public int callbackOrder => 11;

public bool OnBuildRequested(VRCSDKRequestedBuildType requestedBuildType)
{
ESFASceneSetupEditorUtility.SetupAll();
return true;
Comment on lines +91 to +98

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore play-mode scene setup hook

After moving setup logic out of ESFASceneSetup, the only remaining entry point is the build callback, so entering Play Mode no longer runs SetupAll(). In editor testing sessions this skips extension injection and scene wiring (kills board, wind changer links, air-vehicle world settings) unless the scene was preprocessed manually, which regresses behavior compared with the previous Awake-based setup path.

Useful? React with 👍 / 👎.

}
}
}
#endif

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions Packages/com.nekometer.esnya.esnya-sf-addons/Editor/ESFAUI.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
using SaccFlightAndVehicles;
Expand All @@ -6,6 +8,53 @@ namespace EsnyaSFAddons.Editor
{
public static class ESFAUI
{
/// <summary>
/// Draws a dropdown popup when <paramref name="options"/> is non-empty, otherwise falls back to a plain text field.
/// Handles the case where the current serialized value is not present in <paramref name="options"/> by
/// prepending a read-only placeholder entry so the existing value is not silently overwritten.
/// </summary>
public static void StringPopupOrField(SerializedProperty property, GUIContent label, string[] options)
{
if (options == null || options.Length == 0)
{
EditorGUILayout.PropertyField(property, label);
return;
}

var current = property.stringValue ?? string.Empty;
var idx = Array.IndexOf(options, current);

string[] displayOptions;
int displayIdx;
if (idx >= 0)
{
displayOptions = options;
displayIdx = idx;
}
else
{
var placeholder = string.IsNullOrEmpty(current) ? "(none)" : $"(current) {current}";
displayOptions = new[] { placeholder }.Concat(options).ToArray();
displayIdx = 0;
}

EditorGUI.BeginChangeCheck();
var newIdx = EditorGUILayout.Popup(label, displayIdx, displayOptions.Select(s => new GUIContent(s)).ToArray());
if (EditorGUI.EndChangeCheck() && newIdx != displayIdx)
{
if (idx >= 0)
{
property.stringValue = options[newIdx];
}
else if (newIdx > 0)
{
// User selected an actual option (skip placeholder at index 0)
property.stringValue = options[newIdx - 1];
}
}
}


public static bool MiniButton(string label)
{
return GUILayout.Button(label, EditorStyles.miniButton, GUILayout.ExpandWidth(false));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "EsnyaSFAddons.Editor",
"references": [
"GUID:3c1bc1267eab5884ebe7f232c09ee0d9",
"GUID:823e7b1dbeb8b2a4c9d5014bf2a39093",
"GUID:99835874ee819da44948776e0df4ff1d",
"GUID:30028048dda6a584cacbcdacfa19980d",
"GUID:80a8b162ac804404bae7b5fdc3041428",
"GUID:84265b35cca3905448e623ef3903f0ff",
"GUID:627c4d5cd580ddf41bd320e784fe8b9d",
"GUID:f253815156df439380cb4780773d184b",
"GUID:c06a60146d220a445a50a3e2fdd223a6"
"UdonSharp.Editor",
"UdonSharp.Runtime",
"VRC.Udon",
"VRC.Udon.Editor",
"VRC.SDKBase",
"VRC.SDKBase.Editor.BuildPipeline",
"InariUdonRuntime",
"SaccFlightAndVehicles.Runtime",
"EsnyaSFAddons.Runtime"
],
"includePlatforms": [
"Editor"
Expand All @@ -19,7 +19,7 @@
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": ["UDONSHARP"],
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
}
Loading
Loading