Merge branch 'master' into add-items

This commit is contained in:
OLEGSHA 2021-12-21 17:12:45 +03:00
commit ce573b51ce
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
3 changed files with 146 additions and 131 deletions

View File

@ -3,14 +3,14 @@
*/ */
plugins { plugins {
// Apply the java-library plugin to add support for Java Library // Apply the java-library plugin to add support for Java Library
id 'java-library' id 'java-library'
/* /*
* Uncomment the following line to enable the Eclipse plugin. * Uncomment the following line to enable the Eclipse plugin.
* This is only necessary if you don't use Buildship plugin from the IDE * This is only necessary if you don't use Buildship plugin from the IDE
*/ */
//id 'eclipse' //id 'eclipse'
} }
java { java {
@ -18,8 +18,8 @@ java {
* We're Java 8 for now. * We're Java 8 for now.
* Why? As of 2020, most users have Oracle Java, which only supports Java 8. * Why? As of 2020, most users have Oracle Java, which only supports Java 8.
*/ */
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
} }
compileJava { compileJava {
@ -29,9 +29,9 @@ compileJava {
* However, on JDK 9 and later versions, '--release' option is required, * However, on JDK 9 and later versions, '--release' option is required,
* which is missing on JDK 8. * which is missing on JDK 8.
*/ */
if (JavaVersion.current() != JavaVersion.VERSION_1_8) { if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
options.compilerArgs.addAll(['--release', '8']) options.compilerArgs.addAll(['--release', '8'])
} }
} }
/* /*
@ -40,39 +40,38 @@ compileJava {
repositories { repositories {
mavenCentral() mavenCentral()
jcenter()
/*
/* * Specify Windcorp Maven repository
* Specify Windcorp Maven repository * Currently used by:
* Currently used by: * - ru.windcorp.fork.io.github.java-graphics:glm:1.0.1
* - ru.windcorp.fork.io.github.java-graphics:glm:1.0.1 */
*/ maven { url 'https://windcorp.ru/./maven' }
maven { url 'https://windcorp.ru/./maven' }
} }
dependencies { dependencies {
// Google Guava // Google Guava
// A generic utilities library // A generic utilities library
implementation 'com.google.guava:guava:30.0-jre' implementation 'com.google.guava:guava:30.0-jre'
// Trove4j // Trove4j
// Provides optimized Collections for primitive types // Provides optimized Collections for primitive types
implementation 'net.sf.trove4j:trove4j:3.0.3' implementation 'net.sf.trove4j:trove4j:3.0.3'
// java-graphics // java-graphics
// A GLM (OpenGL Mathematics) port to Java // A GLM (OpenGL Mathematics) port to Java
// Unfortunately, Maven Central Repository provides an outdated version of this library, which contains several critical bugs // Unfortunately, Maven Central Repository provides an outdated version of this library, which contains several critical bugs
implementation 'ru.windcorp.fork.io.github.java-graphics:glm:1.0.1' implementation 'ru.windcorp.fork.io.github.java-graphics:glm:1.0.1'
// Log4j // Log4j
// A logging library // A logging library
implementation 'org.apache.logging.log4j:log4j-api:2.16.0' implementation 'org.apache.logging.log4j:log4j-api:2.17.0'
implementation 'org.apache.logging.log4j:log4j-core:2.16.0' implementation 'org.apache.logging.log4j:log4j-core:2.17.0'
// JUnit // JUnit
// A unit-testing library // A unit-testing library
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
// See LWJGL dependencies below // See LWJGL dependencies below
} }
@ -99,8 +98,8 @@ switch (OperatingSystem.current()) {
case OperatingSystem.LINUX: case OperatingSystem.LINUX:
def osArch = System.getProperty("os.arch") def osArch = System.getProperty("os.arch")
project.ext.lwjglNatives = osArch.startsWith("arm") || osArch.startsWith("aarch64") project.ext.lwjglNatives = osArch.startsWith("arm") || osArch.startsWith("aarch64")
? "natives-linux-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}" ? "natives-linux-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}"
: "natives-linux" : "natives-linux"
break break
case OperatingSystem.MAC_OS: case OperatingSystem.MAC_OS:
project.ext.lwjglNatives = "natives-macos" project.ext.lwjglNatives = "natives-macos"
@ -118,12 +117,12 @@ dependencies {
implementation "org.lwjgl:lwjgl-openal" implementation "org.lwjgl:lwjgl-openal"
implementation "org.lwjgl:lwjgl-opengl" implementation "org.lwjgl:lwjgl-opengl"
implementation "org.lwjgl:lwjgl-stb" implementation "org.lwjgl:lwjgl-stb"
runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
} }
// LWJGL END // LWJGL END
@ -141,49 +140,56 @@ project.ext.platforms = new HashSet<>()
task addNativeDependencies { task addNativeDependencies {
doFirst { doFirst {
def archs = project.ext.platforms def archs = project.ext.platforms
switch (archs.size()) { switch (archs.size()) {
case 0: case 0:
println "Adding LWJGL native dependencies for local platform only:\n\t$lwjglNatives" println "Adding LWJGL native dependencies for local platform only:\n\t$lwjglNatives"
archs.add project.ext.lwjglNatives archs.add project.ext.lwjglNatives
break break
case 1: case 1:
println "Adding LWJGL native dependencies for platform\n\t" + archs.get(0) println "Adding LWJGL native dependencies for platform\n\t" + archs.get(0)
break break
default: default:
println "Adding LWJGL native dependencies for platforms:\n\t" + archs.join("\n\t") println "Adding LWJGL native dependencies for platforms:\n\t" + archs.join("\n\t")
} }
if (project.ext.lwjglNatives.isEmpty()) println "WTF" if (project.ext.lwjglNatives.isEmpty()) println "WTF"
dependencies { dependencies {
archs.each { arch -> archs.each { arch ->
runtimeOnly "org.lwjgl:lwjgl::$arch" runtimeOnly "org.lwjgl:lwjgl::$arch"
runtimeOnly "org.lwjgl:lwjgl-glfw::$arch" runtimeOnly "org.lwjgl:lwjgl-glfw::$arch"
runtimeOnly "org.lwjgl:lwjgl-openal::$arch" runtimeOnly "org.lwjgl:lwjgl-openal::$arch"
runtimeOnly "org.lwjgl:lwjgl-opengl::$arch" runtimeOnly "org.lwjgl:lwjgl-opengl::$arch"
runtimeOnly "org.lwjgl:lwjgl-stb::$arch" runtimeOnly "org.lwjgl:lwjgl-stb::$arch"
} }
} }
} }
} }
compileJava.mustRunAfter addNativeDependencies // Make sure runtimeOnly has not been resolved compileJava.mustRunAfter addNativeDependencies // Make sure runtimeOnly has not been resolved
task requestLinuxDependencies { task requestLinuxDependencies {
description 'Adds linux, linux-arm64 and linux-arm32 native libraries to built artifacts.' description 'Adds linux, linux-arm64 and linux-arm32 native libraries to built artifacts.'
doFirst { doFirst {
project.ext.platforms.addAll(['natives-linux', 'natives-linux-arm64', 'natives-linux-arm32']) project.ext.platforms.addAll([
'natives-linux',
'natives-linux-arm64',
'natives-linux-arm32'
])
} }
} }
task requestWindowsDependencies { task requestWindowsDependencies {
description 'Adds windows and windows-x86 native libraries to built artifacts.' description 'Adds windows and windows-x86 native libraries to built artifacts.'
doFirst { doFirst {
project.ext.platforms.addAll(['natives-windows', 'natives-windows-x86']) project.ext.platforms.addAll([
'natives-windows',
'natives-windows-x86'
])
} }
} }
task requestMacOSDependencies { task requestMacOSDependencies {
description 'Adds macos native libraries to built artifacts.' description 'Adds macos native libraries to built artifacts.'
doFirst { doFirst {
project.ext.platforms.addAll(['natives-macos']) project.ext.platforms.addAll(['natives-macos'])
} }
@ -192,7 +198,7 @@ task requestMacOSDependencies {
def dependencySpecificationTasks = tasks.findAll { task -> task.name.startsWith('request') && task.name.endsWith('Dependencies') } def dependencySpecificationTasks = tasks.findAll { task -> task.name.startsWith('request') && task.name.endsWith('Dependencies') }
task requestCrossPlatformDependencies { task requestCrossPlatformDependencies {
description 'Adds native libraries for all available platforms to built artifacts.' description 'Adds native libraries for all available platforms to built artifacts.'
dependsOn dependencySpecificationTasks dependsOn dependencySpecificationTasks
} }
@ -205,7 +211,7 @@ def isDependencyRequested(String dep) {
if (dep.endsWith(".jar")) { if (dep.endsWith(".jar")) {
dep = dep.substring(0, dep.length() - ".jar".length()) dep = dep.substring(0, dep.length() - ".jar".length())
} }
return !dep.contains("natives-") || return !dep.contains("natives-") ||
project.ext.platforms.contains(dep.substring(dep.indexOf("natives-"), dep.length())) project.ext.platforms.contains(dep.substring(dep.indexOf("natives-"), dep.length()))
} }
@ -219,7 +225,7 @@ task specifyLocalManifest {
doFirst { doFirst {
def classPath = [] def classPath = []
configurations.runtimeClasspath.each { configurations.runtimeClasspath.each {
if (isDependencyRequested(it.getName())) { if (isDependencyRequested(it.getName())) {
classPath.add("lib/" + it.getName()) classPath.add("lib/" + it.getName())
@ -227,18 +233,18 @@ task specifyLocalManifest {
println "\tRemoving from JAR classpath (not requested): " + it.getName() println "\tRemoving from JAR classpath (not requested): " + it.getName()
} }
} }
if (classPath.size() == configurations.runtimeClasspath.size()) { if (classPath.size() == configurations.runtimeClasspath.size()) {
println "Nothing removed from JAR classpath" println "Nothing removed from JAR classpath"
} }
jar { jar {
manifest { manifest {
attributes( attributes(
"Main-Class": "ru.windcorp.progressia.client.ProgressiaClientMain", "Main-Class": "ru.windcorp.progressia.client.ProgressiaClientMain",
"Class-Path": configurations.runtimeClasspath.collect { "lib/" + it.getName() } .findAll { isDependencyRequested(it) } .join(' ') "Class-Path": configurations.runtimeClasspath.collect { "lib/" + it.getName() } .findAll { isDependencyRequested(it) } .join(' ')
) )
} }
} }
} }
} }
@ -248,13 +254,13 @@ jar.dependsOn specifyLocalManifest
/* /*
* Library export * Library export
*/ */
task exportLibs(type: Sync) { task exportLibs(type: Sync) {
mustRunAfter addNativeDependencies mustRunAfter addNativeDependencies
into libsDirectory.get().getAsFile().getPath() + "/lib" into libsDirectory.get().getAsFile().getPath() + "/lib"
exclude { !isDependencyRequested(it.getName()) } exclude { !isDependencyRequested(it.getName()) }
from configurations.runtimeClasspath from configurations.runtimeClasspath
} }
jar.dependsOn(exportLibs) jar.dependsOn(exportLibs)
@ -264,52 +270,52 @@ jar.dependsOn(exportLibs)
*/ */
task packageDebian(type: Exec) { task packageDebian(type: Exec) {
description 'Builds the project and creates a Debain package.' description 'Builds the project and creates a Debain package.'
group 'Progressia' group 'Progressia'
dependsOn build dependsOn build
dependsOn requestLinuxDependencies dependsOn requestLinuxDependencies
commandLine './buildPackages.sh', 'debian' commandLine './buildPackages.sh', 'debian'
doLast { doLast {
println "Debian package available in build_packages/" println "Debian package available in build_packages/"
} }
} }
task packageWindows(type: Exec) { task packageWindows(type: Exec) {
description 'Builds the project and creates a Windows installer.' description 'Builds the project and creates a Windows installer.'
group 'Progressia' group 'Progressia'
dependsOn build dependsOn build
dependsOn requestWindowsDependencies dependsOn requestWindowsDependencies
commandLine './buildPackages.sh', 'windows' commandLine './buildPackages.sh', 'windows'
doLast { doLast {
println "Windows installer available in build_packages/" println "Windows installer available in build_packages/"
} }
} }
task buildCrossPlatform { task buildCrossPlatform {
description 'Builds the project including native libraries for all available platforms.' description 'Builds the project including native libraries for all available platforms.'
group 'Progressia' group 'Progressia'
dependsOn requestCrossPlatformDependencies dependsOn requestCrossPlatformDependencies
dependsOn build dependsOn build
doLast { doLast {
println "Native libraries for all platforms have been added" println "Native libraries for all platforms have been added"
} }
} }
task buildLocal { task buildLocal {
description "Builds the project including only native libraries for current platform ($lwjglNatives)." description "Builds the project including only native libraries for current platform ($lwjglNatives)."
group 'Progressia' group 'Progressia'
dependsOn build dependsOn build
doLast { doLast {
println "Native libraries only for platform $lwjglNatives have been added" println "Native libraries only for platform $lwjglNatives have been added"
} }
} }

View File

@ -563,6 +563,10 @@ public class Component extends Named {
inputBus.unregister(listener); inputBus.unregister(listener);
} }
protected boolean passInputToChildren(InputEvent e) {
return true;
}
InputBus getInputBus() { InputBus getInputBus() {
return inputBus; return inputBus;
} }

View File

@ -27,6 +27,7 @@ import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent;
import ru.windcorp.progressia.client.graphics.input.bus.InputBus; import ru.windcorp.progressia.client.graphics.input.bus.InputBus;
import ru.windcorp.progressia.common.util.LowOverheadCache;
import ru.windcorp.progressia.common.util.StashingStack; import ru.windcorp.progressia.common.util.StashingStack;
public abstract class GUILayer extends AssembledFlatLayer { public abstract class GUILayer extends AssembledFlatLayer {
@ -40,7 +41,7 @@ public abstract class GUILayer extends AssembledFlatLayer {
public GUILayer(String name, Layout layout) { public GUILayer(String name, Layout layout) {
super(name); super(name);
getRoot().setLayout(layout); getRoot().setLayout(layout);
getRoot().addInputListener(KeyEvent.class, this::attemptFocusTransfer, InputBus.Option.IGNORE_FOCUS); getRoot().addInputListener(KeyEvent.class, this::attemptFocusTransfer, InputBus.Option.IGNORE_FOCUS);
} }
@ -75,20 +76,22 @@ public abstract class GUILayer extends AssembledFlatLayer {
} }
/** /**
* Stack for {@link #handleInput(InputEvent)}. * Stacks for {@link #handleInput(InputEvent)}.
*/ */
private StashingStack<EventHandlingFrame> path = new StashingStack<>(64, EventHandlingFrame::new); private final LowOverheadCache<StashingStack<EventHandlingFrame>> pathCache = new LowOverheadCache<>(
() -> new StashingStack<>(64, EventHandlingFrame::new)
);
/* /*
* This is essentially a depth-first iteration of the component tree. The * This is essentially a depth-first iteration of the component tree. The
* recursive procedure has been unrolled to reduce call stack length. * recursive procedure has been unrolled to reduce call stack length.
*/ */
@Override @Override
public void handleInput(InputEvent event) { public void handleInput(InputEvent event) {
StashingStack<EventHandlingFrame> path = pathCache.grab();
if (!path.isEmpty()) { if (!path.isEmpty()) {
throw new IllegalStateException( throw new IllegalStateException("path is not empty: " + path);
"path is not empty: " + path + ". Are events being processed concurrently?"
);
} }
path.push().init(root); path.push().init(root);
@ -101,7 +104,7 @@ public abstract class GUILayer extends AssembledFlatLayer {
Component c = it.next(); Component c = it.next();
if (c.isEnabled()) { if (c.isEnabled()) {
if (c.getChildren().isEmpty()) { if (c.getChildren().isEmpty() || !c.passInputToChildren(event)) {
c.getInputBus().dispatch(event); c.getInputBus().dispatch(event);
} else { } else {
path.push().init(c); path.push().init(c);
@ -114,15 +117,17 @@ public abstract class GUILayer extends AssembledFlatLayer {
} }
} }
pathCache.release(path);
} }
private void attemptFocusTransfer(KeyEvent e) { private void attemptFocusTransfer(KeyEvent e) {
Component focused = getRoot().findFocused(); Component focused = getRoot().findFocused();
if (focused == null) { if (focused == null) {
return; return;
} }
if (e.getKey() == GLFW.GLFW_KEY_TAB && !e.isRelease()) { if (e.getKey() == GLFW.GLFW_KEY_TAB && !e.isRelease()) {
e.consume(); e.consume();
if (e.hasShift()) { if (e.hasShift()) {