update to latest engine release candidate

This commit is contained in:
2025-10-11 18:10:45 +02:00
parent 04bd2ee3e4
commit e020b64c86
74 changed files with 3862 additions and 889 deletions

2
.gitattributes vendored
View File

@@ -3,8 +3,10 @@
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
# Binary files should be left untouched
*.jar binary
*.bin filter=lfs diff=lfs merge=lfs -text

View File

@@ -13,10 +13,6 @@ jobs:
steps:
- uses: actions/checkout@v3
with:
lfs: true
fetch-depth: 1
- name: Set up JDK 21
uses: actions/setup-java@v3
@@ -35,6 +31,37 @@ jobs:
path: dist/portable/*-portable.jar
retention-days: 7
build-web:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
pages: write
steps:
- uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
cache: gradle
- name: Build Web Application
run: ./gradlew buildBundledWebApp
- name: Upload pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'dist/web-bundle'
- name: Deploy to GitHub Pages
if: github.event_name == 'release'
id: deployment
uses: actions/deploy-pages@v4
build-native:
runs-on: ${{ matrix.os }}
strategy:
@@ -51,9 +78,6 @@ jobs:
steps:
- uses: actions/checkout@v3
with:
lfs: true
fetch-depth: 1
- name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
@@ -63,15 +87,6 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
native-image-job-reports: 'true'
- name: Build Installer for ${{ matrix.platform }}
shell: bash
run: |
if [[ "${{ matrix.platform }}" == "linux" ]]; then
sudo apt-get install -y rpm
fi
./gradlew buildInstaller
ls -R dist
- name: Build Native Executable for ${{ matrix.platform }}
shell: bash
run: |

11
.gitignore vendored
View File

@@ -1,10 +1,15 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build
bin
dist
*.hprof
.idea
.DS_Store
gradle-local.properties
.idea/
node_modules/
*.map
.sourcemaps
.settings
platform-web/.env.nostr-deploy.local
local.properties

18
.vscode/launch.json vendored
View File

@@ -4,22 +4,22 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Current File",
"request": "launch",
"mainClass": "${file}"
},
{
"type": "java",
"name": "DesktopLauncher",
"name": "Debug Application",
"request": "launch",
"mainClass": "org.ngengine.platform.DesktopLauncher",
"projectName": "platform-desktop",
"osx": {
"vmArgs": "-XstartOnFirstThread"
}
},
"linux": {
"env": {
"__GL_THREADED_OPTIMIZATIONS": "0"
}
},
"vmArgs": "-ea -Dthreadwarden=true -Djava.util.logging.config.file=${workspaceFolder}/dev-logging.properties",
}
]
}

15
.vscode/settings.json vendored
View File

@@ -1,3 +1,16 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
"java.configuration.updateBuildConfiguration": "automatic",
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/.DS_Store": true,
"**/Thumbs.db": true,
"**/gradle": true,
"**/.gradle": true,
// "**/build": true,
"**/bin": true,
// "platform-*": true
}
}

View File

@@ -23,6 +23,7 @@ dependencies {
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

View File

@@ -12,34 +12,15 @@ import org.ngengine.demo.adc.PhysicsComponent;
import org.ngengine.demo.adc.PostprocessingComponent;
import org.ngengine.demo.adc.SoundComponent;
import org.ngengine.gui.win.NWindowManagerComponent;
import org.ngengine.nostr4j.keypair.NostrPublicKey;
import com.jme3.system.AppSettings;
public class Main {
public static NGEAppRunner main(String arg[]){
AppSettings settings = new AppSettings(true);
settings.setRenderer(AppSettings.LWJGL_OPENGL32);
settings.setWidth(1280);
settings.setHeight(720);
settings.setGammaCorrection(true);
settings.setSamples(2);
settings.setStencilBits(8);
settings.setDepthBits(24);
settings.setVSync(true);
settings.setGraphicsDebug(false);
settings.setX11PlatformPreferred(true);
settings.setTitle("Nostr Game Engine Demo");
settings.setEmulateMouse(true);
settings.setEmulateKeyboard(true);
NostrPublicKey appId = NostrPublicKey.fromBech32("npub1tc32kq8hr992tzvt09rwuc5wk6aa08pquqawasv20acjp4umny5q6axr4t");
NGEAppRunner appRunner = NGEApplication.createApp(appId, settings, app -> {
NGEAppRunner appRunner = NGEApplication.createApp( app -> {
ImmersiveAdComponent dep = app.enableAds();
ComponentManager mng = app.getComponentManager();

View File

@@ -15,7 +15,7 @@ import com.simsilica.lemur.HAlignment;
import com.simsilica.lemur.VAlignment;
public class HudComponent implements Component<Object>, InputHandlerFragment {
private Runnable closeHud;
private NHud hud;
@Override
public void onEnable(ComponentManager mng, Runner runner, DataStoreProvider dataStore, boolean firstTime,
@@ -26,22 +26,18 @@ public class HudComponent implements Component<Object>, InputHandlerFragment {
windowManager.showCursor(false);
this.closeHud= windowManager.showWindow(
NHud.class,
(win, err) -> {
win.setFitContent(false);
win.setFullscreen(true);
NLabel crossair = new NLabel("+");
crossair.setTextVAlignment(VAlignment.Center);
crossair.setTextHAlignment(HAlignment.Center);
win.getCenter().addChild(crossair);
}
);
this.hud = windowManager.showWindow( NHud.class );
hud.setFitContent(false);
hud.setFullscreen(true);
NLabel crossair = new NLabel("+");
crossair.setTextVAlignment(VAlignment.Center);
crossair.setTextHAlignment(HAlignment.Center);
hud.getCenter().addChild(crossair);
}
@Override
public void onDisable(ComponentManager mng, Runner runner, DataStoreProvider dataStore) {
this.closeHud.run();
hud.close();
}
@Override

View File

@@ -16,7 +16,7 @@ import com.simsilica.lemur.HAlignment;
import com.simsilica.lemur.VAlignment;
public class LoadingScreenComponent implements Component<Object>, LogicFragment {
private Runnable closeHud;
private NHud hud;
private NLabel txt;
@Override
public void onEnable(ComponentManager mng, Runner runner, DataStoreProvider dataStore, boolean firstTime,
@@ -29,22 +29,19 @@ public class LoadingScreenComponent implements Component<Object>, LogicFragment
txt = new NLabel("Loading");
this.closeHud= windowManager.showWindow(
NHud.class,
(win, err) -> {
win.setFitContent(false);
win.setFullscreen(true);
txt.setFontSize(32);
txt.setTextVAlignment(VAlignment.Center);
txt.setTextHAlignment(HAlignment.Center);
win.getCenter().addChild(txt);
}
);
hud = windowManager.showWindow(NHud.class);
hud.setFitContent(false);
hud.setFullscreen(true);
txt.setFontSize(32);
txt.setTextVAlignment(VAlignment.Center);
txt.setTextHAlignment(HAlignment.Center);
hud.getCenter().addChild(txt);
}
@Override
public void onDisable(ComponentManager mng, Runner runner, DataStoreProvider dataStore) {
this.closeHud.run();
hud.close();
}
float time = 0;

View File

@@ -83,7 +83,6 @@ public class MapComponent implements Component<Object>, AsyncAssetLoadingFragmen
preload.accept(sky);
} catch(Exception e){
e.printStackTrace();
System.exit(1);
}
}

View File

@@ -0,0 +1,47 @@
{
"AppId": "npub146wutmuxfmnlx9fcty0lkns2rpwhnl57kpes26mmt4hygalsakrsdllryz",
"Display": 0,
"Width": 1280,
"Height": 720,
"Fullscreen": false,
"Resizable": true,
"Title": "AdCity",
"Version": "1.0.0",
"VersionCode": 1,
"ShortName": "adc",
"Namespace":"org.ngengine.adc",
"Copyright": "",
"VSync": true,
"GammaCorrection": true,
"ScreenOrientation": "landscape",
"relays": {
"blossom": {
"default": [
"https://blossom.primal.net",
"https://blossom.band/"
]
},
"nostr": {
"ads":[
"wss://nostr.rblb.it",
"wss://relay.damus.io"
],
"default": [
"wss://relay.ngengine.org",
"wss://relay2.ngengine.org",
"wss://relay.damus.io",
"wss://relay.primal.net",
"wss://relay.nostr.band",
"wss://relay.snort.social",
"wss://nos.lol"
],
"nip46": [
"wss://relay.nsec.app",
"wss://relay.ngengine.org",
"wss://relay2.ngengine.org"
]
}
}
}

View File

@@ -2,19 +2,8 @@
org.gradle.configuration-cache=false
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
teaVmVersion=0.12.3
# NGE versions
ngePlatformVersion=0.1.3
ngeVersion=0.1
# Build targets
withDesktopPlatform=true
withAndroidPlatform=false
# Project settings
version=1.0.0
versionCode=1
projectName=adcity
applicationId=org.ngengine.demo.AdcDemo
copyright=Copyright (c) 2025
javaOptions=
ngePlatformVersion=0.2.1
ngeVersion=0.2-rc3

View File

@@ -8,9 +8,8 @@ constraintlayout = "2.2.1"
espressoCore = "3.7.0"
guava = "33.3.1-jre"
junit = "4.13.2"
junitVersion = "4.13.3-SNAPSHOT"
junitVersion = "4.13.2"
material = "1.12.0"
ngePlatformAndroid = "0.1.0-SNAPSHOT"
navigationFragment = "2.6.0"
navigationUi = "2.6.0"

View File

@@ -0,0 +1,54 @@
import javax.imageio.ImageIO
import java.awt.Image
import java.awt.image.BufferedImage
import java.awt.geom.Ellipse2D
gradle.ext.generateAndroidIcons = { inputLogoPath, outputDirPath ->
def inputLogo = file(inputLogoPath)
def outputDir = file(outputDirPath)
def densities = [
mdpi : 48,
hdpi : 72,
xhdpi: 96,
xxhdpi: 144,
xxxhdpi: 192
]
if (!inputLogo.exists()) {
throw new GradleException("Logo file not found at ${inputLogo}")
}
def original = ImageIO.read(inputLogo)
densities.each { name, size ->
def dir = new File(outputDir, "mipmap-${name}")
dir.mkdirs()
// --- Regular square launcher ---
def square = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB)
def g = square.createGraphics()
g.drawImage(original.getScaledInstance(size, size, Image.SCALE_SMOOTH), 0, 0, null)
g.dispose()
def launcherFile = new File(dir, "ic_launcher.png")
ImageIO.write(square, "png", launcherFile)
def launcherFileF = new File(dir, "ic_launcher_foreground.png")
ImageIO.write(square, "png", launcherFileF)
println "Generated ${launcherFile} (${size}x${size})"
// --- Round launcher ---
def round = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB)
def gr = round.createGraphics()
// Create circular clipping mask
gr.setClip(new Ellipse2D.Float(0, 0, size, size))
gr.drawImage(original.getScaledInstance(size, size, Image.SCALE_SMOOTH), 0, 0, null)
gr.dispose()
def roundFile = new File(dir, "ic_launcher_round.png")
ImageIO.write(round, "png", roundFile)
println "Generated ${roundFile} (circular ${size}x${size})"
}
}

View File

@@ -0,0 +1,231 @@
project.ext {
dynamicTargetTypes = [
'com.jme3.export.Savable',
'com.jme3.asset.AssetLoader',
'com.jme3.asset.plugins.FileLocator',
'com.jme3.network.Message',
// 'com.jme3.network.serializing.Serializable',
// 'org.ngengine.network.protocol.NetworkSafe',
'org.ngengine.components.fragments.Fragment',
'org.ngengine.components.Component',
'com.jme3.asset.cache.AssetCache',
'com.jme3.asset.AssetProcessor',
'com.jme3.post.Filter',
'com.jme3.util.BufferAllocator',
'com.jme3.asset.AssetLocator',
'com.jme3.anim.util.JointModelTransform',
'com.jme3.material.logic.TechniqueDefLogic',
'com.jme3.material.Technique',
'com.jme3.material.TechniqueDef',
'com.jme3.util.clone.JmeCloneable',
'com.jme3.system.JmeSystem',
'com.jme3.system.JmeSystemDelegate',
'com.jme3.util.SafeArrayList',
'com.jme3.plugins.json.JsonParser',
'java.lang.Cloneable',
'com.jme3.asset.CloneableSmartAsset',
'com.jme3.post.SceneProcessor',
'com.jme3.util.res.ResourceLoader',
'org.ngengine.nostr4j.listeners.NostrRelayComponent',
'org.ngengine.auth.Auth',
'org.ngengine.gui.win.NWindow',
'org.ngengine.auth.AuthStrategy',
'org.ngengine.auth.AuthConfig',
'com.simsilica.lemur.core.GuiComponent',
'com.simsilica.lemur.Panel',
'com.simsilica.lemur.style.Styles',
'com.simsilica.lemur.style.StyleTree',
// 'com.simsilica.lemur.style.StyleDefaults',
// 'com.simsilica.lemur.style.StyleAttribute',
'com.simsilica.lemur.style.Selector',
'com.simsilica.lemur.style.ElementId',
'com.simsilica.lemur.style.Attributes',
]
dynamicAdditionalClasses = [
]
dynamicScanSubclasses = true
dynamicExcludePatterns = [
'org\\.teavm\\..*',
'java\\.lang\\..*',
'org\\.joda\\.time\\..*',
'java\\..*',
'javax\\..*',
'kotlin\\..*',
'com\\.google\\.gson\\..*',
'org\\.threeten\\..*',
'org\\.apache\\..*',
'com\\.simsilica\\.lemur\\.ColorChooser.*',
'org\\.slf4j\\..*'
]
dynamicClassesFound = new TreeSet<String>()
dynamicReflectionClasses = new TreeSet<String>()
}
ext.scanClasspathForClasses = { project ->
// Create a collection to hold all classpath entries
Set<File> classpath = new LinkedHashSet<>()
// Add project's compiled classes
if (project.sourceSets.findByName('main')) {
classpath.addAll(project.sourceSets.main.output.classesDirs.files)
classpath.addAll(project.sourceSets.main.output.resourcesDir)
}
// Add runtime dependencies
if (project.configurations.findByName('runtimeClasspath')) {
classpath.addAll(project.configurations.runtimeClasspath.files)
}
// Add compile dependencies (some may not be in runtime)
if (project.configurations.findByName('compileClasspath')) {
classpath.addAll(project.configurations.compileClasspath.files)
}
// Keep only existing dirs/jars
classpath = classpath.findAll {
it.exists() && (it.isDirectory() || it.name.endsWith('.jar'))
} as LinkedHashSet<File>
println "Scanning ${classpath.size()} classpath entries"
// Build a single loader for EVERYTHING
URL[] urls = classpath.collect { it.toURI().toURL() } as URL[]
ClassLoader scanLoader = new URLClassLoader(urls, this.class.classLoader)
// println "Target types: ${project.ext.dynamicTargetTypes}"
// Reset results
project.ext.dynamicClassesFound.clear()
project.ext.dynamicReflectionClasses.clear()
// Check target types loadable with the same loader
project.ext.dynamicTargetTypes.each { targetType ->
try {
Class.forName(targetType, false, scanLoader)
// println "✓ Target type $targetType is loadable"
} catch (Throwable t) {
println "✗ Target type $targetType is not loadable: ${t.class.simpleName}: ${t.message}"
}
}
// Seed manual classes
project.ext.dynamicAdditionalClasses.each { cn ->
project.ext.dynamicClassesFound.add(cn)
project.ext.dynamicReflectionClasses.add(cn)
}
int totalProcessed = 0
int totalMatched = 0
classpath.each { file ->
if (file.isDirectory()) {
def r = scanDirectory(file, file, project.ext.dynamicTargetTypes,
project.ext.dynamicClassesFound, project.ext.dynamicReflectionClasses,
project.ext.dynamicScanSubclasses, project.ext.dynamicExcludePatterns,
scanLoader)
totalProcessed += r.processed; totalMatched += r.matched
} else {
def r = scanJar(file, project.ext.dynamicTargetTypes,
project.ext.dynamicClassesFound, project.ext.dynamicReflectionClasses,
project.ext.dynamicScanSubclasses, project.ext.dynamicExcludePatterns,
scanLoader)
totalProcessed += r.processed; totalMatched += r.matched
}
}
println "Processed ${totalProcessed} classes total"
println "Matched ${totalMatched} classes"
println "Found ${project.ext.dynamicClassesFound.size()} dynamic classes"
[classes: project.ext.dynamicClassesFound, reflectionClasses: project.ext.dynamicReflectionClasses]
}
def scanDirectory(baseDir, dir, targetTypes, classesFound, reflectionClasses, scanSubclasses, excludePatterns, ClassLoader scanLoader) {
int processed = 0, matched = 0
dir.eachFileRecurse { file ->
if (file.isFile() && file.name.endsWith('.class')) {
def rel = baseDir.toPath().relativize(file.toPath()).toString()
def className = rel.substring(0, rel.length() - 6).replace(File.separator, '.')
processed++
if (!className.contains('$') && className != 'module-info' && className != 'package-info' && !isExcluded(className, excludePatterns)) {
try {
Class<?> clazz = Class.forName(className, false, scanLoader)
if (isCompatibleType(clazz, targetTypes, scanSubclasses, scanLoader)) {
classesFound.add(className)
reflectionClasses.add(className)
matched++
}
} catch (Throwable ignored) {}
}
}
}
[processed: processed, matched: matched]
}
def scanJar(jarFile, targetTypes, classesFound, reflectionClasses, scanSubclasses, excludePatterns, ClassLoader scanLoader) {
int processed = 0, matched = 0
try {
new java.util.jar.JarFile(jarFile).withCloseable { jar ->
jar.entries().findAll { !it.isDirectory() && it.name.endsWith('.class') }.each { e ->
def className = e.name.substring(0, e.name.length() - 6).replace('/', '.')
processed++
if (!className.contains('$') && className != 'module-info' && className != 'package-info' && !isExcluded(className, excludePatterns)) {
try {
Class<?> clazz = Class.forName(className, false, scanLoader)
if (isCompatibleType(clazz, targetTypes, scanSubclasses, scanLoader)) {
classesFound.add(className)
reflectionClasses.add(className)
matched++
}
} catch (Throwable ignored) {}
}
}
}
} catch (Throwable t) {
println "Error scanning JAR ${jarFile.name}: ${t.message}"
}
[processed: processed, matched: matched]
}
def isCompatibleType(Class<?> clazz, Collection<String> targetTypes, boolean scanSubclasses, ClassLoader scanLoader) {
if (clazz == null) return false
// Assignable to any target class/interface
for (def targetType : targetTypes) {
try {
Class<?> targetClass = Class.forName(targetType, false, scanLoader)
if (targetClass.isAssignableFrom(clazz)) return true
} catch (Throwable ignored) {}
}
// Traverse interfaces
for (def iface : clazz.interfaces) {
if (targetTypes.contains(iface.name) || (scanSubclasses && isCompatibleType(iface, targetTypes, scanSubclasses, scanLoader))) {
return true
}
}
// Traverse superclass
scanSubclasses && isCompatibleType(clazz.superclass, targetTypes, scanSubclasses, scanLoader)
}
// Helper to check if a class should be excluded
def isExcluded(String className, Collection<String> excludePatterns) {
for (def pattern : excludePatterns) {
if (className.matches(pattern)) {
return true
}
}
return false
}

15
gradle/libs/props.gradle Normal file
View File

@@ -0,0 +1,15 @@
import groovy.json.JsonSlurper
gradle.ext.loadNgeAppProperties = { path ->
def ngeappFile = file(path)
if (ngeappFile.exists()) {
def jsonSlurper = new JsonSlurper()
def fileContent = ngeappFile.text.replaceAll(/\/\/.*?$/, '').trim()
def ngeappConfig = jsonSlurper.parseText(fileContent)
return ngeappConfig
} else {
logger.warn(path+" file not found")
return [:]
}
}

BIN
icon.icns

Binary file not shown.

View File

@@ -1,8 +1 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Mon Sep 01 09:13:24 CEST 2025
sdk.dir=/home/riccardobl/Android/Sdk

View File

@@ -2,19 +2,31 @@ plugins {
id 'com.android.application'
}
def localPropsFile = file("${rootDir}/local.properties")
if (!localPropsFile.exists()) {
def userHome = System.getProperty('user.home')
localPropsFile.text = "sdk.dir=${userHome}/Android/Sdk"
println "Created local.properties with sdk.dir=${userHome}/Android/Sdk"
}
android {
compileSdk 36
namespace "${project.applicationId}"
namespace "${project.Namespace}"
defaultConfig {
applicationId "${project.applicationId}"
applicationId "${project.Namespace}"
minSdk 33
targetSdk 33
versionCode project.versionCode.toInteger()
versionName project.version
versionCode project.VersionCode.toInteger()
versionName project.Version
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [
appLabel : (project.findProperty('Title') ?: "NGE Unnamed App"),
screenOrientation: (project.findProperty('ScreenOrientation') ?: "landscape")
]
}
packagingOptions {
jniLibs {
useLegacyPackaging = true
@@ -27,14 +39,17 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
buildFeatures {
viewBinding true
}
}
@@ -52,7 +67,19 @@ dependencies {
implementation project(':app')
implementation "org.ngengine:nge-platform-android:${ngePlatformVersion}"
implementation "org.ngengine:nge-app:${ngeVersion}"
implementation "org.ngengine:jme3-android:${ngeVersion}"
implementation "org.ngengine:jme3-android-native:${ngeVersion}"
implementation "org.ngengine:nge-android:${ngeVersion}"
}
apply from: "${rootDir}/gradle/libs/android-icon-gen.gradle"
task generateAndroidLauncherIcons (){
doLast {
gradle.ext.generateAndroidIcons("${rootDir}/icon.png", "${projectDir}/src/main/res")
}
}
android.applicationVariants.all { variant ->
variant.mergeResourcesProvider.configure { dependsOn(generateAndroidLauncherIcons) }
}

View File

@@ -5,7 +5,7 @@
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="Nostr Game Engine App"
android:label="${appLabel}"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:largeHeap="true"
@@ -13,8 +13,9 @@
<activity
android:name="org.ngengine.platform.AndroidLauncherActivity"
android:exported="true"
android:screenOrientation="landscape"
android:theme="@style/Theme.AppCompat.NoActionBar">
android:screenOrientation="${screenOrientation}"
android:theme="@style/Theme.AppCompat.NoActionBar"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -13,22 +13,22 @@ import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import org.ngengine.app.Main;
import org.ngengine.platform.android.AndroidThreadedPlatform;
import org.ngengine.demo.AdcDemo.R;
public class AndroidLauncherActivity extends AppCompatActivity {
private AndroidLauncherFragment launcherFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_launcher);
int layoutId = getResources().getIdentifier("activity_android_launcher", "layout", getPackageName());
setContentView(layoutId);
launcherFragment = new AndroidLauncherFragment();
int containerId = getResources().getIdentifier("fragment_container", "id", getPackageName());
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, launcherFragment)
.add(containerId, new AndroidLauncherFragment(Main::main, AndroidThreadedPlatform::new))
.commit();
}

View File

@@ -1,308 +0,0 @@
package org.ngengine.platform;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.jme3.audio.AudioRenderer;
import com.jme3.input.JoyInput;
import com.jme3.input.android.AndroidSensorJoyInput;
import com.jme3.system.AppSettings;
import com.jme3.system.SystemListener;
import com.jme3.system.android.JmeAndroidSystem;
import com.jme3.system.android.OGLESContext;
import com.jme3.util.AndroidLogHandler;
import com.jme3.util.AndroidNativeBufferAllocator;
import com.jme3.util.BufferAllocatorFactory;
import android.app.AlertDialog;
import org.ngengine.NGEApplication.NGEAppRunner;
import org.ngengine.NGEApplication;
import org.ngengine.app.Main;
import org.ngengine.platform.android.AndroidThreadedPlatform;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class AndroidLauncherFragment extends Fragment implements
SystemListener {
private static final Logger logger = Logger.getLogger(AndroidLauncherFragment.class.getName());
protected GLSurfaceView view = null;
private NGEApplication app = null;
private boolean finishOnAppStop = true;
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
public void setCloseActivityOnAppStop(boolean close){
this.finishOnAppStop = close;
}
/**
* onCreate is called once for this Fragment instance.
* Note: AppSettings configuration has been removed. Configure settings in your app.
*/
@Override
@SuppressWarnings("unchecked")
public void onCreate(Bundle savedInstanceState) {
initializeLogHandler();
logger.fine("onCreate");
super.onCreate(savedInstanceState);
System.setProperty( BufferAllocatorFactory.PROPERTY_BUFFER_ALLOCATOR_IMPLEMENTATION, AndroidNativeBufferAllocator.class.getName());
NGEPlatform.set(new AndroidThreadedPlatform(this.getContext()));
NGEAppRunner runner = Main.main(new String[0]);
app = runner.app();
AppSettings settings = app.getSettings();
settings.setAudioRenderer(AppSettings.ANDROID_OPENAL_SOFT);
app.start();
OGLESContext ctx = (OGLESContext) app.getJme3App().getContext();
ctx.setSystemListener(this);
}
/**
* Create the GLSurfaceView and return it as the Fragment's view.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
logger.fine("onCreateView");
view = ((OGLESContext) app.getJme3App().getContext()).createView(requireActivity());
JmeAndroidSystem.setView(view);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
logger.fine("onActivityCreated");
super.onActivityCreated(savedInstanceState);
}
@Override
public void onStart() {
logger.fine("onStart");
super.onStart();
}
/**
* When the Fragment resumes, call gainFocus() in the jME application.
*/
@Override
public void onResume() {
logger.fine("onResume");
super.onResume();
gainFocus();
}
/**
* When the Fragment pauses, call loseFocus() in the jME application.
*/
@Override
public void onPause() {
logger.fine("onPause");
loseFocus();
super.onPause();
}
@Override
public void onStop() {
logger.fine("onStop");
super.onStop();
}
/**
* Clear references to the GLSurfaceView.
*/
@Override
public void onDestroyView() {
logger.fine("onDestroyView");
if (view != null) {
if (view.getParent() instanceof ViewGroup) {
((ViewGroup) view.getParent()).removeView(view);
}
}
view = null;
JmeAndroidSystem.setView(null);
super.onDestroyView();
}
/**
* Called by the system when the application is being destroyed.
*/
@Override
public void onDestroy() {
logger.fine("onDestroy");
if (app != null) {
app.stop();
}
app = null;
super.onDestroy();
}
/**
* Called when an error has occurred. Shows an error message and logs the exception.
*/
@Override
public void handleError(final String errorMsg, final Throwable t) {
String stackTrace = "";
String title = "Error";
if (t != null) {
// Convert exception to string
StringWriter sw = new StringWriter(100);
t.printStackTrace(new PrintWriter(sw));
stackTrace = sw.toString();
title = t.toString();
}
final String finalTitle = title;
final String finalMsg = (errorMsg != null ? errorMsg : "Uncaught Exception")
+ "\n" + stackTrace;
logger.log(Level.SEVERE, finalMsg);
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setTitle(finalTitle);
builder.setMessage(finalMsg);
AlertDialog dialog = builder.create();
dialog.show();
}
});
}
/**
* Removes the standard Android log handler due to an issue with not logging
* entries lower than INFO level and adds a handler that produces
* JME formatted log messages.
*/
protected void initializeLogHandler() {
Logger log = LogManager.getLogManager().getLogger("");
for (Handler handler : log.getHandlers()) {
if (log.getLevel() != null && log.getLevel().intValue() <= Level.FINE.intValue()) {
Log.v("AndroidHarness", "Removing Handler class: " + handler.getClass().getName());
}
log.removeHandler(handler);
}
Handler handler = new AndroidLogHandler();
log.addHandler(handler);
handler.setLevel(Level.ALL);
}
@Override
public void initialize() {
app.getJme3App().initialize();
}
@Override
public void reshape(int width, int height) {
app.getJme3App().reshape(width, height);
}
@Override
public void rescale(float x, float y) {
app.getJme3App().rescale(x, y);
}
@Override
public void update() {
app.getJme3App().update();
}
@Override
public void requestClose(boolean esc) {
app.getJme3App().requestClose(esc);
}
@Override
public void destroy() {
if (app != null) {
app.getJme3App().destroy();
}
if (finishOnAppStop) {
requireActivity().finish();
}
}
@Override
public void gainFocus() {
logger.fine("gainFocus");
if (view != null) {
view.onResume();
}
if (app != null) {
// resume the audio
AudioRenderer audioRenderer = app.getJme3App().getAudioRenderer();
if (audioRenderer != null) {
audioRenderer.resumeAll();
}
// resume the sensors (aka joysticks)
if (app.getJme3App().getContext() != null) {
JoyInput joyInput = app.getJme3App().getContext().getJoyInput();
if (joyInput instanceof AndroidSensorJoyInput) {
((AndroidSensorJoyInput) joyInput).resumeSensors();
}
}
app.getJme3App().gainFocus();
}
}
@Override
public void loseFocus() {
logger.fine("loseFocus");
if (app != null) {
app.getJme3App().loseFocus();
}
if (view != null) {
view.onPause();
}
if (app != null) {
// pause the audio
AudioRenderer audioRenderer = app.getJme3App().getAudioRenderer();
if (audioRenderer != null) {
audioRenderer.pauseAll();
}
// pause the sensors (aka joysticks)
if (app.getJme3App().getContext() != null) {
JoyInput joyInput = app.getJme3App().getContext().getJoyInput();
if (joyInput instanceof AndroidSensorJoyInput) {
((AndroidSensorJoyInput) joyInput).pauseSensors();
}
}
}
}
}

View File

@@ -1,30 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="12dp"
android:insetTop="12dp"
android:insetRight="12dp"
android:insetBottom="12dp">
<bitmap
android:src="@mipmap/ic_launcher_foreground"
android:gravity="center"
android:filter="true"
android:antialias="true" />
</inset>

View File

@@ -1,170 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#0f0113ff"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -6,6 +6,12 @@ plugins {
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
dependencies {
testImplementation libs.junit
@@ -16,11 +22,17 @@ dependencies {
implementation project(':app')
}
application {
mainClass = "org.ngengine.platform.DesktopLauncher"
}
configurations {
nativeImageCompileOnly {
canBeResolved = true
}
}
run {
jvmArgs = [
"-Djava.util.logging.config.file=${rootProject.projectDir}/dev-logging.properties",
@@ -43,8 +55,6 @@ shadowJar {
}
build.dependsOn shadowJar
graalvmNative {
toolchainDetection = true
metadataRepository {
@@ -84,9 +94,9 @@ graalvmNative {
]
// Add G1 GC only if linux
if (org.gradle.internal.os.OperatingSystem.current().isLinux()) {
arguments.add('--gc=G1')
}
// if (org.gradle.internal.os.OperatingSystem.current().isLinux()) {
// arguments.add('--gc=G1')
// }
buildArgs.addAll(arguments)
sharedLibrary = false
@@ -94,11 +104,6 @@ graalvmNative {
}
}
configurations {
nativeImageCompileOnly {
canBeResolved = true
}
}
def getOsName(){
def osName = org.gradle.internal.os.OperatingSystem.current().getName().toLowerCase()
@@ -116,8 +121,6 @@ def getOsName(){
task traceNative(type: JavaExec) {
group = 'graalvm'
description = 'Trace reflection and resource usage'
mainClass = application.mainClass.get()
classpath = sourceSets.main.runtimeClasspath
jvmArgs = [
@@ -152,8 +155,6 @@ task traceNative(type: JavaExec) {
task buildNativeExecutable {
group = 'graalvm'
description = 'Build native executable for current platform'
dependsOn 'nativeCompile'
doLast {
def buildDirNative = "${project.buildDir}/native/nativeCompile"
@@ -185,84 +186,10 @@ task buildNativeExecutable {
def jpackage(installerType, distDir){
def os = org.gradle.internal.os.OperatingSystem.current()
def jarFile = shadowJar.archiveFile.get().asFile
def jarDir = jarFile.parentFile
def mainClass = application.mainClass.get()
def shadowJarFile = shadowJar.archiveFile.get().asFile
def commandLine = [
'jpackage',
'--input', jarDir.absolutePath,
'--main-jar', jarFile.name,
'--main-class', mainClass,
'--name', rootProject.name,
'--app-version', project.version,
'--type', installerType,
'--dest', distDir,
'--java-options', project.findProperty('javaOptions') ?: '',
'--copyright', project.findProperty('copyright')
]
// Optional: platform-specific flags
if (os.isWindows()) {
commandLine += ['--win-menu', '--win-shortcut']
} else if (os.isMacOsX()) {
commandLine += ['--icon', "${rootProject.projectDir}/icon.icns"]
} else if (os.isLinux()) {
commandLine += ['--icon', "${rootProject.projectDir}/icon.png"]
}
return commandLine
}
task buildInstaller(type: DefaultTask) {
group = 'distribution'
description = 'Create native installer using jpackage'
task buildPortable {
dependsOn shadowJar
def os = org.gradle.internal.os.OperatingSystem.current()
def osName = getOsName()
def osArch = System.getProperty("os.arch").toLowerCase()
def buildName = "${rootProject.name}-${project.version}-${osName}-${osArch}-SETUP";
def distDir = file("${rootProject.projectDir}/dist/${buildName}.setup")
doLast {
if (distDir.exists()) {
println "Deleting existing output directory: ${distDir}"
delete distDir
}
if(os.isWindows()){
exec {
commandLine jpackage('exe', distDir)
}
} else if(os.isMacOsX()){
exec {
commandLine jpackage('dmg', distDir)
}
} else if(os.isLinux()){
exec {
commandLine jpackage('deb', distDir)
}
exec {
commandLine jpackage('rpm', distDir)
}
}
println "Portable JAR created: ${shadowJar.destinationDirectory}/${shadowJar.archiveFileName.get()}"
}
}
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}

View File

@@ -2,10 +2,12 @@ package org.ngengine.platform;
import org.ngengine.app.Main;
import org.ngengine.platform.jvm.JVMAsyncPlatform;
import java.io.IOException;
import org.ngengine.NGEApplication.NGEAppRunner;
public class DesktopLauncher {
public static void main(String[] args) {
public static void main(String[] args) throws IOException {
NGEPlatform.set(new JVMAsyncPlatform());
NGEAppRunner runner = Main.main(args);
runner.start();

View File

@@ -57,12 +57,6 @@
{
"type": "[Lcom.simsilica.lemur.focus.FocusChangeListener;"
},
{
"type": "[Lcom.simsilica.lemur.input.AnalogFunctionListener;"
},
{
"type": "[Lcom.simsilica.lemur.input.StateFunctionListener;"
},
{
"type": "[Ljava.awt.event.MouseMotionListener;"
},
@@ -75,24 +69,6 @@
}
]
},
{
"type": "com.bulletphysics.collision.dispatch.CompoundCollisionAlgorithm",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.dispatch.ConvexConvexAlgorithm",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.dispatch.UnionFind$Element",
"methods": [
@@ -102,87 +78,6 @@
}
]
},
{
"type": "com.bulletphysics.collision.narrowphase.DiscreteCollisionDetectorInterface$ClosestPointInput",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.narrowphase.GjkEpaSolver$Face",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.narrowphase.GjkEpaSolver$He",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.narrowphase.GjkEpaSolver$Mkv",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.narrowphase.ManifoldPoint",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.narrowphase.PersistentManifold",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.collision.narrowphase.VoronoiSimplexSolver$SubSimplexClosestResult",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.dynamics.constraintsolver.SolverBody",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.bulletphysics.dynamics.constraintsolver.SolverConstraint",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.jme3.asset.CloneableAssetProcessor",
"methods": [
@@ -273,15 +168,6 @@
{
"type": "com.jme3.cursors.plugins.CursorLoader"
},
{
"type": "com.jme3.export.SavableWrapSerializable",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.jme3.export.binary.BinaryLoader"
},
@@ -294,24 +180,6 @@
}
]
},
{
"type": "com.jme3.light.PointLight",
"methods": [
{
"name": "clone",
"parameterTypes": []
}
]
},
{
"type": "com.jme3.light.SpotLight",
"methods": [
{
"name": "clone",
"parameterTypes": []
}
]
},
{
"type": "com.jme3.material.Material",
"methods": [
@@ -482,15 +350,6 @@
}
]
},
{
"type": "com.jme3.scene.plugins.gltf.LightsPunctualExtensionLoader",
"methods": [
{
"name": "<init>",
"parameterTypes": []
}
]
},
{
"type": "com.jme3.scene.plugins.gltf.UserDataLoader",
"methods": [
@@ -578,9 +437,6 @@
{
"type": "com.jme3.texture.plugins.AWTLoader"
},
{
"type": "com.jme3.texture.plugins.AWTWebpImageLoader"
},
{
"type": "com.jme3.texture.plugins.DDSLoader"
},
@@ -1230,8 +1086,7 @@
},
{
"type": "java.nio.DirectFloatBufferU",
"allDeclaredFields": true,
"unsafeAllocated": true
"allDeclaredFields": true
},
{
"type": "java.nio.DirectIntBufferU",
@@ -3152,9 +3007,6 @@
},
{
"type": "org.ngengine.nostr4j.signer.NostrNIP46Signer"
},
{
"type": "org.ngengine.store.DataStore$SerializableEntry"
}
],
"jni": [
@@ -3784,12 +3636,6 @@
{
"type": "java.lang.System",
"methods": [
{
"name": "getProperty",
"parameterTypes": [
"java.lang.String"
]
},
{
"name": "load",
"parameterTypes": [

File diff suppressed because one or more lines are too long

445
platform-web/build.gradle Normal file
View File

@@ -0,0 +1,445 @@
plugins {
id 'com.github.node-gradle.node' version '7.1.0'
id "java"
id "war"
id "org.teavm" version "${teaVmVersion}"
}
import java.security.MessageDigest
import java.nio.file.Files
import java.nio.file.Paths
apply from: "${rootDir}/gradle/libs/class-finder.gradle"
configurations {
withResources {
canBeResolved = true
}
}
node {
download = true
distBaseUrl = null
version = "22.18.0"
}
configurations.configureEach {
exclude group: 'org.ngengine', module: 'jme3-jbullet'
}
dependencies {
implementation "org.teavm:teavm-jso:${teaVmVersion}"
implementation "org.teavm:teavm-jso-apis:${teaVmVersion}"
implementation "org.teavm:teavm-metaprogramming-api:${teaVmVersion}"
implementation "org.teavm:teavm-classlib:${teaVmVersion}"
implementation "org.teavm:teavm-tooling:${teaVmVersion}"
implementation "org.teavm:teavm-core:${teaVmVersion}"
implementation "org.ngengine:nge-platform-teavm:${ngePlatformVersion}"
implementation "org.ngengine:nge-app:${ngeVersion}"
implementation "org.ngengine:jme3-plugins-json:${ngeVersion}"
implementation "org.ngengine:nge-web:${ngeVersion}"
implementation "org.ngengine:nge-web-bullet:${ngeVersion}"
implementation project(':app')
withResources project(':app')
withResources "org.ngengine:nge-platform-teavm:${ngePlatformVersion}"
withResources "org.ngengine:nge-web:${ngeVersion}"
withResources "org.ngengine:nge-web-bullet:${ngeVersion}"
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
sourceSets {
test {
resources {
srcDirs = ['src/test/resources', 'src/main/resources']
}
}
}
def binaryExclusions = [
'**/*.class',
'**/*.dll',
'**/*.so',
'**/*.dylib',
'**/package.html',
"**/*.kotlin_builtins",
"**/build.data",
"**/*.xml",
"**/test*.png",
// '**/*.java'
]
def generateHashes(File dir) {
def hashes = []
Files.walk(Paths.get(dir.toURI())).filter {
Files.isRegularFile(it)
}.forEach { file ->
def relativePath = dir.toPath().relativize(file).toString()
if(relativePath.endsWith(".class")) return;
if(relativePath.endsWith(".java")) return;
def hash = generateSHA256(file.toFile())
def size = file.toFile().length()
hashes << "$hash $size $relativePath"
}
return hashes.join('\n')
}
def generateSHA256(file) {
def messageDigest = MessageDigest.getInstance("SHA-256")
file.eachByte(4096) { bytes, len ->
messageDigest.update(bytes, 0, len)
}
return messageDigest.digest().collect { String.format("%02x", it) }.join()
}
task copyAllResources {
dependsOn configurations.runtimeClasspath.getTaskDependencyFromProjectDependency(true, 'jar')
dependsOn 'jar'
['compileTeavmJava','processTeavmResources','compileJava','processResources']
.each { tn -> if (tasks.findByName(tn) != null) dependsOn tn }
doLast {
def dest = file("${rootDir}/dist/web")
dest.mkdirs()
def safeCopy = { spec ->
copy {
into dest
from spec
exclude(*binaryExclusions)
exclude '**/module-info.class'
includeEmptyDirs = false
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}
safeCopy('src/main/resources')
def runtimeFiles = configurations.runtimeClasspath.resolvedConfiguration.lenientConfiguration.files
runtimeFiles.each { f ->
if (!f.exists()) return
if (f.isDirectory()) {
safeCopy(f)
} else if (f.name.endsWith('.jar')) {
safeCopy(project.zipTree(f))
}
}
println "Resource aggregation complete. Total files: " + fileTree(dest).matching { exclude(*binaryExclusions) }.files.size()
def manifestFile = file("${rootDir}/dist/web/manifest.json")
if (manifestFile.exists()) {
def manifest = new groovy.json.JsonSlurper().parseText(manifestFile.text)
manifest.name = Title
manifest.short_name = ShortName
manifestFile.text = groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson(manifest))
println "Updated manifest.json: name=$Title, short_name=$ShortName"
}
def outputDir = file("${rootDir}/dist/web/")
def outputFile = file("${rootDir}/dist/web/resources.index.txt")
outputFile.text = generateHashes(outputDir)
}
}
def generateClassListFile(File outputFile, Collection<String> classes, Closure<String> lineFormatter) {
outputFile.parentFile.mkdirs()
outputFile.text = classes.collect(lineFormatter).join('\n')
println "Generated class list at ${outputFile.absolutePath}"
}
def generateCodeFromTemplate(File outputFile, String template, Map<String, Object> vars) {
outputFile.parentFile.mkdirs()
String result = template
vars.each { key, value ->
result = result.replace("{{$key}}", value.toString())
}
outputFile.text = result
println "Generated code at ${outputFile.absolutePath}"
}
task scanClasspathForTeaVM {
dependsOn configurations.compileClasspath.getTaskDependencyFromProjectDependency(true, 'classes')
doLast {
def scanResults = project.scanClasspathForClasses(project)
def preserveListFile = file("${buildDir}/generated/teaReflectList.txt")
generateClassListFile(preserveListFile, scanResults.classes) { className ->
"**/${className.replace('.', '/')}.java"
}
def reflectionSupplierFile = file("${buildDir}/generated/teaReflect.java")
def template = """private static void initGenerated() {
{{classInitializers}}
}"""
generateCodeFromTemplate(reflectionSupplierFile, template, [
classInitializers: scanResults.reflectionClasses.collect {
" TeaReflectionSupplier.addReflectionClass(\"${it}\");"
}.join('\n')
])
}
}
task updateTeaReflectionSupplier {
dependsOn scanClasspathForTeaVM
doLast {
def reflectionSupplierFile = file("${buildDir}/generated/teaReflect.java")
def teaReflectionSupplierFile = file("${projectDir}/src/main/java/org/ngengine/platform/TeaReflectionSupplier.java")
if (reflectionSupplierFile.exists() && teaReflectionSupplierFile.exists()) {
def content = teaReflectionSupplierFile.text
def initGeneratedContent = reflectionSupplierFile.text
content = content.replaceAll(/(?s)private static void initGenerated\(\)\s*\{.*?\}/, initGeneratedContent)
teaReflectionSupplierFile.text = content
println "Updated TeaReflectionSupplier.java with generated initGenerated() method"
}
}
}
tasks.named('compileJava').configure {
dependsOn 'updateTeaReflectionSupplier'
}
teavm.js {
addedToWebApp = false
mainClass = "org.ngengine.platform.WebLauncher"
obfuscated = false
debugInformation = true
strict= false
outOfProcess=false
// optimization=org.teavm.gradle.api.OptimizationLevel.NONE
sourceMap=true
moduleType = org.teavm.gradle.api.JSModuleType.ES2015
def classesToPreserve=[]
def preserveListFile = file("${buildDir}/generated/teaReflectList.txt")
if (preserveListFile.exists()) {
preserveListFile.readLines().each { line ->
if (line.trim()) {
classesToPreserve.add(line.trim())
}
}
}
def fqcnToPreserve = new LinkedHashSet<String>()
def toFqcn = { File baseDir, File f ->
def rel = f.path.substring(baseDir.path.length() + 1)
rel = rel.replaceAll(/\.java$/, '').replaceAll(/\.class$/, '')
rel.replace('/', '.')
}
rootProject.allprojects.each { prj ->
def ss = prj.extensions.findByName('sourceSets')
def mainSS = ss?.findByName('main')
if (mainSS == null) return
mainSS.java.srcDirs.each { srcDir ->
if (!srcDir.exists()) return
fileTree(srcDir).matching { include classesToPreserve }.forEach { f ->
def fqcn = toFqcn(srcDir, f)
fqcnToPreserve.add(fqcn)
}
}
}
def rtArtifacts = configurations.runtimeClasspath.resolvedConfiguration.lenientConfiguration.files
rtArtifacts.each { artifact ->
if (!artifact.exists()) return
if (artifact.isDirectory()) {
fileTree(artifact).matching { include classesToPreserve.collect { it.replace('.java', '.class') } }.forEach { f ->
def fqcn = toFqcn(artifact, f)
fqcnToPreserve.add(fqcn)
}
} else if (artifact.name.endsWith('.jar')) {
def classFilePatterns = classesToPreserve.collect { it.replace('.java', '.class') }
.collect { it.replace('**/', '') }
try {
def jarFile = new java.util.jar.JarFile(artifact)
def entries = jarFile.entries()
while (entries.hasMoreElements()) {
def entry = entries.nextElement()
if (entry.isDirectory()) continue
def entryName = entry.getName()
if (classFilePatterns.any { pattern ->
entryName.endsWith(pattern) || entryName.matches(pattern.replace("*", ".*"))
}) {
def fqcn = entryName.replaceAll(/\.class$/, '').replace('/', '.')
fqcnToPreserve.add(fqcn)
}
}
jarFile.close()
} catch (Exception e) {
println "WARNING: Could not process JAR file: ${artifact.name} - ${e.message}"
}
}
}
fqcnToPreserve.each {
preservedClasses.add(it)
}
targetFileName = "webapp.js"
}
task buildWebApp {
dependsOn 'compileJava', 'generateJavaScript', 'copyAllResources'
doLast {
def jsDir = file("$buildDir/generated/teavm/js")
def distDir = file("${rootDir}/dist/web")
distDir.mkdirs()
copy {
from jsDir
into distDir
}
println "Copied web app to: $distDir"
}
}
task buildBundledWebApp {
dependsOn buildWebApp
doLast {
def jsDir = file("$rootDir/dist/web")
def bundledJsDir = file("$rootDir/dist/web-bundle")
def bundleIgnoreFile = file("$jsDir/bundle-ignore.txt")
def zipFile = file("$bundledJsDir/ngeapp-bundle.zip")
def configFile = file("$bundledJsDir/ngeapp.json")
bundledJsDir.mkdirs()
// Read ignore patterns from bundle-ignore.txt
def ignorePatterns = []
if (bundleIgnoreFile.exists()) {
bundleIgnoreFile.eachLine { line ->
if (line.trim() && !line.startsWith('//')) ignorePatterns.add(line.trim())
}
println "Found ${ignorePatterns.size()} patterns to exclude from bundle"
} else {
println "Warning: bundle-ignore.txt not found at ${bundleIgnoreFile}. No files will be excluded from the bundle."
}
// Create zip with everything except ignored files
ant.zip(destfile: zipFile) {
fileset(dir: jsDir) {
ignorePatterns.each { pattern ->
if (pattern.endsWith('/')) {
exclude(name: "${pattern}**")
} else {
exclude(name: pattern)
}
}
}
}
// Copy ignored files to bundledjs directory
if (!ignorePatterns.isEmpty()) {
println "Copying excluded files to bundled directory..."
delete fileTree(bundledJsDir).matching { include '**/*' exclude 'ngeapp-bundle.zip', 'ngeapp-config.json' }
fileTree(jsDir).visit { fileDetails ->
if (fileDetails.isDirectory()) return
def relativePath = fileDetails.relativePath.toString()
def matchesPattern = false
for (pattern in ignorePatterns) {
if (pattern.endsWith('/')) {
if (relativePath.startsWith(pattern) || relativePath.startsWith(pattern.substring(0, pattern.length() - 1))) {
matchesPattern = true
break
}
} else {
if (relativePath == pattern) {
matchesPattern = true
break
}
}
}
if (matchesPattern) {
println "Copying excluded file: $relativePath"
copy {
from fileDetails.file
into new File(bundledJsDir, fileDetails.relativePath.parent.toString())
}
}
}
println "Finished copying excluded files"
}
// Calculate hash of zip file
def hash = generateSHA256(zipFile)
// Set bundle in config file
def config = [:]
if (configFile.exists()) {
try {
config = new groovy.json.JsonSlurper().parseText(configFile.text)
println "Updating existing config file: $configFile.path"
} catch (Exception e) {
println "Warning: Could not parse existing config file: $e.message"
config = [:]
}
}
config.bundle = "ngeapp-bundle.zip"
config.bundleHash = hash
configFile.text = groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson(config))
println "Created bundle: $zipFile.path"
println "Bundle hash: $hash"
println "Config written to: $configFile.path"
}
}
task npmCi(type: NpmTask) {
workingDir = file("${projectDir}")
args = ['ci']
}
task runWebApp(type: NpxTask) {
dependsOn buildWebApp
workingDir = file("$rootDir/dist/web")
command = 'http-server'
args = [ '.', '-p', '8000']
}
task runBundledWebApp(type: NpxTask) {
dependsOn buildBundledWebApp
workingDir = file("$rootDir/dist/web-bundle")
command = 'http-server'
args = [ '.', '-p', '8000']
}
task deployWebApp(type: NpxTask) {
dependsOn buildBundledWebApp
dependsOn npmCi
command = 'nostr-deploy-cli'
args = ['deploy','--skip-setup', '-d', "${rootDir}/dist/web-bundle"]
workingDir = file("${projectDir}")
}

2033
platform-web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
{
"devDependencies": {
"nostr-deploy-cli": "^0.7.6"
}
}

View File

@@ -0,0 +1,744 @@
package org.ngengine.platform;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.teavm.classlib.ReflectionContext;
import org.teavm.classlib.ReflectionSupplier;
import org.teavm.model.ClassReader;
import org.teavm.model.FieldReader;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReader;
import org.teavm.model.ValueType;
public class TeaReflectionSupplier implements ReflectionSupplier {
private static ArrayList<Pattern> regexPatterns = new ArrayList<>();
private static ArrayList<Class<?>> clazzList = new ArrayList<>();
private static ArrayList<String> clazzNameList = new ArrayList<>();
static {
init();
}
private static void initGenerated() {
TeaReflectionSupplier.addReflectionClass("com.jcraft.jzlib.Deflate");
TeaReflectionSupplier.addReflectionClass("com.jcraft.jzlib.GZIPHeader");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.AnimClip");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.AnimComposer");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.AnimLayer");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.AnimTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.Armature");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.ArmatureMask");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.Joint");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.MatrixJointModelTransform");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.MorphControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.MorphTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.SeparateJointModelTransform");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.SingleLayerInfluenceMask");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.SkinningControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.TransformTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.tween.AbstractTween");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.tween.Tween");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.tween.action.Action");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.tween.action.BaseAction");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.tween.action.BlendAction");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.tween.action.BlendableAction");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.tween.action.ClipAction");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.util.HasLocalTransform");
TeaReflectionSupplier.addReflectionClass("com.jme3.anim.util.JointModelTransform");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.AnimControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.Animation");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.AudioTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.Bone");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.BoneTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.ClonableTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.CompactArray");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.CompactFloatArray");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.CompactQuaternionArray");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.CompactVector3Array");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.EffectTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.Pose");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.PoseTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.Skeleton");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.SkeletonControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.SpatialTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.Track");
TeaReflectionSupplier.addReflectionClass("com.jme3.animation.TrackInfo");
TeaReflectionSupplier.addReflectionClass("com.jme3.app.StatsView");
TeaReflectionSupplier.addReflectionClass("com.jme3.app.state.ScreenshotAppState");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.AssetKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.AssetLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.AssetLocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.AssetProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.CloneableAssetProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.CloneableSmartAsset");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.FilterKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.MaterialKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.ModelKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.ShaderNodeDefinitionKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.TextureKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.cache.AssetCache");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.cache.SimpleAssetCache");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.cache.WeakRefAssetCache");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.cache.WeakRefCloneAssetCache");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.plugins.ClasspathLocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.plugins.FileLocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.plugins.HttpZipLocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.plugins.UrlLocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.asset.plugins.ZipLocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.AudioBuffer");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.AudioData");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.AudioKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.AudioNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.AudioStream");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.BandPassFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.Filter");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.HighPassFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.LowPassFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.plugins.OGGLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.audio.plugins.WAVLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.bounding.BoundingBox");
TeaReflectionSupplier.addReflectionClass("com.jme3.bounding.BoundingSphere");
TeaReflectionSupplier.addReflectionClass("com.jme3.bounding.BoundingVolume");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.animation.BoneLink");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.animation.DacConfiguration");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.animation.DacLinks");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.animation.DynamicAnimControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.animation.PhysicsLink");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.animation.RangeOfMotion");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.animation.TorsoLink");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.PhysicsCollisionObject");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.BoxCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.CapsuleCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.CollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.CompoundCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.ConeCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.CylinderCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.GImpactCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.HeightfieldCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.HullCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.MeshCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.PlaneCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.SimplexCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.SphereCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.collision.shapes.infos.ChildCollisionShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.AbstractPhysicsControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.BetterCharacterControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.CharacterControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.GhostControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.KinematicRagdollControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.PhysicsControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.RigidBodyControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.control.VehicleControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.debug.AbstractPhysicsDebugControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.debug.BulletCharacterDebugControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.debug.BulletGhostObjectDebugControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.debug.BulletJointDebugControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.debug.BulletRigidBodyDebugControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.debug.BulletVehicleDebugControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.joints.ConeJoint");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.joints.HingeJoint");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.joints.PhysicsJoint");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.joints.Point2PointJoint");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.joints.SixDofJoint");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.joints.SliderJoint");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.objects.PhysicsCharacter");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.objects.PhysicsGhostObject");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.objects.PhysicsRigidBody");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.objects.PhysicsVehicle");
TeaReflectionSupplier.addReflectionClass("com.jme3.bullet.objects.VehicleWheel");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.Cinematic");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.KeyFrame");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.MotionPath");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.TimeLine");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.AbstractCinematicEvent");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.AnimEvent");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.AnimationEvent");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.AnimationTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.CameraEvent");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.CinematicEvent");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.MotionEvent");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.MotionTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.SoundEvent");
TeaReflectionSupplier.addReflectionClass("com.jme3.cinematic.events.SoundTrack");
TeaReflectionSupplier.addReflectionClass("com.jme3.collision.bih.BIHNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.collision.bih.BIHTree");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.ParticleEmitter");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.ParticleMesh");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.ParticlePointMesh");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.ParticleTriMesh");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.influencers.DefaultParticleInfluencer");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.influencers.EmptyParticleInfluencer");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.influencers.NewtonianParticleInfluencer");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.influencers.ParticleInfluencer");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.influencers.RadialParticleInfluencer");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.shapes.EmitterBoxShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.shapes.EmitterMeshConvexHullShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.shapes.EmitterMeshFaceShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.shapes.EmitterMeshVertexShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.shapes.EmitterPointShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.shapes.EmitterShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.effect.shapes.EmitterSphereShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.environment.EnvironmentProbeControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.environment.util.BoundingSphereDebug");
TeaReflectionSupplier.addReflectionClass("com.jme3.environment.util.Circle");
TeaReflectionSupplier.addReflectionClass("com.jme3.export.JmeImporter");
TeaReflectionSupplier.addReflectionClass("com.jme3.export.NullSavable");
TeaReflectionSupplier.addReflectionClass("com.jme3.export.Savable");
TeaReflectionSupplier.addReflectionClass("com.jme3.export.binary.BinaryImporter");
TeaReflectionSupplier.addReflectionClass("com.jme3.export.binary.BinaryLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.export.xml.XMLImporter");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.BitmapCharacter");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.BitmapCharacterSet");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.BitmapFont");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.BitmapText");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.BitmapTextPage");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.GlyphParser");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.Kerning");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.Rectangle");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.StringBlock");
TeaReflectionSupplier.addReflectionClass("com.jme3.font.plugins.BitmapFontLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.input.ChaseCamera");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.AmbientLight");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.DirectionalLight");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.Light");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.LightList");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.LightProbe");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.OrientedBoxProbeArea");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.PointLight");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.ProbeArea");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.SphereProbeArea");
TeaReflectionSupplier.addReflectionClass("com.jme3.light.SpotLight");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.MatParam");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.MatParamOverride");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.MatParamTexture");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.Material");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.MaterialList");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.MaterialProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.RenderState");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.ShaderGenerationInfo");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.Technique");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.TechniqueDef");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.logic.DefaultTechniqueDefLogic");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.logic.MultiPassLightingLogic");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.logic.SinglePassAndImageBasedLightingLogic");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.logic.SinglePassLightingLogic");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.logic.StaticPassLightingLogic");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.logic.TechniqueDefLogic");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.plugins.J3MLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.material.plugins.ShaderNodeDefinitionLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.ColorRGBA");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Line");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.LineSegment");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Matrix3f");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Matrix4f");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Plane");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Quaternion");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Ray");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Rectangle");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Ring");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Spline");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Transform");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Triangle");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Vector2f");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Vector3f");
TeaReflectionSupplier.addReflectionClass("com.jme3.math.Vector4f");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.AbstractMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.Message");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.message.ChannelInfoMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.message.ClientRegistrationMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.message.CompressedMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.message.DisconnectMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.message.GZIPCompressedMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.message.SerializerRegistrationsMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.message.ZIPCompressedMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.rmi.RemoteMethodCallMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.rmi.RemoteMethodReturnMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.rmi.RemoteObjectDefMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.service.rpc.msg.RpcCallMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.network.service.rpc.msg.RpcResponseMessage");
TeaReflectionSupplier.addReflectionClass("com.jme3.plugins.gson.GsonParser");
TeaReflectionSupplier.addReflectionClass("com.jme3.plugins.json.JsonParser");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.Filter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.FilterPostProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.HDRRenderer");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.PreDepthProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.SceneProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.BloomFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.CartoonEdgeFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.ColorOverlayFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.ComposeFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.ContrastAdjustmentFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.CrossHatchFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.DepthOfFieldFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.FXAAFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.FadeFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.FogFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.GammaCorrectionFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.KHRToneMapFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.LightScatteringFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.PosterizationFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.RadialBlurFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.SoftBloomFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.ToneMapFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.filters.TranslucentBucketFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.post.ssao.SSAOFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.renderer.Camera");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.AssetLinkNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.BatchNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.CameraNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.CollisionData");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.Geometry");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.GeometryGroupNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.LightNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.Mesh");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.Node");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.SimpleBatchNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.Spatial");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.UserData");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.VertexBuffer");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.control.AbstractControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.control.BillboardControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.control.CameraControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.control.Control");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.control.LightControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.control.LodControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.control.UpdateControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.Arrow");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.Grid");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.SkeletonDebugger");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.SkeletonInterBoneWire");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.SkeletonPoints");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.SkeletonWire");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.WireBox");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.WireFrustum");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.WireSphere");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.custom.ArmatureDebugger");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.custom.ArmatureInterJointsWire");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.custom.ArmatureNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.debug.custom.JointShape");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.instancing.InstancedGeometry");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.instancing.InstancedNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.mesh.MorphTarget");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.IrBoneWeightIndex");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.IrVertex");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.MTLLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.OBJLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.fbx.ContentTextureKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.fbx.ContentTextureLocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.fbx.FbxLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.fbx.SceneKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.fbx.SceneLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.fbx.SceneWithAnimationLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.gltf.BinDataKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.gltf.BinLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.gltf.GlbLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.gltf.GltfLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.gltf.GltfModelKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.ogre.MaterialLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.ogre.MeshLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.ogre.OgreMeshKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.ogre.SceneLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.ogre.SceneMeshLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.ogre.SkeletonLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.plugins.ogre.matext.OgreMaterialKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.AbstractBox");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Box");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.CenterQuad");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Curve");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Cylinder");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Dome");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Line");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.PQTorus");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Quad");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.RectangleMesh");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Sphere");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.StripBox");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Surface");
TeaReflectionSupplier.addReflectionClass("com.jme3.scene.shape.Torus");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.Shader");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.ShaderNode");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.ShaderNodeDefinition");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.ShaderNodeVariable");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.VariableMapping");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.bufferobject.BufferObject");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.bufferobject.BufferRegion");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.plugins.GLSLLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.shader.plugins.ShaderAssetKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.AbstractShadowFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.AbstractShadowRenderer");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.BasicShadowRenderer");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.DirectionalLightShadowFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.DirectionalLightShadowRenderer");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.PointLightShadowFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.PointLightShadowRenderer");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.PssmShadowFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.PssmShadowRenderer");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.SpotLightShadowFilter");
TeaReflectionSupplier.addReflectionClass("com.jme3.shadow.SpotLightShadowRenderer");
TeaReflectionSupplier.addReflectionClass("com.jme3.system.AppSettings");
TeaReflectionSupplier.addReflectionClass("com.jme3.system.JmeSystem");
TeaReflectionSupplier.addReflectionClass("com.jme3.system.JmeSystemDelegate");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.GeoMap");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.LODGeomap");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.MultiTerrainLodControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.NormalRecalcControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.TerrainGrid");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.TerrainGridLodControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.TerrainGridTileLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.TerrainLodControl");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.TerrainPatch");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.TerrainQuad");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.grid.AssetTileLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.grid.FractalTileLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.grid.ImageTileLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.lodcalc.LodCalculator");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.lodcalc.LodThreshold");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.lodcalc.PerspectiveLodCalculator");
TeaReflectionSupplier.addReflectionClass("com.jme3.terrain.geomipmap.lodcalc.SimpleLodThreshold");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.FrameBuffer");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.Image");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.Texture");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.Texture2D");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.Texture3D");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.TextureArray");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.TextureCubeMap");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.TextureProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.plugins.DDSLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.plugins.PFMLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.plugins.SVGTextureKey");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.plugins.TGALoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.texture.plugins.ktx.KTXLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.ui.Picture");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.BufferAllocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.IntMap");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.ListMap");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.NativeObject");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.PrimitiveAllocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.ReflectionAllocator");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.SafeArrayList");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.clone.JmeCloneable");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.res.DefaultResourceLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.res.ResourceLoader");
TeaReflectionSupplier.addReflectionClass("com.jme3.util.struct.StructStd140BufferObject");
TeaReflectionSupplier.addReflectionClass("com.jme3.water.ReflectionProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.water.SimpleWaterProcessor");
TeaReflectionSupplier.addReflectionClass("com.jme3.water.WaterFilter");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.ActionButton");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Button");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Checkbox");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Container");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.GridPanel");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Insets3f");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Label");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.ListBox");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.OptionPanel");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Panel");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.PasswordField");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.ProgressBar");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.RollupPanel");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Selector");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Slider");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.Spinner");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.TabbedPanel");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.TextField");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.AbstractGuiComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.BorderLayout");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.BoxLayout");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.DynamicInsetsComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.IconComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.InsetsComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.QuadBackgroundComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.SpringGridLayout");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.TbtQuadBackgroundComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.Text2d");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.TextComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.component.TextEntryComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.AbstractNodeControl");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.CommandMap");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.GuiComponent");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.GuiControl");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.GuiLayout");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.GuiMaterial");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.LightingMaterialAdapter");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.core.UnshadedMaterialAdapter");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.dnd.DragAndDropControl");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.effect.EffectControl");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.event.CursorEventControl");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.event.MouseEventControl");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.focus.DefaultFocusTraversalControl");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.geom.DMesh");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.geom.MBox");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.geom.TbtQuad");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.list.DefaultCellRenderer");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.style.Attributes");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.style.ContainsSelector");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.style.ElementId");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.style.ElementSelector");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.style.Selector");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.style.StyleTree");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.style.Styles");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.text.DefaultDocumentModel");
TeaReflectionSupplier.addReflectionClass("com.simsilica.lemur.value.DefaultValueRenderer");
TeaReflectionSupplier.addReflectionClass("de.jarnbjo.vorbis.Floor1");
TeaReflectionSupplier.addReflectionClass("org.ngengine.ads.ImmersiveAdComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.ads.ImmersiveAdControl");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.Auth");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.AuthConfig");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.AuthSelectionWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.AuthStrategy");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.Nip46AuthStrategy");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.nip07.Nip07Auth");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.nip07.Nip07AuthWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.nip46.Nip46Auth");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.nip46.Nip46AuthWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.nip46.Nip46ChallengeWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.nsec.NsecAuth");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.nsec.NsecAuthWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.auth.stored.StoredAuthSelectionWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.Component");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.StallingComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.AppFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.AssetLoadingFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.AsyncAssetLoadingFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.Fragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.GuiViewPortFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.InputHandlerFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.LogicFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.MainViewPortFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.components.fragments.RenderFragment");
TeaReflectionSupplier.addReflectionClass("org.ngengine.demo.adc.CharacterComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.demo.adc.HudComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.demo.adc.LoadingScreenComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.demo.adc.MapComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.demo.adc.PhysicsComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.demo.adc.PostprocessingComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.demo.adc.SoundComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.CollectionSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.MapSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.Nip46MetadataSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.Nip46SignerSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.NostrEventSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.NostrKeyPairSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.NostrPrivateKeySavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.NostrPublicKeySavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.NostrRelayInfoSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.NumberSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.SavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.export.StringSavableWrapper");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NAspectPreservingQuadBackground");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NButton");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NIconButton");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NLabel");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NLoadingSpinner");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NQrViewer");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NSVGIcon");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NTextInput");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.NVSpacer");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.containers.NColumn");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.containers.NContainer");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.containers.NMultiPageList");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.containers.NPanel");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.components.containers.NRow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.qr.BitBuffer");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.win.NToast");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.win.NWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.win.NWindowManagerComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.win.std.NConfirmDialogWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.win.std.NErrorWindow");
TeaReflectionSupplier.addReflectionClass("org.ngengine.gui.win.std.NHud");
TeaReflectionSupplier.addReflectionClass("org.ngengine.lnurl.LnUrlPayerData");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.Lobby");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.LocalLobby");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.protocol.messages.BinaryMessage");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.protocol.messages.ByteDataMessage");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.protocol.messages.ClassRegistrationAckMessage");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.protocol.messages.CompressedMessage");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.protocol.messages.TextDataMessage");
TeaReflectionSupplier.addReflectionClass("org.ngengine.network.protocol.messages.TextMessage");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.NostrFilter");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.NostrRelayInfo");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.NostrRelayLifecycleManager");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.NostrRelaySubManager");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.event.NostrEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.event.SignedNostrEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.event.UnsignedNostrEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.keypair.NostrKey");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.keypair.NostrKeyPair");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.keypair.NostrPrivateKey");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.keypair.NostrPublicKey");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.listeners.NostrRelayComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.nip01.Nip01UserMetadataFilter");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.nip05.Nip05Nip46Data");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.nip46.BunkerUrl");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.nip46.Nip46AppMetadata");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.nip46.NostrconnectUrl");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.nip50.NostrSearchFilter");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.rtc.turn.NostrTURNSettings");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.signer.NostrKeyPairSigner");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.signer.NostrNIP07Signer");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.signer.NostrNIP46Signer");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostr4j.signer.NostrSigner");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.AdBidEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.AdBidFilter");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.AdEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.negotiation.AdAcceptOfferEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.negotiation.AdBailEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.negotiation.AdNegotiationEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.negotiation.AdOfferEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.negotiation.AdPaymentRequestEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.negotiation.AdPayoutEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.nostrads.protocol.negotiation.AdPowNegotiationEvent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.platform.RTCSettings");
TeaReflectionSupplier.addReflectionClass("org.ngengine.player.PlayerManagerComponent");
TeaReflectionSupplier.addReflectionClass("org.ngengine.web.context.HeapAllocator");
TeaReflectionSupplier.addReflectionClass("org.ngengine.web.context.WebSystem");
TeaReflectionSupplier.addReflectionClass("org.ngengine.web.filesystem.WebImageLoader");
TeaReflectionSupplier.addReflectionClass("org.ngengine.web.filesystem.WebLocator");
TeaReflectionSupplier.addReflectionClass("org.ngengine.web.filesystem.WebResourceLoader");
TeaReflectionSupplier.addReflectionClass("org.ngengine.web.json.TeaJSONParser");
}
private static void init() {
initGenerated();
}
public static void addReflectionClass(Class<?> c) {
clazzList.add(c);
}
public static void addReflectionClass(String className) {
clazzNameList.add(className);
}
public static void addRegex(String regex) {
regexPatterns.add(Pattern.compile(regex));
}
public TeaReflectionSupplier() {
System.out.println("TeaReflectionSupplier initialized");
}
@Override
public Collection<String> getAccessibleFields(ReflectionContext context, String className) {
Set<String> fields = new HashSet<>();
ClassReader cls = context.getClassSource().get(className);
if (cls == null) {
return Collections.emptyList();
}
try {
Class<?> clazz = context.getClassLoader().loadClass(className);
if (cls != null) {
if (canHaveReflection(clazz)) {
for (FieldReader field : cls.getFields()) {
String name = field.getName();
fields.add(name);
}
}
}
} catch (ClassNotFoundException e) {
new RuntimeException(e);
}
return fields;
}
private boolean isWhitelistedType(ReflectionContext context, ValueType t) throws ClassNotFoundException{
boolean canHaveReflection = false;
if (t instanceof ValueType.Void) {
return true;
}
if (t instanceof ValueType.Array) {
ValueType.Array a = (ValueType.Array) t;
t = a.getItemType();
}
if (t instanceof ValueType.Object) {
ValueType.Object obj = (ValueType.Object) t;
if(obj.getClassName().startsWith("java.lang")) {
canHaveReflection = true;
} else {
Class<?> sc = context.getClassLoader().loadClass(obj.getClassName());
canHaveReflection = canHaveReflection(sc);
}
} else if (t instanceof ValueType.Primitive) {
canHaveReflection = true;
}
return canHaveReflection;
}
@Override
public Collection<MethodDescriptor> getAccessibleMethods(ReflectionContext context, String className) {
Set<MethodDescriptor> methods = new HashSet<>();
ClassReader cls = context.getClassSource().get(className);
if (cls == null) {
return Collections.emptyList();
}
try {
Class<?> clazz = context.getClassLoader().loadClass(className);
if (canHaveReflection(clazz)) {
Collection<? extends MethodReader> methods2 = cls.getMethods();
int constructors = 0;
for (MethodReader method : methods2) {
boolean isConstructor = method.getName().equals("<init>");
if(isConstructor) {
constructors++;
}
boolean canHaveReflection = true;
if (canHaveReflection && !isConstructor) {
ValueType t = method.getResultType();
canHaveReflection = isWhitelistedType(context, t);
}
if (!canHaveReflection) {
continue;
}
MethodDescriptor descriptor = method.getDescriptor();
methods.add(descriptor);
}
}
} catch (ClassNotFoundException e) {
new RuntimeException(e);
}
return methods;
}
private boolean canHaveReflection(Class<?> clazz) {
for (Class<?> c : clazzList) {
if (c.isAssignableFrom(clazz) || c.equals(clazz)) {
return true;
}
}
String className = clazz.getName();
for(String cn : clazzNameList) {
if(cn.equals(className)) {
return true;
}
}
for (Pattern pattern : regexPatterns) {
if (pattern.matcher(className).matches()) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,21 @@
package org.ngengine.platform;
import org.ngengine.NGEApplication.NGEAppRunner;
import org.ngengine.app.Main;
import org.ngengine.platform.teavm.TeaVMPlatform;
import org.ngengine.web.context.WebSystem;
import com.jme3.system.JmeSystem;
public class WebLauncher {
public static void main(String[] args) {
new Thread(()->{ // must be a thread to run in a suspendable context in teavm
NGEPlatform.set(new TeaVMPlatform());
JmeSystem.setSystemDelegate(new WebSystem());
NGEAppRunner runner = Main.main(args);
runner.start();
}).start();
}
}

View File

@@ -0,0 +1 @@
org.ngengine.platform.TeaReflectionSupplier

View File

@@ -0,0 +1,13 @@
{
"name": "Nostr Game Engine Web App",
"short_name": "ngewebapp",
"start_url": "index.html",
"display": "standalone",
"icons": [{
"src": "logo.webp",
"sizes": "4096x4096",
"type": "image/webp"
}],
"background_color": "#08020c",
"theme_color": "#08020c"
}

View File

@@ -0,0 +1,11 @@
# Global logging level - set to a higher threshold
.level = INFO
# Handler (console or file)
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Set FINEST logging only for org.ngengine.nostr4j and its children
org.ngengine.nostr4j.level = INFO
org.ngengine.level = INFO

View File

@@ -5,9 +5,11 @@ pluginManagement {
google()
mavenCentral()
gradlePluginPortal()
maven { url = uri("https://teavm.org/maven/repository") }
mavenLocal()
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
id("com.android.application") version '8.12.2' apply false
id("com.android.library") version '8.12.2' apply false
id("org.jetbrains.kotlin.android") version "2.1.20" apply false
@@ -16,8 +18,19 @@ pluginManagement {
plugins {
id("org.gradle.toolchains.foojay-resolver") version "1.0.0"
}
toolchainManagement {
jvm {
javaRepositories {
repository("foojay") {
resolverClass = org.gradle.toolchains.foojay.FoojayToolchainResolver
}
}
}
}
dependencyResolutionManagement {
repositories {
@@ -27,18 +40,58 @@ dependencyResolutionManagement {
maven {
url = uri("https://central.sonatype.com/repository/maven-snapshots")
}
maven { url = uri("https://teavm.org/maven/repository") }
ivy {
name = "Node.js"
setUrl("https://nodejs.org/dist/")
patternLayout {
artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
}
metadataSources {
artifact()
}
content {
includeModule("org.nodejs", "node")
}
}
}
}
rootProject.name = settings.projectName
include('app')
if(withDesktopPlatform) {
include('platform-desktop')
if (!gradle.hasProperty('ext')) {
gradle.ext {}
}
// if (withAndroidPlatform) {
// include('platform-android')
// }
gradle.beforeProject { p ->
if (p == p.rootProject) {
p.tasks.register("cleanDist", org.gradle.api.tasks.Delete) {
delete p.layout.projectDirectory.dir("dist")
}
p.gradle.projectsEvaluated {
def cleanTask = p.tasks.findByName("clean") ?: p.tasks.register("clean")
cleanTask.configure { dependsOn("cleanDist") }
}
}
}
// import json properties
apply from: "${rootDir}/gradle/libs/props.gradle"
def ngeConfig = gradle.ext.loadNgeAppProperties("${rootDir}/app/src/main/resources/ngeapp.json")
gradle.beforeProject { p ->
ngeConfig.each { k, v -> p.ext.set(k, v) }
if (ngeConfig.Version) p.version = ngeConfig.Version.toString()
if (ngeConfig.Namespace) p.group = ngeConfig.Namespace.toString()
}
print("Build with config: "+ngeConfig)
rootProject.name = ngeConfig.ShortName
include('app')
// ENABLE DESKTOP BUILD TARGET
include('platform-desktop')
// ENABLE ANDROID BUILD TARGET
include('platform-android')
// ENABLE WEB BUILD TARGET
include('platform-web')