Merge branch 'master' into Textures

This commit is contained in:
OLEGSHA 2021-01-10 23:33:22 +03:00
commit 73be13734e
18 changed files with 803 additions and 207 deletions

7
.gitignore vendored
View File

@ -16,7 +16,12 @@ bin
# Ignore MacOS # Ignore MacOS
**/.DS_Store **/.DS_Store
.idea/ .idea/
run/
# Ignore the dedicated working directory
run/*
# ... Except the dummy file inside to make sure that the directory exists
!run/.dummy
# Ignore package building artifacts # Ignore package building artifacts
build_packages/* build_packages/*

View File

@ -1,46 +1,58 @@
# Progressia # Progressia
A free, open source sandbox survival game currently in early development. A free, open-source sandbox survival game currently in early development.
## Description
The game has barely begun development so much of its features are yet to be implemented.
In broader terms, Progressia is a challenging game about survival, exploration and
engineering in a realistic voxel sandbox environment. The game is heavily inspired by
Minecraft technology mods, Factorio, Vintage Story and Minetest. Progressia's main unique
features will include highly composite items and blocks, a realistically-scaled world,
temperature mechanics and a parallelism-capable server.
## System requirements
- GNU/Linux (x64, arm32 or arm64), Windows XP or later (x64 or x86) or MacOS (x64)
- Java 8 or later
- OpenGL 2.1 or later
- Probably at least 4 GiB RAM
- Less than 1 GiB of storage space
See [Build Guide](docs/building/BuildGuide.md) for compilation requirements.
## Contributing ## Contributing
For now, contact @Javapony in Telegram for details. Contributing is completely allowed, but we don't have any set guidelines yet. All contributors welcome. Please contact Javapony in [Telegram](https://t.me/javapony)
or join our [Discord server](https://discord.gg/M4ukyPYgGP) for details or help.
## Building ## Building
On GNU/Linux and MacOS:
1. `$ git clone https://github.com/OLEGSHA/Progressia.git` 1. `$ git clone https://github.com/OLEGSHA/Progressia.git`
2. `$ gradlew build` 2. `$ chmod +x gradlew`
3. `$ ./gradlew buildLocal`
### Additional setup for Eclipse IDE On Windows:
If you have Buildship plugin installed, use File - Import - Gradle - Existing Gradle Project. Main class is `ru.windcorp.progressia.client.ProgressiaClientMain`. 1. `git clone https://github.com/OLEGSHA/Progressia.git`
2. `gradlew.bat buildLocal`
Alternatively do the following: Alternatively use Linux/MacOS steps in a Bash shell.
1. Add `id 'eclipse'` into `build.gradle` inside `plugins { ... }`: For a more in-depth explanation, solutions for common problems and tips for IDE configuration
``` please see the [Build Guide](docs/building/BuildGuide.md).
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
id 'eclipse'
}
```
2. `$ gradlew eclipse`
3. Import the project with File - Import - Existing Projects into Workspace
4. On Windows, make sure the project has UTF-8 encoding with <RMB on project in project tree> - Properties - Resource - Text file encoding - Other - UTF-8
### Additional setup for IntelliJ IDEA
1. Open the project with File - Open Project
2. Press button 'Add configuration...' and open 'Application' in templates list
3. Add `ru.windcorp.progressia.client.ProgressiaClientMain` in 'Main class' text field
4. Choose `Progressia.main` in 'Use classpath of module' drop-down list
5. Click 'Create configuration' and press 'Apply'
## Libraries ## Libraries
* LWJGL - OpenGL, OpenAL, GLFW and several more libraries ported to Java - [LWJGL](https://www.lwjgl.org/) ([GitHub](https://github.com/LWJGL/lwjgl3)) OpenGL, OpenAL, GLFW and STB libraries ported to Java
* Google Guava - [OpenGL](https://en.wikipedia.org/wiki/OpenGL) a low-level graphics interface
* Trove4j - [OpenAL](https://en.wikipedia.org/wiki/OpenAL) a low-level audio interface
* java-graphics/glm - GLM ported to Java. _Maven Central contains an outdated version, a custom repository used instead_ - [GLFW](https://www.glfw.org/) ([GitHub](https://github.com/glfw/glfw)) a minimalistic OpenGL-capable windowing library
* OpenSimplex2 - [STB (GitHub)](https://github.com/nothings/stb) a collection of various algorithms. `stb_vorbis` is used
* log4j - [Guava (GitHub)](https://github.com/google/guava) a generic utilities library
- [Trove4j (BitBucket)](https://bitbucket.org/trove4j/trove) optimized primitive collections
- [java-graphics/glm (GitHub)](https://github.com/java-graphics/glm) GLM ported to Java. _Maven Central contains an outdated version, a custom repository used instead_
- [OpenSimplex2 (GitHub)](https://github.com/KdotJPG/OpenSimplex2) a minimalistic highly optimized noise generator
- [Log4j](https://logging.apache.org/log4j/2.x/) [(GitHub)](https://github.com/apache/logging-log4j2) a logging library

View File

@ -1,31 +1,90 @@
/*
* build.gradle for Progressia
*/
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.
* This is only necessary if you don't use Buildship plugin from the IDE
*/
//id 'eclipse'
} }
java {
/*
* We're Java 8 for now.
* Why? As of 2020, most users have Oracle Java, which only supports Java 8.
*/
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
compileJava {
/*
* We want to compile for Java 8.
* If we are using JDK 8, no further action is required.
* However, on JDK 9 and later versions, '--release' option is required,
* which is missing on JDK 8.
*/
if (JavaVersion.current() != JavaVersion.VERSION_1_8) {
options.compilerArgs.addAll(['--release', '8'])
}
}
/*
* Dependencies
*/
repositories { repositories {
mavenCentral() mavenCentral()
jcenter() jcenter()
maven { url 'http://windcorp.ru/./maven' } /*
* Specify Windcorp Maven repository
* Currently used by:
* - ru.windcorp.fork.io.github.java-graphics:glm:1.0.1
*/
maven { url 'https://windcorp.ru/./maven' }
} }
dependencies { dependencies {
implementation 'org.apache.commons:commons-math3:3.6.1' // Google Guava
// A generic utilities library
implementation 'com.google.guava:guava:30.0-jre' implementation 'com.google.guava:guava:30.0-jre'
// Trove4j
// Provides optimized Collections for primitive types
implementation 'net.sf.trove4j:trove4j:3.0.3' implementation 'net.sf.trove4j:trove4j:3.0.3'
// java-graphics
// A GLM (OpenGL Mathematics) port to Java
// 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
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.3' implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.13.3'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.3' implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.3'
// JUnit
// A unit-testing library
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
// See also LWJGL dependencies below // See LWJGL dependencies below
} }
/*
* Progressia uses the following LWJGL libraries:
* - Core libraries
* - OpenGL
* - OpenAL
* - GLFW
* - STB
*/
/* /*
* LWJGL * LWJGL
* (auto-generated script) * (auto-generated script)
@ -55,94 +114,202 @@ dependencies {
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion") implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
implementation "org.lwjgl:lwjgl" implementation "org.lwjgl:lwjgl"
implementation "org.lwjgl:lwjgl-assimp"
implementation "org.lwjgl:lwjgl-bgfx"
implementation "org.lwjgl:lwjgl-glfw" implementation "org.lwjgl:lwjgl-glfw"
implementation "org.lwjgl:lwjgl-nanovg"
implementation "org.lwjgl:lwjgl-nuklear"
implementation "org.lwjgl:lwjgl-openal" implementation "org.lwjgl:lwjgl-openal"
implementation "org.lwjgl:lwjgl-opengl" implementation "org.lwjgl:lwjgl-opengl"
implementation "org.lwjgl:lwjgl-par"
implementation "org.lwjgl:lwjgl-stb" implementation "org.lwjgl:lwjgl-stb"
implementation "org.lwjgl:lwjgl-vulkan"
runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-assimp::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-bgfx::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-nanovg::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-nuklear::$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-par::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives" runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
if (lwjglNatives == "natives-macos") runtimeOnly "org.lwjgl:lwjgl-vulkan::$lwjglNatives"
} }
// LWJGL END // LWJGL END
configurations { /*
packageOnly * Tasks
packageLibraries.extendsFrom runtimeClasspath */
packageLibraries.extendsFrom packageOnly
}
dependencies { /*
def archs = ['natives-linux', 'natives-linux-arm64', 'natives-linux-arm32', 'natives-macos', 'natives-windows', 'natives-windows-x86'] * Additional native libraries specification
*/
project.ext.platforms = new HashSet<>()
task addNativeDependencies {
doFirst {
def archs = project.ext.platforms
switch (archs.size()) {
case 0:
println "Adding LWJGL native dependencies for local platform only:\n\t$lwjglNatives"
archs.add project.ext.lwjglNatives
break
case 1:
println "Adding LWJGL native dependencies for platform\n\t" + archs.get(0)
break
default:
println "Adding LWJGL native dependencies for platforms:\n\t" + archs.join("\n\t")
}
if (project.ext.lwjglNatives.isEmpty()) println "WTF"
dependencies {
archs.each { arch -> archs.each { arch ->
packageOnly "org.lwjgl:lwjgl::$arch" runtimeOnly "org.lwjgl:lwjgl::$arch"
packageOnly "org.lwjgl:lwjgl-assimp::$arch" runtimeOnly "org.lwjgl:lwjgl-glfw::$arch"
packageOnly "org.lwjgl:lwjgl-bgfx::$arch" runtimeOnly "org.lwjgl:lwjgl-openal::$arch"
packageOnly "org.lwjgl:lwjgl-glfw::$arch" runtimeOnly "org.lwjgl:lwjgl-opengl::$arch"
packageOnly "org.lwjgl:lwjgl-nanovg::$arch" runtimeOnly "org.lwjgl:lwjgl-stb::$arch"
packageOnly "org.lwjgl:lwjgl-nuklear::$arch" }
packageOnly "org.lwjgl:lwjgl-openal::$arch" }
packageOnly "org.lwjgl:lwjgl-opengl::$arch"
packageOnly "org.lwjgl:lwjgl-par::$arch"
packageOnly "org.lwjgl:lwjgl-stb::$arch"
} }
packageOnly "org.lwjgl:lwjgl-vulkan::natives-macos"
} }
jar { compileJava.mustRunAfter addNativeDependencies // Make sure runtimeOnly has not been resolved
manifest {
attributes( task requestLinuxDependencies {
"Main-Class": "ru.windcorp.progressia.client.ProgressiaClientMain", description 'Adds linux, linux-arm64 and linux-arm32 native libraries to built artifacts.'
"Class-Path": configurations.packageLibraries.collect { "lib/" + it.getName() }.join(' ') doFirst {
) project.ext.platforms.addAll(['natives-linux', 'natives-linux-arm64', 'natives-linux-arm32'])
} }
} }
task requestWindowsDependencies {
description 'Adds windows and windows-x86 native libraries to built artifacts.'
doFirst {
project.ext.platforms.addAll(['natives-windows', 'natives-windows-x86'])
}
}
task requestMacOSDependencies {
description 'Adds macos native libraries to built artifacts.'
doFirst {
project.ext.platforms.addAll(['natives-macos'])
}
}
def dependencySpecificationTasks = tasks.findAll { task -> task.name.startsWith('request') && task.name.endsWith('Dependencies') }
task requestCrossPlatformDependencies {
description 'Adds native libraries for all available platforms to built artifacts.'
dependsOn dependencySpecificationTasks
}
addNativeDependencies.mustRunAfter dependencySpecificationTasks
/*
* Determines if the provided dependency should be packaged
*/
def isDependencyRequested(String dep) {
if (dep.endsWith(".jar")) {
dep = dep.substring(0, dep.length() - ".jar".length())
}
return !dep.contains("natives-") ||
project.ext.platforms.contains(dep.substring(dep.indexOf("natives-"), dep.length()))
}
/* /*
* Copies runtime dependencies to a prespecified location so they can be packaged properly. * Manifest specification
*/ */
task copyLibs(type: Copy) {
into "${libsDir}/lib"
from configurations.runtimeClasspath
}
build.dependsOn(copyLibs) task specifyLocalManifest {
dependsOn addNativeDependencies // Make sure all native dependencies are specified
task copyLibsForPackaging(type: Copy) { doFirst {
into "${libsDir}/lib" def classPath = []
from configurations.packageLibraries
}
task createPackages(type: Exec) { configurations.runtimeClasspath.each {
commandLine './buildPackages.sh' if (isDependencyRequested(it.getName())) {
} classPath.add("lib/" + it.getName())
} else {
println "\tRemoving from JAR classpath (not requested): " + it.getName()
}
}
java { if (classPath.size() == configurations.runtimeClasspath.size()) {
sourceCompatibility = JavaVersion.VERSION_1_8 println "Nothing removed from JAR classpath"
targetCompatibility = JavaVersion.VERSION_1_8 }
}
compileJava { jar {
if (JavaVersion.current() != JavaVersion.VERSION_1_8) { manifest {
options.compilerArgs.addAll(['--release', '8']) attributes(
"Main-Class": "ru.windcorp.progressia.client.ProgressiaClientMain",
"Class-Path": configurations.runtimeClasspath.collect { "lib/" + it.getName() } .findAll { isDependencyRequested(it) } .join(' ')
)
}
}
} }
} }
createPackages.dependsOn(build) jar.dependsOn specifyLocalManifest
createPackages.dependsOn(copyLibsForPackaging)
/*
* Library export
*/
task exportLibs(type: Sync) {
mustRunAfter addNativeDependencies
into libsDirectory.get().getAsFile().getPath() + "/lib"
exclude { !isDependencyRequested(it.getName()) }
from configurations.runtimeClasspath
}
jar.dependsOn(exportLibs)
/*
* Packaging
*/
task packageDebian(type: Exec) {
description 'Builds the project and creates a Debain package.'
group 'Progressia'
dependsOn build
dependsOn requestLinuxDependencies
commandLine './buildPackages.sh', 'debian'
doLast {
println "Debian package available in build_packages/"
}
}
task packageWindows(type: Exec) {
description 'Builds the project and creates a Windows installer.'
group 'Progressia'
dependsOn build
dependsOn requestWindowsDependencies
commandLine './buildPackages.sh', 'windows'
doLast {
println "Windows installer available in build_packages/"
}
}
task buildCrossPlatform {
description 'Builds the project including native libraries for all available platforms.'
group 'Progressia'
dependsOn requestCrossPlatformDependencies
dependsOn build
doLast {
println "Native libraries for all platforms have been added"
}
}
task buildLocal {
description "Builds the project including only native libraries for current platform ($lwjglNatives)."
group 'Progressia'
dependsOn build
doLast {
println "Native libraries only for platform $lwjglNatives have been added"
}
}

View File

@ -1,38 +1,161 @@
#!/bin/bash #!/bin/bash
lst="nsis" echoerr() { echo "$@" 1>&2; }
user=`whoami` buildDebianPackage() {
dpkg -l 2>/dev/null > ls.tmp # Commands that must be available to execute this action
requiredCommands='dpkg-deb fakeroot'
for items in $lst # Version that the package will receive
do version='0.1_all'
cmd=$(grep "\ $items\ " ls.tmp)
if [ $? == 0 ] directory="build_packages/DEB/progressia-$version"
then
echo "$items installed!" # .deb control file that must be present
echo "Building..." configurationFile="$directory/DEBIAN/control"
outputFile="build_packages/DEB/progressia-$version.deb"
echo "Checking environment to build Debian package"
for item in $requiredCommands; do
if command -v "$item" &> /dev/null; then
echo "- $item found"
else else
echo "Package $items not found! Please install $items." echoerr "Command $item not found, cannot package"
rm ls.tmp exit 100
exit 1
fi fi
done done
rm ls.tmp
cd build_packages/DEB/progressia-0.1_all/ if ! [ -r "$configurationFile" ]; then
mkdir -p home/$user/Progressia echoerr "$configurationFile is missing or not readable, cannot package"
exit 101
else
echo "- $configurationFile is present and readable"
fi
cd ../../.. echo "Environment OK; packaging Debian package"
exitCode=0
cp -r build/libs/lib build_packages/DEB/progressia-0.1_all/home/$user/Progressia/ {
cp build/libs/Progressia.jar build_packages/DEB/progressia-0.1_all/home/$user/Progressia/ user=`whoami`
cp -r build/libs/lib build_packages/NSIS homeDir="$directory/home/$user/Progressia/"
cp build/libs/Progressia.jar build_packages/NSIS
makensis build_packages/NSIS/ProgressiaInstaller.nsi mkdir -p "$homeDir" &&
mv build_packages/NSIS/ProgressiaInstaller.exe build_packages/Progressia.exe cp -r 'build/libs/lib' "$homeDir/lib" &&
fakeroot dpkg-deb --build build_packages/DEB/progressia-0.1_all cp 'build/libs/Progressia.jar' "$homeDir/Progressia.jar" &&
mv build_packages/DEB/progressia-0.1_all.deb build_packages/progressia-0.1_all.deb echo "------ DPKG-DEB ------" &&
echo "Build done!" fakeroot dpkg-deb --build "$directory" &&
echo "---- DPKG-DEB END ----" &&
mv "$outputFile" build_packages
} || {
echoerr "Could not create Debian package"
exitCode=1
}
{
if [ -d "$homeDir" ]; then
rm -r "$homeDir"
fi
echo "Cleaned up"
} || {
echoerr "Could not clean up after packaging Debian package"
exitCode=2
}
exit "$exitCode"
}
buildWindowsInstaller() {
# Commands that must be available to execute this action
requiredCommands='makensis'
# NSIS configuration file that must be present
configurationFile='build_packages/NSIS/ProgressiaInstaller.nsi'
# File that will be output
outputFile='build_packages/NSIS/ProgressiaInstaller.exe'
echo "Checking environment to build Windows installer"
for item in $requiredCommands; do
if command -v "$item" &> /dev/null; then
echo "- $item found"
else
echoerr "Command $item not found, cannot build"
exit 100
fi
done
if ! [ -r "$configurationFile" ]; then
echoerr "$configurationFile is missing or not readable, cannot build"
exit 101
else
echo "- $configurationFile is present and readable"
fi
echo "Environment OK; building Windows installer"
exitCode=0
{
cp -r 'build/libs/lib' 'build_packages/NSIS/lib' &&
cp 'build/libs/Progressia.jar' 'build_packages/NSIS/Progressia.jar' &&
echo "------ NSIS ------" &&
makensis "$configurationFile" &&
echo "---- NSIS END ----" &&
mv "$outputFile" build_packages
} || {
echoerr "Could not build Windows installer"
exitCode=1
}
{
if [ -d 'build_packages/NSIS/lib' ]; then
rm -r 'build_packages/NSIS/lib'
fi
if [ -e 'build_packages/NSIS/Progressia.jar' ]; then
rm 'build_packages/NSIS/Progressia.jar'
fi
echo "Cleaned up"
} || {
echoerr "Could not clean up after building Windows installer"
exitCode=2
}
exit "$exitCode"
}
printUsage() {
echoerr "Usage: $0 TARGET"
echoerr " where TARGET is 'debian' or 'windows'"
}
if [ -n "$2" ]; then
echoerr "Too many arguments."
printUsage
exit 202
fi
case "$1" in
"debian")
buildDebianPackage
;;
"windows")
buildWindowsInstaller
;;
"")
echoerr "No action specified"
printUsage
exit 200
;;
"--help" | "-help" | "help" | "?")
printUsage
;;
*)
echoerr "Unknown action '$1'"
printUsage
exit 201
;;
esac

203
docs/building/BuildGuide.md Normal file
View File

@ -0,0 +1,203 @@
# Build Guide
This document is a guide to building Progressia from source.
Compilation should be possible on all platforms that support JDK 8 or later, however, packaging scripts require Bash.
This guide assumes you are familiar with using a terminal or Windows Command Prompt or PowerShell.
See [Eclipse Guide](EclipseGuide.md) and [IntelliJ IDEA Guide](IntelliJIDEAGuide.md) for IDE-specific configuration.
## Basic compilation
### Installing prerequisites
Compiling Progressia requires that a JDK (Java Development Kit) 8 or later is available in your system path. Please
note that JDK is not the same as a JRE (Java Runtime Environment), the software required to execute Java programs;
you may be able to run Progressia but not compile it.
To check whether you have the correct JDK installed please run
`javac -version`.
If this command fails or outputs version 1.7 or lower, then you need to (re-)install JDK. (javac is the Java
Compiler.)
Progressia developers recommend [OpenJDK](https://openjdk.java.net/) as the free, open-source Java implementation.
Confusion may arise from the project's name: OpenJDK issues both JRE and JDK; an OpenJDK JRE is not enough to compile
Progressia. Another popular choice is [Oracle Java](https://www.oracle.com/java/technologies/), which is proprietary
and thus not recommended.
To install OpenJDK JDK on GNU/Linux, install the appropriately named package with your package manager (on Debian,
Ubuntu and other dpkg-based distributions, run
`apt-get install default-jdk`
with root privileges).
To install OpenJDK JDK on MacOS or Windows, Progressia developers recommend [AdoptOpenJDK](https://adoptopenjdk.net/),
which creates and distributes OpenJDK installers and packages. Please confirm that JDK installed correctly using
the aforementioned test.
### Getting the source code
Progressia source code is managed with [git](https://git-scm.com/), a popular open-source tool. It is a program that
automatically keeps track of changes in a set of source code and allows synchronization of those changes between
different computers. A copy of the source code is called a repository. This guide will assume that
[Progressia's GitHub repository](https://github.com/OLEGSHA/Progressia/) is accessible; if it is not, please look up
the relevant instructions.
If git is installed on your system, perform a clone of
`https://github.com/OLEGSHA/Progressia.git`.
The details may vary depending on your git frontend; if you are not using a frontend, issue the following command:
```
git clone https://github.com/OLEGSHA/Progressia.git
```
Run the command in your directory of choice, git will create a subfolder. After the action completes you should
have a local copy of the source code.
If you do not have git installed, use GitHub's 'Download ZIP' option (available through the green 'Code' button at
the time of writing this). Unpack the downloaded archive into any directory.
### Compiling
Compilation and related tasks are managed by [Gradle](https://gradle.org/), another popular open-source tool. The repository
contains a Gradle Wrapper which automatically detects and installs the appropriate Gradle version. Gradle is most
conveniently controlled with one of two scripts, `gradlew` or `gradlew.bat` for Bash and Windows Command Prompt respectively,
which are distributed within the repository as well. Gradle itself uses another file, `build.gradle`, that contains the
relevant instructions in Groovy.
On GNU/Linux and MacOS, the script may need to receive the execution permission before being run:
```
chmod +x gradlew
```
A most basic compilation is achieved with:
```
./gradlew buildLocal
```
This instructs Gradle to compile, check and test a JAR archive with the game, as well as to download all necessary
dependencies. The resulting JAR file will only reference libraries required to run the game on your current platform.
The compiled JAR and all necessary libraries can be found in `build/libs/`. The `lib` directory next to `Progressia.jar`
contains all runtime dependencies; the game may be run with a simple
`java -jar Progressia.jar`
if `lib` is located in the same directory as the JAR file. (On many systems double-clicking `Progressia.jar` has the
same effect.) Otherwise, if there is no `lib` directory next to the JAR, classpath must be set manually with command
line options for `java`.
A more conventional command, `./gradlew build`, may be used to the same effect; however, Progressia developers recommend
against using it as their effects might start to differ with future updates.
## Building for other platforms
### Native libraries and why platforms matter
Although Java is well-known for its portability, Progressia has a limited set of architectures that it supports.
This is a consequence of the fact that Progressia uses [OpenGL](https://en.wikipedia.org/wiki/OpenGL),
[OpenAL](https://en.wikipedia.org/wiki/OpenAL), [GLFW](https://www.glfw.org) and [STB](https://github.com/nothings/stb),
four libraries originally implemented in the C language. In order to access them, a Java wrapper library,
[LWJGL](https://www.lwjgl.org/), is used. Unfortunately such wrappers need to be hand-written for each platform
and require complicated compilation.
In practice this means that along with the pure Java libraries, such as Guava or GLM, Progressia carries several
LWJGL libraries that each consist of a Java interface and a compiled binary implementation (called a native library).
A separate version of a single native library is required to run Progressia on different platforms; if a game only
contains natives for Windows, it cannot be run on GNU/Linux.
### How Gradle is set up
Gradle builds Progressia by first choosing which platform or platforms should be supported. It then downloads,
if necessary, and processes only dependencies that are relevant to the current configuration. When creating the JAR
file, Gradle appends only selected libraries to the JAR's manifest file. It finally copies only the libraries included
in the manifest to the `build/libs/lib` directory.
Why not package all natives all the time? This is inefficient when producing temporary builds for development purposes
because unnecessary dependencies need to be downloaded and processed. This mechanism is also used to trim down the
size of various system-specific installers and packages since, for example, a Windows Installer is not expected to
produce a installation that runs on anything other than Windows, so GNU/Linux and MacOS natives need not be packaged
with it.
Unless instructed otherwise, Gradle only chooses the local platform. Thus the procedure described in 'Basic Compilation'
produces an output that only contains the natives for the platform that performed the compilation. It is unsuitable for
publication and may be generally inconvenient.
### Building cross-platform
Fortunately it is possible to produce a maximally cross-platform version by running Gradle with a different task:
```
./gradlew buildCrossPlatform
```
This command performs the same actions as the `buildLocal` command, except that all possible native libraries are
included in the JAR manifest and copied into `build/libs/lib`. The result may be run on any supported platform.
However, because of the large amount of libraries, it has significantly greater size than a platform-specific
build.
### Building for a specific platform
Some users might find the need to build for a specific set of platforms. Inclusion of GNU/Linux, Windows or MacOS
dependencies individually can be controlled with the following arguments to the `./gradlew build` command:
- `requestLinuxDependencies` requests that `natives-linux`, `natives-linux-arm32` and `natives-linux-arm64` binaries are included;
- `requestWindowsDependencies` requests that `natives-windows` and `natives-windows-x86` binaries are included;
- `requestMacOSDependencies` requests that `natives-macos` binaries are included.
These requests can be applied in any combination. For example, the following command produces a build containing only
GNU/Linux and Windows natives:
```
./gradlew build requestLinuxDependencies requestWindowsDependencies
```
For finer control please edit `build.gradle` manually by adding the desired natives to the `project.ext.platforms` set like so:
```
project.ext.platforms = new HashSet<>()
project.ext.platforms.add 'natives-windows-x86'
```
## Packaging
A Debian package and a Windows installer can be created automatically on systems that support Bash. These tasks are delegated
by Gradle to `buildPackages.sh` in repository root. This script checks the environment and assembles the requested output; the
resulting files are moved into `build_packages`.
### Creating a Debian package
A Debian package can be created with the following Gradle task:
```
./gradlew packageDebian
```
Gradle will then build all artifacts necessary to run the game on GNU/Linux (all three architectures) and invoke
`./buildPackages.sh debian`. Commands `dpkg-deb` and `fakeroot` must be available in system path in order to build the package.
### Creating a Windows installer
A Windows installer can be created with the following Gradle task:
```
./gradlew packageWindows
```
Gradle will then build all artifacts necessary to run the game on Windows (both x64 and x86 architectures) and invoke
`./buildPackages.sh windows`.
Windows installers are implemented with [NSIS](https://nsis.sourceforge.io/). Command `makensis` must be available in system
path in order to build the installer.
## Gradle tasks summary
- `buildLocal` creates a build optimized for current platform. Use this to quickly build the game during development.
- `buildCrossPlatform` creates a build that supports all known architectures. Use this to build a universal version of the game.
- `build` currently a synonym of `buildLocal`; creates a default build.
- `packageDebian` creates a Debian package. Do not invoke together with `packageWindows`.
- `packageWindows` creates a Windows installer. Do not invoke together with `packageDebian`.
- `requestLinuxDependencies` requests that `natives-linux`, `natives-linux-arm32` and `natives-linux-arm64` binaries are included when building.
- `requestWindowsDependencies` requests that `natives-windows` and `natives-windows-x86` binaries are included when building.
- `requestMacOSDependencies` requests that `natives-macos` binaries are included when building.
- `requestCrossPlatformDependencies` requests that all binaries are included when building.
All other basic and Java-related Gradle tasks are available as well.

View File

@ -0,0 +1,113 @@
### Eclipse Guide
This document is a guide to configuring Eclipse IDE for developing Progressia.
## Setup
### Downloading project
Although the project may be downloaded manually or using git directly (as described in the
[Build Guide](BuildGuide.md)), it may be more convenient to use Eclipse's EGit. If you
choose not to, skip the following subsection.
#### Using EGit
[EGit](https://www.eclipse.org/egit/) is a git interface for Eclipse. It is currently shipped
with Eclipse IDE.
1. Open Git perspective. (Git perspective is not visible by default. To open it, use
'Window' menu > 'Perspective' > 'Open Perspective' > 'Other' > select Git.)
2. In 'Git Repositories' view, click 'Clone a Git Repository and add the clone to this view'
button.
3. Paste
`https://github.com/OLEGSHA/Progressia.git`
or the appropriate git URI into the 'URI' field and click 'Next'.
4. Review the branches and click 'Next'.
5. Edit the local repository path if necessary and click 'Finish'.
Note: avoid importing the project from the Git Clone Wizard as doing so will fail to specify
Gradle dependencies.
### Importing project
Gradle dependencies need to be imported into the IDE for proper code analysis and launching.
#### Using Buildship plugin for Eclipse
[Buildship](https://projects.eclipse.org/projects/tools.buildship) is an Eclipse plugin
that integrates Gradle into the IDE. This is the recommended method.
1. In 'File' menu, select 'Import...'.
2. In the Import Wizard, select 'Gradle' > 'Existing Gradle Project'. Click 'Next'.
3. In the Gradle Import Wizard, click 'Next' to arrive at directory selection.
4. Select the directory that contains `build.gradle` file in 'Project root directory' field.
5. Click 'Finish' and allow the plugin to import the project.
When using this method, any changes to the `build.gradle` file must be followed by a Gradle
refresh ((Project context menu) > 'Gradle' > 'Refresh Gradle Project').
#### Using Eclipse plugin for Gradle
Gradle features a plugin for Eclipse that can generate project specifications for the IDE.
It is deactivated by default.
1. Enable the Eclipse plugin by uncommenting the `id 'eclipse'` line in `build.gradle`
(note the disappearance of `//`). Please make sure not to accidentally commit this change in git!
```
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
/*
* Uncomment the following line to enable the Eclipse plugin.
* This is only necessary if you don't use Buildship plugin from the IDE
*/
id 'eclipse'
}
```
2. Run
`./gradlew eclipse`
in the directory that contains `build.gradle`. This command will
generate Eclipse project files.
3. In 'File' menu in the Eclipse IDE, select 'Import...'.
4. In the Import Wizard, select 'General' > 'Existing Projects into Workspace'. Click 'Next'.
5. Select the directory that contains `build.gradle` file in 'Select root directory' field.
6. Click 'Finish' and allow the IDE to import the project.
When using this method, any changes to the `build.gradle` file must be followed by
`./gradlew eclipse` command and a project refresh ((Project context menu) > 'Refresh').
### Creating a Run Configuration
Run configurations are used by Eclipse IDE to specify how a project must be run.
1. In 'Run' menu, select 'Run Configurations...'.
2. In the Run Configurations, select 'Java Application', then click 'New launch configuration'.
3. Specify the project and the name of the new configuration.
4. Put
`ru.windcorp.progressia.client.ProgressiaClientMain`
into 'Main Class' field.
5. In the 'Arguments' tab, put
`${workspace_loc:Progressia}/run`
into 'Working directory:' > 'Other' field. Replace `Progressia` with your name of the project.
Alternatively specify another location outside of the project's root directory.
6. Click 'Apply' to save changes. Exit Run Configurations.
Step 5 is required to specify that the game must run in some directory other than the project root,
which is the default in Eclipse.
## Common problems
### Buildship plugin fails with a cryptic message
This may be caused by a lack of Java in your system path. Eclipse stores the path to the JVM it
uses in its settings and is thus not affected by the changes to the system path. However, Gradle
searches for Java installations in system path regardless and may fail independently of Eclipse.
__Solution:__ the simplest solution is to reinstall JDK making sure that system path is affected.
See [Build Guide](BuildGuide.md) for details. Another course of action is to manually append the
Java installation directory (specifically its `bin` folder) to the system `PATH` variable.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

1
run/.dummy Normal file
View File

@ -0,0 +1 @@
This is a dummy file to make sure run/ directory is stored and created by git.

View File

@ -39,7 +39,6 @@ public class ProgressiaLauncher {
CrashReports.registerProvider(new OpenALContextProvider()); CrashReports.registerProvider(new OpenALContextProvider());
CrashReports.registerProvider(new ArgsContextProvider()); CrashReports.registerProvider(new ArgsContextProvider());
CrashReports.registerProvider(new LanguageContextProvider()); CrashReports.registerProvider(new LanguageContextProvider());
CrashReports.registerProvider(new StackTraceProvider());
// Analyzers // Analyzers
CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer()); CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer());

View File

@ -18,6 +18,7 @@
package ru.windcorp.progressia.client; package ru.windcorp.progressia.client;
import ru.windcorp.progressia.Proxy; import ru.windcorp.progressia.Proxy;
import ru.windcorp.progressia.client.audio.AudioSystem;
import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend;
import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue; import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue;
import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram; import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram;
@ -47,6 +48,8 @@ public class ClientProxy implements Proxy {
Atlases.loadAllAtlases(); Atlases.loadAllAtlases();
AudioSystem.initialize();
ServerState.startServer(); ServerState.startServer();
ClientState.connectToLocalServer(); ClientState.connectToLocalServer();
} }

View File

@ -18,12 +18,10 @@
package ru.windcorp.progressia.client; package ru.windcorp.progressia.client;
import ru.windcorp.progressia.ProgressiaLauncher; import ru.windcorp.progressia.ProgressiaLauncher;
import ru.windcorp.progressia.test.ALTest;
public class ProgressiaClientMain { public class ProgressiaClientMain {
public static void main(String[] args) { public static void main(String[] args) {
ALTest.execute();
ProgressiaLauncher.launch(args, new ClientProxy()); ProgressiaLauncher.launch(args, new ClientProxy());
} }

View File

@ -0,0 +1,16 @@
package ru.windcorp.progressia.client.audio;
public class AudioSystem {
static public void initialize() {
AudioManager.initAL();
Thread shutdownHook = new Thread(AudioManager::closeAL, "AL Shutdown Hook");
Runtime.getRuntime().addShutdownHook(shutdownHook);
loadAudioData();
}
static void loadAudioData() {
AudioManager.loadSound("assets/sounds/block_destroy_clap.ogg",
"Progressia:BlockDestroy",
AudioFormat.MONO);
}
}

View File

@ -1,13 +1,11 @@
package ru.windcorp.progressia.common.util; package ru.windcorp.progressia.common.util;
import org.apache.commons.math3.util.FastMath;
public class FloatMathUtils { public class FloatMathUtils {
public static final float PI_F = (float) Math.PI; public static final float PI_F = (float) Math.PI;
public static float floor(float x) { public static float floor(float x) {
return (float) FastMath.floor(x); return (float) Math.floor(x);
} }
public static float normalizeAngle(float a) { public static float normalizeAngle(float a) {

View File

@ -2,14 +2,11 @@ package ru.windcorp.progressia.common.util.crash;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.util.StringBuilderWriter;
import ru.windcorp.jputil.chars.StringUtil; import ru.windcorp.jputil.chars.StringUtil;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -88,6 +85,8 @@ public class CrashReports {
* @return {@code null}, although this method never returns normally. Provided for convenience. * @return {@code null}, although this method never returns normally. Provided for convenience.
*/ */
public static RuntimeException crash(Throwable throwable, String messageFormat, Object... args) { public static RuntimeException crash(Throwable throwable, String messageFormat, Object... args) {
final StackTraceElement[] reportStackTrace;
if (throwable instanceof ReportedException) { if (throwable instanceof ReportedException) {
ReportedException reportedException = (ReportedException) throwable; ReportedException reportedException = (ReportedException) throwable;
@ -95,6 +94,10 @@ public class CrashReports {
throwable = reportedException.getCause(); throwable = reportedException.getCause();
messageFormat = reportedException.getMessageFormat(); messageFormat = reportedException.getMessageFormat();
args = reportedException.getArgs(); args = reportedException.getArgs();
reportStackTrace = reportedException.getStackTrace();
} else {
reportStackTrace = getCurrentStackTrace();
} }
StringBuilder output = new StringBuilder(); StringBuilder output = new StringBuilder();
@ -127,7 +130,9 @@ public class CrashReports {
appendMessageFormat(output, messageFormat, args); appendMessageFormat(output, messageFormat, args);
appendStackTrace(output, throwable); appendStackTrace(output, reportStackTrace, "Reported at:");
output.append('\n');
appendThrowable(output, throwable);
export(output.toString()); export(output.toString());
@ -135,6 +140,13 @@ public class CrashReports {
return null; return null;
} }
private static StackTraceElement[] getCurrentStackTrace() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
final int trim = 3;
return Arrays.copyOfRange(stackTrace, trim, stackTrace.length);
}
private static void appendContextProviders(StringBuilder output) { private static void appendContextProviders(StringBuilder output) {
// Do a local copy to avoid deadlocks -OLEGSHA // Do a local copy to avoid deadlocks -OLEGSHA
@ -225,22 +237,22 @@ public class CrashReports {
addSeparator(output); addSeparator(output);
} }
private static void appendStackTrace(StringBuilder output, Throwable throwable) { private static void appendThrowable(StringBuilder output, Throwable throwable) {
output.append("Stacktrace: \n");
if (throwable == null) { if (throwable == null) {
output.append("no Throwable provided").append("\n"); output.append("No Throwable provided").append("\n");
return; return;
} }
// Formatting to a human-readable string output.append("Reported Throwable:\n");
Writer sink = new StringBuilderWriter(output); appendStackTrace(output, throwable.getStackTrace(), throwable.toString());
try { }
throwable.printStackTrace(new PrintWriter(sink));
} catch (Exception e) { private static void appendStackTrace(StringBuilder output, StackTraceElement[] stackTrace, String header) {
// PLAK output.append(header).append('\n');
for (StackTraceElement element : stackTrace) {
output.append('\t').append(element).append('\n');
} }
output.append("\n");
} }
private static void export(String report) { private static void export(String report) {

View File

@ -1,24 +0,0 @@
package ru.windcorp.progressia.common.util.crash.providers;
import ru.windcorp.progressia.common.util.crash.ContextProvider;
import java.util.Map;
public class StackTraceProvider implements ContextProvider {
@Override
public void provideContext(Map<String, String> output) {
StackTraceElement[] stackTraceBuffer = Thread.currentThread().getStackTrace();
StringBuilder sb = new StringBuilder();
sb.append("\n");
for (int i = 4; i < stackTraceBuffer.length; i++) {
sb.append('\t').append(stackTraceBuffer[i].toString()).append("\n");
}
output.put("Reported from " + Thread.currentThread().getName(), sb.toString());
}
@Override
public String getName() {
return "Stack Trace Context Provider";
}
}

View File

@ -1,30 +0,0 @@
package ru.windcorp.progressia.test;
import ru.windcorp.progressia.client.audio.AudioFormat;
import ru.windcorp.progressia.client.audio.AudioManager;
import ru.windcorp.progressia.client.audio.Music;
public class ALTest {
static private void initializeAL() {
AudioManager.initAL();
}
static void loadALData() {
AudioManager.loadSound("assets/sounds/sample_stereo.ogg",
"Progressia:SampleStereo",
AudioFormat.STEREO);
AudioManager.loadSound("assets/sounds/block_destroy_clap.ogg",
"Progressia:BlockDestroy",
AudioFormat.MONO);
Music music = new Music("Progressia:SampleStereo");
music.setGain(0.5f);
//music.play(false);
}
public static void execute() {
initializeAL();
Thread shutdownHook = new Thread(AudioManager::closeAL, "AL Shutdown Hook");
Runtime.getRuntime().addShutdownHook(shutdownHook);
loadALData();
}
}