12 Commits

Author SHA1 Message Date
22a744f65a Added Options
-Added options menu
-You can move from options to title and back
-Added language change button
*Double check the Russian, I just copied and pasted from other files
2022-01-08 21:16:51 -05:00
c6de19cf19 Rebased everything on master
Now has the dynamic version thing
fixed warnings
2022-01-08 13:57:57 -05:00
c1a57f7d7a Slightly better alignment
The mode for alignment is more concise
2022-01-08 12:45:28 -05:00
162b2249b1 Rewrote build script, improved packaging
- Renamed :packageWindows to :packageNsis
- ImageMagick now required for :packageNsis
- Packaging output is now in build/packages
- Rewrote build script
  - Packaging logic and LWJGL dependencies now in separate files
  - Packaging logic now implemented with Gradle, not Bash scripts
    - Cross-platform?
- Added :packageZip
  - Universal ZIP with start scripts
- Changed version detection logic
  - Tags of ancestor commits are now considered
  - Only tags with format vMAJOR.MINOR.PATCH[-SUFFIX] are considered
  - If the tag's commit isn't HEAD, PATCH is incremented
  - When version detection fails, dummy version is 999.0.0-<buildID or date>
- LWJGL target platforms can be overridden with forceTargets project property
2022-01-07 22:23:24 +03:00
dececb4589 Fixed window icons error on Wayland 2021-12-26 20:36:32 +03:00
ec17eb7065 Added window icons
- Added window icons for various sizes
  - Broken on Wayland
  - Due to a bug in texture loading, textures a flipped
    - Included non-flipped versions
- Added TextureSettings.allocateExactBuffer
  - When true, texture size is not rounded to a power of 2
2021-12-26 14:30:50 +03:00
e4d0570200 Added automatic version detection to Gradle and game 2021-12-25 20:24:45 +03:00
576cfed99f Fixed import warnings 2021-10-17 14:05:40 +03:00
5af1b7309d Better Alignment
-Created some Layouts to properly adjust where things go
    -LayoutEdges for text on the same row on opposite sides of the screen
    -LayoutColumn for a non-max width column
-More accessible version string
2021-10-13 23:37:18 -04:00
0f0a94811f Cleaning
-Cleaned up offsets to make it look like a cube and not 6 squares.
-Fixed error where regions would incorrectly reset files
-Some additions to try to match the intended look. I really dont
understand layouts.
2021-09-25 20:45:17 -04:00
51bcca1499 Betterish title screen
-Black background used
	-New Background class for displaying a single texture to the back of
the screen(probably not the best way)
-Title now uses an image
	-Made TextureComponent, I think this probably exists elsewhere but I
couldnt find it
-Cube faces now change color based on where they are facing, looks a lot
like the source material except for rearranging
2021-09-13 13:05:59 -04:00
ce9e95e5ce Well, its [i]a[/i] cube.
-Added CubeComponent to render a cube to the screen
-Added it to the title screen
2021-09-11 21:11:59 -04:00
67 changed files with 1528 additions and 665 deletions

2
.gitattributes vendored
View File

@ -6,4 +6,4 @@
* text=auto eol=lf
*.bat text eol=crlf
*.nsi text eol=crlf

View File

@ -1,23 +1,29 @@
/*
* build.gradle for Progressia
* Build logic for Progressia
* build.gradle
*
* Please refer to
*
* docs/building/BuildScriptReference.md
*
* for user reference.
*/
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'
id 'java'
// GrGit
// A JGit wrapper for Groovy used to access git commit info
id 'org.ajoberstar.grgit' version '4.1.1'
}
/*
* Configure Java version
*/
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
}
@ -34,6 +40,8 @@ compileJava {
}
}
/*
* Dependencies
*/
@ -42,7 +50,7 @@ repositories {
mavenCentral()
/*
* Specify Windcorp Maven repository
* Windcorp Maven repository
* Currently used by:
* - ru.windcorp.fork.io.github.java-graphics:glm:1.0.1
*/
@ -72,230 +80,308 @@ dependencies {
// A unit-testing library
testImplementation 'junit:junit:4.13.2'
// See LWJGL dependencies below
// Also see LWJGL dependencies in build_logic/lwjgl.gradle
}
/*
* Progressia uses the following LWJGL libraries:
* - Core libraries
* - OpenGL
* - OpenAL
* - GLFW
* - STB
*/
/*
* LWJGL
* (auto-generated script)
* ((here be dragons))
* Version resolution
*/
import org.gradle.internal.os.OperatingSystem
import org.ajoberstar.grgit.*
project.ext.lwjglVersion = "3.2.3"
// Pattern: vMAJOR.MINOR.PATCH[-SUFFIX]
project.ext.tagFormat = /^v(\d+)\.(\d+)\.(\d+)(-[\w\-]*)?$/
switch (OperatingSystem.current()) {
case OperatingSystem.LINUX:
def osArch = System.getProperty("os.arch")
project.ext.lwjglNatives = osArch.startsWith("arm") || osArch.startsWith("aarch64")
? "natives-linux-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}"
: "natives-linux"
break
case OperatingSystem.MAC_OS:
project.ext.lwjglNatives = "natives-macos"
break
case OperatingSystem.WINDOWS:
project.ext.lwjglNatives = System.getProperty("os.arch").contains("64") ? "natives-windows" : "natives-windows-x86"
break
}
dependencies {
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
implementation "org.lwjgl:lwjgl"
implementation "org.lwjgl:lwjgl-glfw"
implementation "org.lwjgl:lwjgl-openal"
implementation "org.lwjgl:lwjgl-opengl"
implementation "org.lwjgl:lwjgl-stb"
runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-openal::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
}
// LWJGL END
/*
* Tasks
*/
/*
* 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")
String version_parseVersion(String tag, boolean increment) {
try {
def data = (tag =~ tagFormat)[0]
def major = data[1]
def minor = data[2]
def patch = data[3] as int
def suffix = data[4] ?: ''
if (increment) {
def oldVersion = "$major.$minor.$patch$suffix"
patch++
def newVersion = "$major.$minor.$patch$suffix"
logger.info "Version parsed from Git: $oldVersion, incremented to $newVersion"
return newVersion
} else {
def newVersion = "$major.$minor.$patch$suffix"
logger.info "Version parsed from Git: $newVersion"
return newVersion
}
} catch (any) {
logger.warn "Could not parse version from tag \"$tag\""
return tag
}
}
if (project.ext.lwjglNatives.isEmpty()) println "WTF"
dependencies {
archs.each { arch ->
runtimeOnly "org.lwjgl:lwjgl::$arch"
runtimeOnly "org.lwjgl:lwjgl-glfw::$arch"
runtimeOnly "org.lwjgl:lwjgl-openal::$arch"
runtimeOnly "org.lwjgl:lwjgl-opengl::$arch"
runtimeOnly "org.lwjgl:lwjgl-stb::$arch"
Tag version_findRelevantTag(Grgit git) {
def tags = git.tag.list()
def commits = [ git.head() ]
def visited = new HashSet<>()
while (true) {
if (commits.isEmpty()) return null
def nextCommits = new HashSet<>()
def formatSpecificationPrinted = false
for (def commit : commits) {
def tag = tags.findAll { it.commit == commit } ?.max { it.dateTime }
if (tag != null) {
if (tag.name ==~ tagFormat) {
return tag
} else {
if (!formatSpecificationPrinted) {
formatSpecificationPrinted = true
logger.info 'Expecting tag format: vMAJOR.MINOR.PATCH[-SUFFIX]'
}
logger.info 'Ignoring tag due to invalid format: {}', tag.name
}
}
nextCommits.addAll commit.parentIds.collect(git.resolve.&toCommit)
}
visited.addAll commits
nextCommits.removeAll visited
commits = nextCommits
}
}
compileJava.mustRunAfter addNativeDependencies // Make sure runtimeOnly has not been resolved
task requestLinuxDependencies {
description 'Adds linux, linux-arm64 and linux-arm32 native libraries to built artifacts.'
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()))
}
/*
* Manifest specification
*/
task specifyLocalManifest {
dependsOn addNativeDependencies // Make sure all native dependencies are specified
task resolveVersion {
description 'Resolves version information from Git repository or project properties.'
doFirst {
def classPath = []
configurations.runtimeClasspath.each {
if (isDependencyRequested(it.getName())) {
classPath.add("lib/" + it.getName())
try {
def git = Grgit.open(dir: project.projectDir)
project.ext.commit = git.head().id
project.ext.branch = git.branch.current().name
if (project.version != 'unspecified') {
// Leave version as-is
return
}
def tag = version_findRelevantTag(git)
if (tag == null) {
String suffix
if (project.hasProperty('buildId')) {
suffix = project.buildId;
} else {
suffix = java.time.ZonedDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern('yyyy_MM_dd'))
}
project.version = "999.0.0-$suffix"
logger.warn 'Git repository does not contain an applicable tag, using dummy version {}\nSpecify version with -Pversion=1.2.3 or create a Git tag named v1.2.3', project.version
} else {
println "\tRemoving from JAR classpath (not requested): " + it.getName()
project.version = version_parseVersion(tag.name, tag.commit != git.head())
}
} catch (org.eclipse.jgit.errors.RepositoryNotFoundException e) {
if (project.version == 'unspecified') project.version = 'dev'
project.ext.commit = '-'
project.ext.branch = '-'
logger.warn 'No Git repository found in project root, using dummy version {}\nSpecify version with -Pversion=1.2.3 or create a Git tag named v1.2.3', project.version
}
if (classPath.size() == configurations.runtimeClasspath.size()) {
println "Nothing removed from JAR classpath"
}
jar {
manifest {
attributes(
"Main-Class": "ru.windcorp.progressia.client.ProgressiaClientMain",
"Class-Path": configurations.runtimeClasspath.collect { "lib/" + it.getName() } .findAll { isDependencyRequested(it) } .join(' ')
)
}
}
doLast {
if (!project.hasProperty('buildId')) {
project.ext.buildId = '-'
}
}
}
jar.dependsOn specifyLocalManifest
/*
* Library export
* Configure JAR manifest
*/
task configureManifest {
description 'Populates JAR manifest with Main-Class, Class-Path and version metadata.'
jar.dependsOn configureManifest
dependsOn resolveVersion
doFirst {
jar.manifest.attributes(
'Main-Class': 'ru.windcorp.progressia.client.ProgressiaClientMain',
'Class-Path': configurations.runtimeClasspath.collect { "lib/${it.name}" } .join(' '),
'Specification-Title': 'Progressia',
'Implementation-Title': 'Progressia',
'Implementation-Version': project.version,
'Implementation-Version-Git-Commit': project.commit,
'Implementation-Version-Git-Branch': project.branch,
'Implementation-Version-BuildId': project.buildId,
)
}
}
/*
* Copy libraries into buil/libs/lib directory, next to Progressia.jar
*/
task exportLibs(type: Sync) {
mustRunAfter addNativeDependencies
description 'Copies runtime libraries into a subdirectory next to the output JAR.'
jar.dependsOn exportLibs
into libsDirectory.get().getAsFile().getPath() + "/lib"
exclude { !isDependencyRequested(it.getName()) }
from configurations.runtimeClasspath
into 'build/libs/lib'
}
jar.dependsOn(exportLibs)
/*
* Packaging
* Apply LWJGL logic
*/
apply from: 'build_logic/lwjgl.gradle'
/*
* Packaging working directory configuration
*/
task packageDebian(type: Exec) {
description 'Builds the project and creates a Debain package.'
group 'Progressia'
dependsOn build
dependsOn requestLinuxDependencies
commandLine './buildPackages.sh', 'debian'
import java.nio.file.*
import java.nio.file.attribute.*
task createPackagingDirs() {
description 'Resets build/tmp/packaging directory.'
doLast {
println "Debian package available in build_packages/"
def tmpDir = buildDir.toPath().resolve 'tmp/packaging'
def nuke = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
if (e == null) {
Files.delete(dir);
return FileVisitResult.CONTINUE;
} else {
// directory iteration failed
throw e;
}
}
}
// Fckn nuke tmpDir from orbit
// I'm so done with deleting file trees in Java/Groovy/whatever
// ...Not using File.deleteDir() because the latter recurses into symlinks, and we don't want to wipe build/libs/lib
if (Files.exists(tmpDir)) {
Files.walkFileTree tmpDir, nuke
}
Files.createDirectories tmpDir.resolve('workingDir')
Files.createDirectories buildDir.toPath().resolve('packages')
}
}
task linkBuildOutputForPackaging() {
description 'Symlinks the contents of build/libs into packaging working directory.'
dependsOn build
dependsOn createPackagingDirs
onlyIf { preparePackaging.ext.mode == 'symlink' }
doLast {
def from = buildDir.toPath().resolve 'libs'
def into = buildDir.toPath().resolve "tmp/packaging/workingDir/${preparePackaging.ext.buildDest}"
Files.createDirectories into
Files.list(from).each {
def fileName = it.fileName.toString()
// Exclude all JARs except the current one
if (fileName ==~ "${project.name}.*\\.jar" && fileName != tasks.jar.archiveFileName.get())
return
Files.createSymbolicLink into.resolve(it.fileName), it
}
}
}
task copyBuildOutputForPackaging(type: Copy) {
description 'Copies the contents of build/libs into packaging working directory.'
dependsOn build
dependsOn createPackagingDirs
onlyIf { preparePackaging.ext.mode == 'copy' }
from 'build/libs'
filesMatching("${project.name}*.jar") {
include tasks.jar.archiveFileName.get()
}
into "build/tmp/packaging/workingDir/${ -> preparePackaging.ext.buildDest}"
}
task preparePackaging {
preparePackaging.ext.buildDest = ''
preparePackaging.ext.mode = 'symlink'
dependsOn createPackagingDirs
dependsOn linkBuildOutputForPackaging
dependsOn copyBuildOutputForPackaging
}
/*
* Apply all packaging scripts
*/
new File(projectDir, 'build_logic/packaging').list().each {
apply from: "build_logic/packaging/$it/script.gradle"
}
/*
* Ensure no more than one packaging task is scheduled
*/
gradle.taskGraph.whenReady { graph ->
if (graph.allTasks.count { it.name ==~ /package[^_]*/ } > 1) {
def offenders = graph.allTasks.findAll { it.name ==~ /package[^_]*/ }
throw new GradleException("Cannot execute multiple package tasks within a single build\n" +
"\tOffending tasks: $offenders")
}
}
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/"
}
}
/*
* Convenience build tasks
*/
task buildCrossPlatform {
description 'Builds the project including native libraries for all available platforms.'
@ -305,17 +391,17 @@ task buildCrossPlatform {
dependsOn build
doLast {
println "Native libraries for all platforms have been added"
logger.info 'Native libraries for all platforms have been added'
}
}
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 (${lwjgl.localArch})."
group 'Progressia'
dependsOn build
doLast {
println "Native libraries only for platform $lwjglNatives have been added"
logger.info "Native libraries only for platform ${lwjgl.localArch} have been added"
}
}

View File

@ -1,191 +0,0 @@
#!/bin/bash
#
# Progressia
# Copyright (C) 2020-2021 Wind Corporation and contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
echoerr() { echo "$@" 1>&2; }
buildDebianPackage() {
# Commands that must be available to execute this action
requiredCommands='dpkg-deb fakeroot'
# Package name. Sync with control file manually!
name='progressia-techdemo'
# Version that the package will receive. Sync with control file manually!
version='1.0_all'
# This directory will be copied into $tmpDir
templateDirectory="build_packages/DEB/template"
# Files that must be present
requiredFiles="$templateDirectory/DEBIAN/control"
nameAndVersion="$name-$version"
tmpDir="build_packages/DEB/$nameAndVersion"
outputFile="build_packages/DEB/$nameAndVersion.deb"
echo "Checking environment to build Debian package"
for item in $requiredCommands; do
if command -v "$item" &> /dev/null; then
echo "- $item found"
else
echoerr "Command $item not found, cannot package"
exit 100
fi
done
for file in $requiredFiles; do
if ! [ -r "$file" ]; then
echoerr "$file is missing or not readable, cannot package"
exit 101
else
echo "- $file is present and readable"
fi
done
echo "Environment OK; packaging Debian package"
exitCode=0
{
shareDir="$tmpDir/usr/share/progressia"
mkdir -p "$tmpDir" &&
mkdir -p "$shareDir" &&
cp -r "$templateDirectory"/* "$tmpDir" &&
cp -r 'build/libs/lib' "$shareDir/lib" &&
cp 'build/libs/Progressia.jar' "$shareDir/Progressia.jar" &&
echo "------ DPKG-DEB ------" &&
fakeroot dpkg-deb --build "$tmpDir" &&
echo "---- DPKG-DEB END ----" &&
mv "$outputFile" build_packages
} || {
echoerr "Could not create Debian package"
exitCode=1
}
{
if [ -d "$tmpDir" ]; then
rm -r "$tmpDir"
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' &&
cp 'LICENSE' 'build_packages/NSIS/LICENSE.txt' &&
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
if [ -e 'build_packages/NSIS/LICENSE.txt' ]; then
rm 'build_packages/NSIS/LICENSE.txt'
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

117
build_logic/lwjgl.gradle Normal file
View File

@ -0,0 +1,117 @@
/*
* Build logic for Progressia
* LWJGL dependency logic
*/
project.ext.lwjgl = new HashMap<>()
// Version of LWJGL
lwjgl.version = '3.2.3'
/*
* Target platforms for current operation.
* This is filled in by the request* tasks. This is referenced by the addLwjglNatives task.
* When empty, current platform is assumed.
*/
lwjgl.targets = new HashSet<>()
// LWJGL components. To include org.lwjgl:lwjgl-foobar, add 'foobar' to this list.
lwjgl.libraries = [
'opengl',
'glfw',
'openal',
'stb'
]
// Determine the architecture of the build environment
import org.gradle.internal.os.OperatingSystem
switch (OperatingSystem.current()) {
case OperatingSystem.LINUX:
def osArch = System.getProperty('os.arch')
lwjgl.localArch = osArch.startsWith('arm') || osArch.startsWith('aarch64')
? "linux-${osArch.contains('64') || osArch.startsWith('armv8') ? 'arm64' : 'arm32'}"
: 'linux'
break
case OperatingSystem.MAC_OS:
lwjgl.localArch = 'macos'
break
case OperatingSystem.WINDOWS:
lwjgl.localArch = System.getProperty('os.arch').contains('64') ? 'windows' : 'windows-x86'
break
}
// Declare pure-Java dependencies
dependencies {
// BOM
implementation platform("org.lwjgl:lwjgl-bom:${lwjgl.version}")
// Core
implementation 'org.lwjgl:lwjgl'
// Components
lwjgl.libraries.each { implementation "org.lwjgl:lwjgl-$it" }
}
/*
* Adds LWJGL native libraries to runtimeOnly configuration
*/
task lwjgl_addNativesToRuntimeOnly {
// Make sure runtimeOnly has not been resolved
compileJava.dependsOn lwjgl_addNativesToRuntimeOnly
configureManifest.dependsOn lwjgl_addNativesToRuntimeOnly
exportLibs.dependsOn lwjgl_addNativesToRuntimeOnly
doFirst {
if (project.hasProperty('forceTargets')) {
try {
def oldTargets = lwjgl.targets.join(',')
lwjgl.targets.clear()
lwjgl.targets.addAll project.forceTargets.split(',')*.trim().collect { it == 'local' ? lwjgl.localArch : it }
logger.info 'Overriding selected platforms {} with {}', oldTargets, lwjgl.targets.join(',')
} catch (Exception e) {
throw new GradleException("Could not parse forceTargets \"${project.forceTargets}\", expecting platform-1,platform-2,local", e)
}
}
if (lwjgl.targets.isEmpty()) {
logger.info 'Adding LWJGL native dependencies for local platform only: {}', lwjgl.localArch
lwjgl.targets.add lwjgl.localArch
} else {
logger.info 'Adding LWJGL native dependencies for platforms: {}', lwjgl.targets.sort().join(', ')
}
dependencies {
lwjgl.targets.each { target ->
runtimeOnly "org.lwjgl:lwjgl::natives-$target"
lwjgl.libraries.each { lib ->
runtimeOnly "org.lwjgl:lwjgl-$lib::natives-$target"
}
}
}
}
}
task requestCrossPlatformDependencies {
description 'Adds LWJGL natives for all available platforms.'
lwjgl_addNativesToRuntimeOnly.mustRunAfter requestCrossPlatformDependencies
}
def requestTask(String name, String... targets) {
def theTask = task "request${name}Dependencies"
theTask.doFirst {
lwjgl.targets.addAll targets
}
theTask.description "Adds LWJGL natives for $name (${targets.join(', ')})."
requestCrossPlatformDependencies.dependsOn theTask
lwjgl_addNativesToRuntimeOnly.mustRunAfter theTask
}
requestTask 'Linux', 'linux', 'linux-arm32', 'linux-arm64'
requestTask 'Windows', 'windows', 'windows-x86'
requestTask 'MacOS', 'macos'

View File

@ -0,0 +1,38 @@
task packageDeb_processResources(type: Copy) {
dependsOn resolveVersion
dependsOn preparePackaging
from 'src/packaging/deb'
filesMatching('DEBIAN/control') {
expand(version: { -> project.version})
}
into 'build/tmp/packaging/workingDir'
}
task packageDeb_configure() {
preparePackaging.mustRunAfter packageDeb_configure
doLast {
tasks.preparePackaging.ext.buildDest = '/usr/share/progressia'
tasks.preparePackaging.ext.mode = 'copy'
}
}
task packageDeb(type: Exec) {
description 'Builds the project and creates a Debian package.'
group 'Progressia'
dependsOn packageDeb_configure
dependsOn requestLinuxDependencies
dependsOn build
dependsOn preparePackaging
dependsOn packageDeb_processResources
executable 'dpkg-deb'
args '--root-owner-group'
args '--build', 'build/tmp/packaging/workingDir'
args 'build/packages'
}

View File

@ -0,0 +1,50 @@
task packageNsis_processResources(type: Copy) {
dependsOn preparePackaging
from ('src/packaging/nsis') {
exclude 'left_side.png'
}
from('LICENSE') {
rename 'LICENSE', 'LICENSE.txt'
}
into 'build/tmp/packaging/workingDir'
}
task packageNsis_generateIcon(type: Exec) {
mustRunAfter preparePackaging
executable 'convert'
args files('src/main/resources/assets/icons/*.original.png').files*.path
args 'build/tmp/packaging/workingDir/logo.ico'
}
task packageNsis_generateLeftSide(type: Exec) {
mustRunAfter preparePackaging
executable 'convert'
args 'src/packaging/nsis/left_side.png'
args '-alpha', 'off'
args 'BMP3:build/tmp/packaging/workingDir/left_side.bmp'
}
task packageNsis(type: Exec) {
description 'Builds the project and creates a Windows NSIS installer.'
group 'Progressia'
dependsOn requestWindowsDependencies
dependsOn build
dependsOn resolveVersion
dependsOn preparePackaging
dependsOn packageNsis_processResources
dependsOn packageNsis_generateIcon
dependsOn packageNsis_generateLeftSide
executable 'makensis'
args '-NOCONFIG'
args "-DPROJECT_NAME=${project.name}"
args "-DPROJECT_VERSION=${ -> project.version}"
args "-DMAIN_JAR_FILE=${ -> project.tasks.jar.archiveFileName.get()}"
args "-DOUTPUT_DIR=${project.buildDir.absolutePath}/packages"
args 'build/tmp/packaging/workingDir/config.nsi'
}

View File

@ -0,0 +1,41 @@
task packageZip_processResources(type: Copy) {
dependsOn preparePackaging
from ('src/packaging/zip') {
filesMatching('start.*') {
filter(
org.apache.tools.ant.filters.ReplaceTokens,
tokens: [mainJarFile: project.tasks.jar.archiveFileName.get()]
)
}
}
from ('src/main/resource/assets/icons/logo256.original.png') {
rename 'logo256.original.png', 'logo.png'
}
from('LICENSE') {
rename 'LICENSE', 'LICENSE.txt'
}
into 'build/tmp/packaging/workingDir'
}
task packageZip(type: Zip) {
description 'Builds the project and creates a cross-platform ZIP package.'
group 'Progressia'
dependsOn resolveVersion
dependsOn requestCrossPlatformDependencies
dependsOn build
dependsOn preparePackaging
dependsOn packageZip_processResources
archiveBaseName = project.name
archiveAppendix = 'universal'
doFirst {
archiveVersion = project.version
}
from 'build/tmp/packaging/workingDir'
destinationDirectory = file('build/packages')
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

View File

@ -1,8 +1,10 @@
# Build Guide
This document is a guide to building Progressia from source.
This document is a guide to building Progressia from source. For quick reference, see
[Build Script Reference](BuildScriptReference.md).
Compilation should be possible on all platforms that support JDK 8 or later, however, packaging scripts require Bash.
Compilation should be possible on all platforms that support JDK 8 or later, however, packaging scripts require
additional programs in `PATH`.
This guide assumes you are familiar with using a terminal or Windows Command Prompt or PowerShell.
@ -150,54 +152,46 @@ 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`.
A universal ZIP distribution, a Debian package and a Windows NSIS installer may be created automatically by the build
script.
### Creating a universal ZIP package
A universal cross-platform ZIP archive can be created with the following Gradle task:
```
./gradlew packageZip
```
Gradle will then build all artifacts necessary to run the game on all available platforms and package game files,
libraries, launch scripts, etc. into a compressed ZIP archive.
The resulting file can be found in `build/packages/`
### Creating a Debian package
A Debian package can be created with the following Gradle task:
```
./gradlew packageDebian
./gradlew packageDeb
```
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.
`dpkg-deb`. Commands `dpkg-deb` 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:
A Windows NSIS installer can be created with the following Gradle task:
```
./gradlew packageWindows
./gradlew packageNsis
```
Gradle will then build all artifacts necessary to run the game on Windows (both x64 and x86 architectures) and invoke
`./buildPackages.sh windows`.
`makensis`.
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.
Windows installers are implemented with [NSIS](https://nsis.sourceforge.io/). [ImageMagick](https://imagemagick.org),
a command-line image editing tool, is used to generate some assets for the installer. Commands `makensis` and
`convert` (from ImageMagick) must be available in system path in order to build the installer.

View File

@ -0,0 +1,103 @@
# Build Script Reference
This document is a user's reference for the build script of Progressia. For a beginner-friendly guide, see
[Build Guide](BuildGuide.md).
## 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.
- `packageZip` creates a universal ZIP. Incompatible with other `package` tasks.
- `packageDeb` creates a Debian package. Incompatible with other `package` tasks.
- `packageNsis` creates a Windows NSIS installer. Incompatible with other `package` tasks.
- `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.
To execute a task, run `./gradlew <task-name>`.
`build`-type tasks output the executable JAR and all libraries required at runtime into `build/libs`. `package`-type
tasks output packages into `build/packages`.
## Packaging tasks
Some packaging tasks require additional software in `PATH`.
| Task | Commands required in `PATH` |
|---------------|------------------------------------------|
| `packageDeb` | `dpkg-deb` |
| `packageZip` | _none_ |
| `packageNsis` | `makensis`, `convert` (from ImageMagick) |
## Version and metadata
### Version scheme
Progressia builds are identified by four parameters: version, Git commit, Git branch and build ID.
Versions roughly follow [semantic versioning](https://semver.org/spec/v2.0.0.html), with each version fitting the
`MAJOR.MINOR.PATCH[-SUFFIX]` pattern. Depending on the build environment (see below), version is either "real" with
no metadata (e.g. `0.43.2` or `1.2.1-beta`) or a dummy fallback with build metadata (e.g. `999.0.0-2021_07_23` or
`999.0.0-WJ3`).
### Version detection
Build script considers three scenarios when determining the version:
1. `version` project property is set explicitly. This may be done in a variety of ways, for example with command line
argument `-Pversion=1.2.3`
(see [Gradle docs](https://docs.gradle.org/current/userguide/build_environment.html#sec:project_properties))
2. Local Git repository is found, and HEAD is tagged appropriately: version is the tag name with leading `v`
stripped. Example: `v1.2.3` is version `1.2.3`
3. Local Git repository is found, and some ancestor of HEAD is tagged appropriately: version is the tag name with
leading `v` stripped and PATCH incremented by one. Example: `v1.2.3` is version `1.2.4`
Tags not named like `vMAJOR.MINOR.PATCH[-SUFFIX]` are ignored for cases 2 and 3.
In all other cases, a fallback dummy value is used for version, appended with build ID or current date.
### Git metadata
Git commit and Git branch are correspond to the state of the local Git repository, if any. In case Git metadata is
unavailable, `-` fallback is used for both fields.
### Build ID
Build ID uniquely identifies artifacts produced by automated build systems. For example, builds executed by WindCorp
Jenkins suite have build IDs like `WJ3` or `WJ142`. Build ID must be provided explicitly; it is `-` unless specified
otherwise.
Build ID may be set with `buildId` project property. This may be done in a variety of ways, for example with command
line argument `-PbuildId=WJ3`
(see [Gradle docs](https://docs.gradle.org/current/userguide/build_environment.html#sec:project_properties)).
## Native libraries
LWJGL uses native libraries. Build script declares platform-specific dependencies based on the set of target
platforms, `project.ext.lwjgl.targets` (aka `lwjgl.targets`). These dependencies are added to `runtimeOnly`
configuration.
When this set is empty, the script selects natives for current platform. Otherwise, all platforms in the set are
included.
`lwjgl.targets` is populated automatically by packaging tasks and by `buildCrossPlatform`. To add extra targets,
``requestXxxDependencies` tasks may be used.
Target selection mechanism may be overridden with `forceTargets` project property. This may be done in a variety of
ways, for example with command line argument `-PforceTargets=windows-x86,local`
(see [Gradle docs](https://docs.gradle.org/current/userguide/build_environment.html#sec:project_properties)). The
value is a comma-separated list of target architectures. `local` target will be replaced with the automatically
detected current architecture.
### Available targets
| Name | Task |
|---------------|------------------------------|
| `linux` | `requestLinuxDependencies` |
| `linux-arm32` | `requestLinuxDependencies` |
| `linux-arm64` | `requestLinuxDependencies` |
| `windows` | `requestWindowsDependencies` |
| `windows-x86` | `requestWindowsDependencies` |
| `macos` | `requestMacOSDependencies` |

1
logs/game.log Normal file
View File

@ -0,0 +1 @@
22:26:25.948 [Music Thread ] WARN ru.windcorp.progressia.test.TestMusicPlayer > No music found

View File

@ -15,9 +15,180 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import org.apache.logging.log4j.LogManager;
import ru.windcorp.progressia.common.util.crash.CrashReports;
/**
* A class providing access to build metadata.
*/
public class Progressia {
private static final String NAME = "Progressia";
private static String version;
private static String gitCommit;
private static String gitBranch;
private static String buildId;
static {
try {
Manifest manifest = findManifest();
if (manifest == null) {
setDevelopmentMetadata();
LogManager.getLogger().info(
"Manifest with Specification-Title not found. "
+ "Either you are in a development environment or something has gone horribly wrong with classloaders."
);
} else {
fillMetadata(manifest);
}
} catch (Throwable t) {
CrashReports.crash(t, "Something went wrong while loading metadata");
}
}
private static Manifest findManifest() {
try {
Enumeration<URL> resources = Progressia.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
Collection<IOException> exceptions = new ArrayList<>();
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
try {
Manifest manifest = new Manifest(url.openStream());
Attributes mainAttributes = manifest.getMainAttributes();
if (NAME.equals(mainAttributes.getValue("Specification-Title"))) {
return manifest;
}
} catch (IOException e) {
exceptions.add(e);
}
}
if (exceptions.isEmpty()) {
return null;
}
IOException scapegoat = null;
for (IOException e : exceptions) {
if (scapegoat == null) {
scapegoat = e;
} else {
scapegoat.addSuppressed(e);
}
}
throw CrashReports.report(scapegoat, "Could not read manifest");
} catch (IOException e) {
throw CrashReports.report(e, "Could not read manifest");
}
}
private static void setDevelopmentMetadata() {
version = "dev";
gitCommit = "-";
gitBranch = "-";
buildId = "-";
}
private static void fillMetadata(Manifest manifest) {
version = getAttributeOrCrash(manifest, "Implementation-Version");
gitCommit = getAttributeOrCrash(manifest, "Implementation-Version-Git-Commit");
gitBranch = getAttributeOrCrash(manifest, "Implementation-Version-Git-Branch");
buildId = getAttributeOrCrash(manifest, "Implementation-Version-BuildId");
}
private static String getAttributeOrCrash(Manifest manifest, String key) {
String result = manifest.getMainAttributes().getValue(key);
if (result == null) {
throw CrashReports.report(null, "Manifest exists but attribute " + key + " not found");
}
return result;
}
public static String getName() {
return NAME;
}
/**
* Returns the version of the game as a String. Version data is retrieved
* from a {@code META-INF/MANIFEST.MF} file located in the main JAR. Version
* format depends on way the game was built:
* <ul>
* <li><code>dev</code> if no matching manifest was found, e.g. when launching from an IDE</li>
* <li>The value of <code>Implementation-Version</code> specified in the manifest:
* <ul>
* <li>[Stage-]Major.Minor.Patch, e.g. <code>alpha-0.3.2</code> or <code>1.4.2</code>, for released versions</li>
* <li>BuildId, e.g. <code>WJ7</code>, for snapshots built by automation systems</li>
* <li>YYYY-MM-DD, e.g. <code>2021-12-32</code>, for snapshots built manually</li>
* </ul>
* </li>
* </ul>
*
* @return the version
*/
public static String getVersion() {
return version;
}
public static String getFullerVersion() {
if (isDefaultGitBranch() || "-".equals(gitBranch)) {
return version;
} else {
return String.format("%s/%s", version, gitBranch);
}
}
/**
* @return the buildId or <code>"-"</code>
*/
public static String getBuildId() {
return buildId;
}
/**
* @return the Git commit or <code>"-"</code>
*/
public static String getGitCommit() {
return gitCommit;
}
public static String getGitCommitShort() {
if (gitCommit == null || "-".equals(gitCommit)) {
return gitCommit;
}
return gitCommit.substring(0, Math.min(7, gitCommit.length()));
}
/**
* @return the Git branch or <code>"-"</code>
*/
public static String getGitBranch() {
return gitBranch;
}
public static boolean isDefaultGitBranch() {
return "master".equals(gitBranch) || "main".equals(gitBranch);
}
public static String getFullVersion() {
return String.format("%s/%s/%s/%s", version, gitBranch, getGitCommitShort(), buildId);
}
}

View File

@ -18,6 +18,8 @@
package ru.windcorp.progressia;
import org.apache.logging.log4j.LogManager;
import ru.windcorp.progressia.client.graphics.GUI;
import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer;
@ -32,6 +34,8 @@ public class ProgressiaLauncher {
public static void launch(String[] args, Proxy proxy) {
arguments = args.clone();
setupCrashReports();
LogManager.getRootLogger().info("Launching " + Progressia.getName() + " version " + Progressia.getFullVersion());
proxy.initialize();
ProgressiaLauncher.proxy = proxy;
@ -44,6 +48,7 @@ public class ProgressiaLauncher {
private static void setupCrashReports() {
// Context providers
CrashReports.registerProvider(new VersionProvider());
CrashReports.registerProvider(new OSContextProvider());
CrashReports.registerProvider(new RAMContextProvider());
CrashReports.registerProvider(new JavaVersionContextProvider());

View File

@ -15,20 +15,30 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.client.graphics.backend;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.system.MemoryUtil.*;
import java.io.IOException;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.opengl.GL;
import com.google.common.eventbus.Subscribe;
import ru.windcorp.progressia.Progressia;
import ru.windcorp.progressia.client.graphics.GUI;
import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent;
import ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.client.graphics.texture.TextureDataEditor;
import ru.windcorp.progressia.client.graphics.texture.TextureLoader;
import ru.windcorp.progressia.client.graphics.texture.TextureSettings;
import ru.windcorp.progressia.common.resource.Resource;
import ru.windcorp.progressia.common.resource.ResourceManager;
import ru.windcorp.progressia.common.util.crash.CrashReports;
class LWJGLInitializer {
@ -63,14 +73,20 @@ class LWJGLInitializer {
glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
long handle = glfwCreateWindow(900, 900, "ProgressiaTest", NULL, NULL);
long handle = glfwCreateWindow(
800,
600,
Progressia.getName() + " " + Progressia.getFullerVersion(),
NULL,
NULL
);
// TODO Check that handle != NULL
GraphicsBackend.setWindowHandle(handle);
glfwMakeContextCurrent(handle);
glfwSwapInterval(0); // TODO: remove after config system is added
glfwSwapInterval(0); // TODO: remove after config system is added
}
private static void positionWindow() {
@ -79,8 +95,30 @@ class LWJGLInitializer {
}
private static void createWindowIcons() {
// TODO Auto-generated method stub
if (glfwGetVersionString().toLowerCase().contains("wayland")) {
// glfwSetWindowIcon is not supported on Wayland
return;
}
final String prefix = "assets/icons/";
String[] sizes = ResourceManager.getResource(prefix + "logoSizes.txt").readAsString().split(" ");
try (GLFWImage.Buffer buffer = GLFWImage.malloc(sizes.length)) {
for (int i = 0; i < sizes.length; ++i) {
Resource resource = ResourceManager.getResource(prefix + "logo" + sizes[i].trim() + ".png");
TextureDataEditor icon = TextureLoader.loadPixels(resource, new TextureSettings(false, true));
buffer.position(i)
.width(icon.getContentWidth())
.height(icon.getContentHeight())
.pixels(icon.getData().getData());
}
glfwSetWindowIcon(GraphicsBackend.getWindowHandle(), buffer);
} catch (IOException e) {
throw CrashReports.report(e, "Could not load window icons");
}
}
private static void initializeOpenGL() {
@ -112,19 +150,19 @@ class LWJGLInitializer {
glfwSetScrollCallback(handle, InputHandler::handleWheelScroll);
GraphicsInterface.subscribeToInputEvents(new Object() {
@Subscribe
public void onFrameResized(FrameResizeEvent event) {
GUI.invalidateEverything();
}
@Subscribe
public void onInputEvent(InputEvent event) {
GUI.dispatchInput(event);
}
});
}
}

View File

@ -45,7 +45,7 @@ public class GNUUnifontLoader {
private static final AtlasGroup ATLAS_GROUP_GNU_UNIFONT = new AtlasGroup("GNUUnifont", 1 << 12);
private static final TextureSettings TEXTURE_SETTINGS = new TextureSettings(false);
private static final TextureSettings TEXTURE_SETTINGS = new TextureSettings(false, false);
private static final int BITS_PER_HEX_DIGIT = 4;
private static final int PREFIX_LENGTH = "0000:".length();

View File

@ -0,0 +1,28 @@
package ru.windcorp.progressia.client.graphics.gui;
import glm.mat._4.Mat4;
import glm.vec._3.Vec3;
import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
import ru.windcorp.progressia.client.graphics.texture.Texture;
public class Background extends GUILayer {
protected Texture backgroundTexture;
public Background(String name, Layout layout, Texture inTexture) {
super(name, layout);
backgroundTexture = inTexture;
}
@Override
protected void assemble(RenderTarget target) {
getRoot().setBounds(0, 0, getWidth(), getHeight());
getRoot().invalidate();
target.pushTransform(new Mat4(1).translate(new Vec3(0,0,500)));
target.drawTexture(0, 0, getWidth(), getHeight(), backgroundTexture);
target.popTransform();
getRoot().assemble(target);
}
}

View File

@ -23,6 +23,10 @@ import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
import ru.windcorp.progressia.client.graphics.font.Font;
import ru.windcorp.progressia.client.graphics.Colors;
/** Class for a traditional button that gets clicked to activate
*
* @author opfromthestart
*/
public class Button extends BasicButton {
public Button(String name, String label, Font labelFont) {
@ -51,9 +55,7 @@ public class Button extends BasicButton {
// Inside area
if (isPressed()) {
// Do nothing
} else {
if (!isPressed()) {
Vec4 backgroundColor;
if (isHovered() && isEnabled()) {
backgroundColor = Colors.HOVER_BLUE;

View File

@ -0,0 +1,23 @@
package ru.windcorp.progressia.client.graphics.gui;
import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
import ru.windcorp.progressia.client.graphics.texture.Texture;
public class TextureComponent extends Component {
private final Texture texture;
public TextureComponent(String name, Texture texture2) {
super(name);
texture = texture2;
setPreferredSize(texture.getSprite().getWidth(),texture.getSprite().getHeight());
}
@Override
protected void assembleSelf(RenderTarget target)
{
target.drawTexture(getX(), getY(), getWidth(), getHeight(), texture);
}
}

View File

@ -27,8 +27,8 @@ import ru.windcorp.progressia.client.graphics.gui.Layout;
public class LayoutAlign implements Layout {
private final int margin;
private double alignX, alignY;
protected final int margin;
protected double alignX, alignY;
public LayoutAlign(double alignX, double alignY, int margin) {
this.alignX = alignX;
@ -72,7 +72,7 @@ public class LayoutAlign implements Layout {
Vec2i result = new Vec2i(0, 0);
c.getChildren().stream()
.map(child -> child.getPreferredSize())
.map(Component::getPreferredSize)
.forEach(size -> {
result.x = max(size.x, result.x);
result.y = max(size.y, result.y);

View File

@ -0,0 +1,56 @@
package ru.windcorp.progressia.client.graphics.gui.layout;
import glm.vec._2.i.Vec2i;
import ru.windcorp.progressia.client.graphics.gui.Component;
import ru.windcorp.progressia.client.graphics.gui.Layout;
import static java.lang.Math.max;
import static java.lang.Math.min;
public class LayoutEdges implements Layout {
private final int margin;
public LayoutEdges(int margin) {
this.margin = margin;
}
@Override
public void layout(Component c) {
for (int i=0;i<2;i++)
{
Component child = c.getChild(i);
Vec2i size = child.getPreferredSize();
int cWidth = c.getWidth() - 2 * margin;
int cHeight = c.getHeight() - 2 * margin;
size.x = min(size.x, cWidth);
size.y = min(size.y, cHeight);
if (i==0) {
child.setBounds(
c.getX() + margin,
c.getY(),
size
);
} else {
child.setBounds(
1920 - size.x - margin,
c.getY(),
size
);
}
}
}
@Override
public Vec2i calculatePreferredSize(Component c) {
Vec2i result = new Vec2i(1920,0);
c.getChildren().stream()
.map(Component::getPreferredSize)
.forEach(size -> result.y = max(Math.abs(size.y), result.y));
return result;
}
}

View File

@ -163,7 +163,7 @@ public class Atlases {
}
}
private static final TextureSettings SETTINGS = new TextureSettings(false);
private static final TextureSettings SETTINGS = new TextureSettings(false, false);
private static final Map<Resource, Sprite> LOADED = new HashMap<>();
private static final Multimap<AtlasGroup, Atlas> ATLASES = MultimapBuilder.hashKeys().arrayListValues().build();

View File

@ -28,7 +28,7 @@ import ru.windcorp.progressia.common.util.crash.CrashReports;
public class SimpleTextures {
private static final TextureSettings SETTINGS = new TextureSettings(false);
private static final TextureSettings SETTINGS = new TextureSettings(false, false);
private static final Map<Resource, Texture> TEXTURES = new HashMap<>();

View File

@ -23,7 +23,7 @@ import static org.lwjgl.opengl.GL12.*;
import java.nio.ByteBuffer;
class TextureData {
public class TextureData {
private final ByteBuffer data;

View File

@ -41,9 +41,17 @@ public class TextureLoader {
int width = readResult.getWidth();
int height = readResult.getHeight();
int bufferWidth;
int bufferHeight;
int bufferWidth = BinUtil.roundToGreaterPowerOf2(width);
int bufferHeight = BinUtil.roundToGreaterPowerOf2(height);
if (settings.allocateExactBuffer()) {
bufferWidth = width;
bufferHeight = height;
} else {
bufferWidth = BinUtil.roundToGreaterPowerOf2(width);
bufferHeight = BinUtil.roundToGreaterPowerOf2(height);
}
WritableRaster raster = TextureUtil.createRaster(
bufferWidth,

View File

@ -21,13 +21,19 @@ package ru.windcorp.progressia.client.graphics.texture;
public class TextureSettings {
private final boolean isFiltered;
private final boolean allocateExactBuffer;
public TextureSettings(boolean isFiltered) {
public TextureSettings(boolean isFiltered, boolean allocateExactBuffer) {
this.isFiltered = isFiltered;
this.allocateExactBuffer = allocateExactBuffer;
}
public boolean isFiltered() {
return isFiltered;
}
public boolean allocateExactBuffer() {
return allocateExactBuffer;
}
}

View File

@ -42,7 +42,7 @@ public class EntityRenderRegistry extends NamespacedInstanceRegistry<EntityRende
ResourceManager.getTextureResource(
"entities/" + name
),
new TextureSettings(false)
new TextureSettings(false, false)
).getData()
);
} catch (IOException e) {

View File

@ -0,0 +1,40 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.common.util.crash.providers;
import java.util.Map;
import ru.windcorp.progressia.Progressia;
import ru.windcorp.progressia.common.util.crash.ContextProvider;
public class VersionProvider implements ContextProvider {
@Override
public void provideContext(Map<String, String> output) {
output.put("Version", Progressia.getVersion());
output.put("Git commit", Progressia.getGitCommit());
output.put("Git branch", Progressia.getGitBranch());
output.put("Build ID", Progressia.getBuildId());
}
@Override
public String getName() {
return "Version Provider";
}
}

View File

@ -43,10 +43,8 @@ public class Region {
private static final boolean RESET_CORRUPTED = true;
public int loadedChunks;
private AtomicBoolean isUsing = new AtomicBoolean(false);
private AtomicBoolean isClosed = new AtomicBoolean(false);
private final AtomicBoolean isUsing = new AtomicBoolean(false);
private final AtomicBoolean isClosed = new AtomicBoolean(false);
private final RegionFile file;
@ -60,6 +58,7 @@ public class Region {
} catch (IOException e) {
RegionWorldContainer.LOG.debug("Uh the file broke");
RegionWorldContainer.LOG.debug(e.getLocalizedMessage());
if (RESET_CORRUPTED) {
this.file.makeHeader(regionCoords);
}
@ -132,7 +131,7 @@ public class Region {
DecodingException {
isUsing.set(true);
int dataOffset = 0;
int dataOffset;
Vec3i pos = RegionWorldContainer.getInRegionCoords(chunkPos);
if (hasOffset(pos)) {

View File

@ -26,9 +26,9 @@ public class RegionFile {
private static final int ID_HEADER_SIZE = 16;
private static final byte[] HEADER_ID = {'P','R','O','G'};
final byte endBytes[] = new byte[SECTOR_SIZE];
final byte[] endBytes = new byte[SECTOR_SIZE];
public static enum SectorType {
public enum SectorType {
Ending(0), // Just an empty block
Data(1), // has a byte counting up in position 1, and then
PartitionLink(2),
@ -54,7 +54,7 @@ public class RegionFile {
public void confirmHeaderHealth(ChunkMap<Integer> offsets, Vec3i regionCoords) throws IOException {
Set<Integer> used = new HashSet<Integer>();
Set<Integer> used = new HashSet<>();
int maxUsed = 0;
final int chunksPerRegion = REGION_DIAMETER * REGION_DIAMETER * REGION_DIAMETER;
@ -63,9 +63,10 @@ public class RegionFile {
}
char prog;
byte prog;
file.seek(0);
for (int i=0;i<4;i++) {
prog = file.readChar();
prog = file.readByte();
if (prog != HEADER_ID[i])
{
throw new IOException("File is not a .progressia_chunk file");
@ -109,7 +110,7 @@ public class RegionFile {
throw new IOException("A sector is used twice");
}
file.seek(HEADER_SIZE + SECTOR_SIZE * offset);
file.seek(HEADER_SIZE + (long) SECTOR_SIZE * offset);
byte type = file.readByte();
if (type == SectorType.Data.data) {
@ -131,25 +132,26 @@ public class RegionFile {
}
public void makeHeader(Vec3i regionCoords) throws IOException {
file.seek(0);
for (int i = 0; i < HEADER_SIZE; i++) {
file.write(0);
}
file.seek(0);
file.write(HEADER_ID);
file.writeInt(regionCoords.x);
file.writeInt(regionCoords.y);
file.writeInt(regionCoords.z);
for (int i = 0; i < HEADER_SIZE; i++) {
file.write(0);
}
}
public void writeBuffer(byte[] buffer, int dataOffset, Vec3i pos) throws IOException {
file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset);
file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset);
int loc = 0;
byte tempBuffer[] = new byte[SECTOR_SIZE];
byte[] tempBuffer = new byte[SECTOR_SIZE];
byte counter = 0;
boolean isDone = false;
while (!isDone) {
if (file.length() > HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1)) {
file.seek(HEADER_SIZE + SECTOR_SIZE * (dataOffset + 1));
if (file.length() > HEADER_SIZE + (long) SECTOR_SIZE * (dataOffset + 1)) {
file.seek(HEADER_SIZE + (long) SECTOR_SIZE * (dataOffset + 1));
byte header = file.readByte();
if (header == SectorType.Data.data) {
byte fileCounter = file.readByte();
@ -157,7 +159,7 @@ public class RegionFile {
// partition place
{
int newOffset = allocateEmptySector();
file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset);
file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset);
file.write(2);
file.writeInt(newOffset);
dataOffset = newOffset;
@ -179,7 +181,7 @@ public class RegionFile {
if (file.getFilePointer() < 256)
LogManager.getLogger("Region")
.debug("at {}, ({},{},{}), {}", file.getFilePointer(), pos.x, pos.y, pos.z, dataOffset);
file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset);
file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset);
dataOffset++;
file.write(tempBuffer);
}
@ -197,7 +199,7 @@ public class RegionFile {
file.seek(definitionOffset);
file.writeInt(dataOffset + 1);
file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE);
file.setLength(HEADER_SIZE + (long) dataOffset * SECTOR_SIZE);
return dataOffset;
}
@ -206,17 +208,17 @@ public class RegionFile {
int dataOffset = (int) Math.ceil((double) (outputLen - HEADER_SIZE) / SECTOR_SIZE);
file.setLength(HEADER_SIZE + dataOffset * SECTOR_SIZE);
file.setLength(HEADER_SIZE + (long) dataOffset * SECTOR_SIZE);
return dataOffset;
}
public byte[] readBuffer(int dataOffset) throws IOException {
file.seek(HEADER_SIZE + SECTOR_SIZE * dataOffset);
file.seek(HEADER_SIZE + (long) SECTOR_SIZE * dataOffset);
int bufferPos = 0;
byte buffer[] = new byte[SECTOR_SIZE * 16];
byte tempBuffer[] = new byte[SECTOR_SIZE];
byte[] buffer = new byte[SECTOR_SIZE * 16];
byte[] tempBuffer = new byte[SECTOR_SIZE];
boolean reachedEnd = false;
byte counter = 0;
@ -229,31 +231,24 @@ public class RegionFile {
if (tempBuffer[0] == SectorType.Data.data) {
if (tempBuffer[1] != counter) {
throw new IOException(
"Sectors were read out of order\nExpected chunk number " + Byte.toString(counter)
+ " but encountered number " + Byte.toString(tempBuffer[1])
"Sectors were read out of order\nExpected chunk number " + counter
+ " but encountered number " + tempBuffer[1]
);
}
counter++;
if (buffer.length - bufferPos < SECTOR_SIZE - SECTOR_HEADER_SIZE - 1) {
byte newBuffer[] = new byte[buffer.length + SECTOR_SIZE * 16];
for (int i = 0; i < buffer.length; i++) // TODO dedicated
// copy, java-y at
// least
{
newBuffer[i] = buffer[i];
}
byte[] newBuffer = new byte[buffer.length + SECTOR_SIZE * 16];
System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
buffer = newBuffer;
}
for (int i = 0; i < SECTOR_SIZE - SECTOR_HEADER_SIZE - 1; i++) {
buffer[bufferPos + i] = tempBuffer[i + 2];
}
System.arraycopy(tempBuffer, 2, buffer, bufferPos, SECTOR_SIZE - SECTOR_HEADER_SIZE - 1);
bufferPos += SECTOR_SIZE - SECTOR_HEADER_SIZE - 1;
} else if (tempBuffer[0] == SectorType.Ending.data) {
reachedEnd = true;
} else if (tempBuffer[0] == SectorType.PartitionLink.data) {
ByteBuffer intBuffer = ByteBuffer.wrap(tempBuffer);
int newOffset = intBuffer.getInt(1);
file.seek(HEADER_SIZE + SECTOR_SIZE * newOffset);
file.seek(HEADER_SIZE + (long) SECTOR_SIZE * newOffset);
} else {
throw new IOException("Invalid sector ID.");
}

View File

@ -0,0 +1,108 @@
package ru.windcorp.progressia.test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import glm.mat._4.Mat4;
import glm.vec._3.Vec3;
import glm.vec._4.Vec4;
import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
import ru.windcorp.progressia.client.graphics.gui.Component;
public class CubeComponent extends Component {
private final Mat4[] transforms;
private final Vec4[] normals;
private final long startTime;
private final double r3 = Math.sqrt(3+.01);
private final int size;
public CubeComponent(String name, int size) {
super(name);
this.size = size;
transforms = new Mat4[6];
normals = new Vec4[6];
setPreferredSize((int) Math.ceil(r3*size),(int) Math.ceil(r3*size));
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(this::requestReassembly, 1, 60, TimeUnit.MILLISECONDS);
startTime = System.currentTimeMillis();
}
// Notes to me
// z axis is through the screen
// y is horizontal spin
// x is vertical spin
private void computeTransforms()
{
//Creates all of the sides
transforms[0] = new Mat4(1);
transforms[1] = new Mat4(1);
transforms[2] = new Mat4(1);
transforms[3] = new Mat4(1);
transforms[4] = new Mat4(1);
transforms[5] = new Mat4(1);
//Gets time since creation(for rotation amount)
long time = System.currentTimeMillis()-startTime;
//Initializes the way each face is facing
normals[0] = new Vec4(0,0,-1,0);
normals[1] = new Vec4(0,1,0,0);
normals[2] = new Vec4(1,0,0,0);
normals[3] = new Vec4(0,0,1,0);
normals[4] = new Vec4(0,-1,0,0);
normals[5] = new Vec4(-1,0,0,0);
for (int i=0;i<6;i++)
{
//Rotates given side with the time one first, then ot get it on its off axis, then gets the image of each axis under the given rotation
//The rotate functions do change the transforms, but the multiplication does not
normals[i] = transforms[i].rotate((float) (time%(6000*6.28) )/ 6000, new Vec3(0,1,0)).rotate((float) 24, new Vec3(1,.5,0)).mul_(normals[i]);
}
double pi2 = Math.PI / 2;
//Move and rotate the sides from the middle of the cube to the appropriate edges
transforms[0].translate(new Vec3(-size/2f,-size/2f,size/2f));
transforms[1].translate(new Vec3(-size/2f,-size/2f,-size/2f)).rotate((float) pi2, new Vec3(1,0,0));
transforms[2].translate(new Vec3(-size/2f,-size/2f,size/2f)).rotate((float) pi2, new Vec3(0,1,0));
transforms[3].translate(new Vec3(-size/2f,-size/2f,-size/2f));
transforms[4].translate(new Vec3(-size/2f,size/2f,-size/2f)).rotate((float) pi2, new Vec3(1,0,0));
transforms[5].translate(new Vec3(size/2f,-size/2f,size/2f)).rotate((float) pi2, new Vec3(0,1,0));
for (int i=0;i<6;i++) // I have no clue why this is necessary, without it the sides of the cube mess up; may need to be changed if the title screen changes position.
{
transforms[i] = transforms[i].translate(new Vec3(0,0,17.5-3*(i<2 ? 1 : 0)));
}
}
@Override
protected void assembleSelf(RenderTarget target)
{
computeTransforms();
setPosition(750,780);
target.pushTransform(new Mat4(1).translate(new Vec3(getX()+size*r3/2,getY()-size*r3/2,0))); //-size*r3/2
for (int b=0; b<6;b++)
{
target.pushTransform(transforms[b]);
float dot = normals[b].dot(new Vec4(-1,0,0,0)); //Gets the "amount" the given side is pointing in the -x direction
Vec4 color = new Vec4(.4+.3*dot, .4+.3*dot, .6+.4*dot,1.0); //More aligned means brighter color
target.fill(0,0, size, size, color);
target.popTransform();
}
target.popTransform();
}
}

View File

@ -18,6 +18,7 @@
package ru.windcorp.progressia.test;
import ru.windcorp.progressia.Progressia;
import ru.windcorp.progressia.client.graphics.Colors;
import ru.windcorp.progressia.client.graphics.font.Font;
import ru.windcorp.progressia.client.graphics.font.Typeface;
@ -30,6 +31,8 @@ import ru.windcorp.progressia.client.localization.MutableStringLocalized;
public class LayerAbout extends GUILayer {
public static String version = "pre-alpha 3";
public LayerAbout() {
super("LayerAbout", new LayoutAlign(1, 1, 5));
@ -50,7 +53,7 @@ public class LayerAbout extends GUILayer {
new Label(
"Version",
font,
new MutableStringLocalized("LayerAbout.Version").format("pre-alpha 3")
new MutableStringLocalized("LayerAbout.Version").format(Progressia.getFullerVersion())
)
);

View File

@ -0,0 +1,53 @@
package ru.windcorp.progressia.test;
import ru.windcorp.progressia.client.graphics.Colors;
import ru.windcorp.progressia.client.graphics.GUI;
import ru.windcorp.progressia.client.graphics.font.Font;
import ru.windcorp.progressia.client.graphics.gui.*;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical;
import ru.windcorp.progressia.client.graphics.texture.SimpleTextures;
import ru.windcorp.progressia.client.localization.Localizer;
import ru.windcorp.progressia.client.localization.MutableString;
import ru.windcorp.progressia.client.localization.MutableStringLocalized;
import java.util.List;
public class LayerOptions extends Background {
public LayerOptions(String name) {
super(name, new LayoutAlign(0, 1f, 15), SimpleTextures.get("title/background"));
Group content = new Group("Layer" + name + ".Group", new LayoutVertical(15));
Font font = new Font().withColor(Colors.BLUE).withAlign(0.5f);
MutableString languageText = new MutableStringLocalized("Layer" + name + ".Language");
content.addChild(new Button(name + ".Language", new Label(name + ".Language", font, languageText)).addAction(this::toggleLanguage));
MutableString playText = new MutableStringLocalized("Layer" + name + ".Return");
content.addChild(new Button(name + ".Return", new Label(name + ".Return", font, playText)).addAction(this::openTitle));
getRoot().addChild(content);
}
private void openTitle(BasicButton basicButton) {
GUI.removeLayer(this);
GUI.addTopLayer(new LayerTitle("Title"));
}
private void toggleLanguage(BasicButton basicButton)
{
String curLang = Localizer.getInstance().getLanguage();
List<String> allLangs = Localizer.getInstance().getLanguages();
int pos = allLangs.indexOf(curLang);
pos++;
if (pos >= allLangs.size())
{
Localizer.getInstance().setLanguage(allLangs.get(0));
}
else
{
Localizer.getInstance().setLanguage(allLangs.get(pos));
}
}
}

View File

@ -1,16 +1,20 @@
package ru.windcorp.progressia.test;
import ru.windcorp.progressia.Progressia;
import ru.windcorp.progressia.client.ClientState;
import ru.windcorp.progressia.client.graphics.Colors;
import ru.windcorp.progressia.client.graphics.GUI;
import ru.windcorp.progressia.client.graphics.font.Font;
import ru.windcorp.progressia.client.graphics.gui.Background;
import ru.windcorp.progressia.client.graphics.gui.BasicButton;
import ru.windcorp.progressia.client.graphics.gui.Button;
import ru.windcorp.progressia.client.graphics.gui.GUILayer;
import ru.windcorp.progressia.client.graphics.gui.Group;
import ru.windcorp.progressia.client.graphics.gui.Label;
import ru.windcorp.progressia.client.graphics.gui.TextureComponent;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutEdges;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical;
import ru.windcorp.progressia.client.graphics.texture.SimpleTextures;
import ru.windcorp.progressia.client.localization.MutableString;
import ru.windcorp.progressia.client.localization.MutableStringLocalized;
import ru.windcorp.progressia.common.util.crash.CrashReports;
@ -24,34 +28,58 @@ import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
public class LayerTitle extends GUILayer {
public class LayerTitle extends Background {
private final BasicButton resetButton;
public LayerTitle(String name) {
super(name, new LayoutAlign(0.5f, 0.7f, 15));
super(name, new LayoutAlign(0, 1f, 15), SimpleTextures.get("title/background"));
Group content = new Group("Layer" + name + ".Group", new LayoutVertical(15));
Group info = new Group("Layer"+name+".InfoGroup", new LayoutEdges(30));
Group buttonContent = new Group("Layer" + name + ".ButtonGroup", new LayoutColumn(15, 320));
MutableString title = new MutableStringLocalized("Layer" + name + ".Title");
Font titleFont = new Font().deriveBold().withColor(Colors.BLACK).withAlign(0.5f);
content.addChild(new Label(name + ".Title", titleFont, title));
Font titleFont = new Font().deriveBold().withColor(Colors.BLUE).withAlign(0.5f);
content.addChild(new TextureComponent(name + ".Title", SimpleTextures.get("title/progressia")));
info.addChild(new Label(
"About",
titleFont,
new MutableStringLocalized("LayerAbout.Title")
)
);
info.addChild(
new Label(
"Version",
titleFont,
Progressia.getFullerVersion()
)
);
content.addChild(info);
Font buttonFont = titleFont.deriveNotBold();
MutableString playText = new MutableStringLocalized("Layer" + name + ".Play");
content.addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame));
buttonContent.addChild(new Button(name + ".Play", new Label(name + ".Play", buttonFont, playText)).addAction(this::startGame));
MutableString resetText = new MutableStringLocalized("Layer" + name + ".Reset");
this.resetButton = new Button(name + ".Reset", new Label(name + ".Reset", buttonFont, resetText)).addAction(this::resetWorld);
content.addChild(resetButton);
buttonContent.addChild(resetButton);
updateResetButton();
MutableString settingsText = new MutableStringLocalized("Layer" + name + ".Options");
buttonContent.addChild(new Button(name + ".Options", new Label(name + ".Options", buttonFont, settingsText)).addAction(this::openOptions));
MutableString quitText = new MutableStringLocalized("Layer" + name + ".Quit");
content.addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> {
System.exit(0);
}));
buttonContent.addChild(new Button(name + "Quit", new Label(name + ".Quit", buttonFont, quitText)).addAction(b -> System.exit(0)));
content.addChild(buttonContent);
getRoot().addChild(content);
buttonContent.setPreferredSize(500, 1000);
CubeComponent cube = new CubeComponent(name+".Cube",300);
getRoot().addChild(cube);
}
private void updateResetButton() {
@ -67,7 +95,7 @@ public class LayerTitle extends GUILayer {
throw CrashReports.report(e, "Problem with loading server");
}
}
private void resetWorld(BasicButton basicButton) {
Path rootPath = Paths.get("tmp_world");
@ -88,8 +116,13 @@ public class LayerTitle extends GUILayer {
} catch (IOException e) {
throw CrashReports.report(e, "Could not reset world");
}
updateResetButton();
}
private void openOptions(BasicButton basicButton) {
GUI.removeLayer(this);
GUI.addTopLayer(new LayerOptions("Options"));
}
}

View File

@ -0,0 +1,33 @@
package ru.windcorp.progressia.test;
import ru.windcorp.progressia.client.graphics.gui.Component;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical;
public class LayoutColumn extends LayoutVertical {
protected int maxWidth;
private final int margin;
public LayoutColumn(int gap, int maxWidth)
{
super(gap);
this.maxWidth = maxWidth;
margin = gap;
}
@Override
public void layout(Component c) {
int x = c.getX() + margin,
y = c.getY() + c.getHeight();
synchronized (c.getChildren()) {
for (Component child : c.getChildren()) {
int height = child.getPreferredSize().y;
y -= margin + height;
child.setBounds(x, y, maxWidth, height);
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
16 20 22 24 32 40 48 64 96 128 256

View File

@ -24,5 +24,8 @@ LayerTitle.Reset = Reset World
LayerTitle.Options = Options
LayerTitle.Quit = Quit
LayerOptions.Return = Back To Menu
LayerOptions.Language = US English
LayerText.Load = Loading...
LayerText.Save = Saving...

View File

@ -24,5 +24,8 @@ LayerTitle.Reset = Сбросить мир
LayerTitle.Options = Настройки
LayerTitle.Quit = Выход
LayerOptions.Return = Главное меню
LayerOptions.Language = Русский
LayerText.Load = Загрузка...
LayerText.Save = Сохранение...

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,8 +1,8 @@
Package: progressia-techdemo
Version: 1.0
Package: progressia
Version: ${version}
Section: custom
Priority: optional
Architecture: all
Maintainer: Javapony <kvadropups@gmail.com>
Depends: java8-runtime
Description: Progressia Techdemo release
Description: Progressia - a 3D sandbox survival game

View File

@ -1,161 +1,164 @@
;NSIS Modern User Interface
;Welcome/Finish Page Example Script
;Written by Joost Verburg
;--------------------------------
;Include Modern UI
!include "MUI2.nsh"
;--------------------------------
;General
!define PROJECT_NAME "Progressia"
; MUI Settings / Icons
!define MUI_ICON "logo.ico"
;!define MUI_UNICON ;Uninstall icon
; MUI Settings / Header
; !define MUI_HEADERIMAGE
; !define MUI_HEADERIMAGE_RIGHT
; !define MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\orange-r-nsis.bmp"
; !define MUI_HEADERIMAGE_UNBITMAP "${NSISDIR}\Contrib\Graphics\Header\orange-uninstall-r-nsis.bmp"
; MUI Settings / Wizard
!define MUI_WELCOMEFINISHPAGE_BITMAP "left_side.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "left_side.bmp"
;Name and file
Name "${PROJECT_NAME}"
OutFile "${PROJECT_NAME}Installer.exe"
Unicode True
;Default installation folder
InstallDir "$PROGRAMFILES\${PROJECT_NAME}"
;Get installation folder from registry if available
InstallDirRegKey HKLM "Software\${PROJECT_NAME}" ""
;Request application privileges for Windows Vista
RequestExecutionLevel admin
;--------------------------------
;Interface Settings
!define MUI_ABORTWARNING
;--------------------------------
;Pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_TEXT "Start ${PROJECT_NAME}"
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_COMPONENTS
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
;Installer Sections
Section "Install ${PROJECT_NAME}" SEC0000
SectionIn RO ;Make it read-only
SetOutPath "$INSTDIR"
SetOverwrite on
;Files
File Progressia.jar
File logo.ico
File /r lib
;Store installation folder
WriteRegStr HKLM SOFTWARE\Progressia "Install_Dir" "$INSTDIR"
;Create uninstaller
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "DisplayName" "${PROJECT_NAME} (remove only)"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteUninstaller "$INSTDIR\Uninstall.exe"
SectionEnd
Section "Create Desktop Shortcut" SEC0001
SetOutPath "$APPDATA\${PROJECT_NAME}"
CreateShortCut "$DESKTOP\${PROJECT_NAME}.lnk" "$INSTDIR\${PROJECT_NAME}.jar" "" "$INSTDIR\logo.ico"
SectionEnd
Section "Start Menu Shortcuts" SEC0002
CreateDirectory "$SMPROGRAMS\${PROJECT_NAME}"
CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\${PROJECT_NAME}.lnk" "$INSTDIR\${PROJECT_NAME}.jar" "" "$INSTDIR\logo.ico"
SectionEnd
;--------------------------------
;Uninstaller Section
Section "Uninstall"
;ADD YOUR OWN FILES HERE...
Delete $INSTDIR\Uninstall.exe
Delete $INSTDIR\Progressia.jar
Delete $INSTDIR\lib\*.*
Delete $INSTDIR\logo.ico
RMDir $INSTDIR\lib
Delete $DESKTOP\${PROJECT_NAME}.lnk
Delete $SMPROGRAMS\${PROJECT_NAME}\Uninstall.lnk
Delete $SMPROGRAMS\${PROJECT_NAME}\${PROJECT_NAME}.lnk
RMDir $INSTDIR
RMDir /r $SMPROGRAMS\${PROJECT_NAME}
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}"
DeleteRegKey HKLM "Software\${PROJECT_NAME}"
SectionEnd
Section "un.Remove user data"
RMDir /r "$APPDATA\${PROJECT_NAME}"
SectionEnd
;--------------------------------
;Functions
Function LaunchLink
SetOutPath "$APPDATA\${PROJECT_NAME}"
ExecShell "" "$INSTDIR\${PROJECT_NAME}.jar"
FunctionEnd
;--------------------------------
;Descriptions
;Language strings
LangString DESC_SecDummy ${LANG_ENGLISH} "Install ${PROJECT_NAME}."
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC0000} $(DESC_SecDummy)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
;NSIS Modern User Interface
;Welcome/Finish Page Example Script
;Written by Joost Verburg
;--------------------------------
;Include Modern UI
!include "MUI2.nsh"
;--------------------------------
;General
; Expecting the following symbols from caller:
; PROJECT_NAME
; PROJECT_VERSION
; MAIN_JAR_FILE
; MUI Settings / Icons
!define MUI_ICON "logo.ico"
;!define MUI_UNICON ;Uninstall icon
; MUI Settings / Header
; !define MUI_HEADERIMAGE
; !define MUI_HEADERIMAGE_RIGHT
; !define MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\orange-r-nsis.bmp"
; !define MUI_HEADERIMAGE_UNBITMAP "${NSISDIR}\Contrib\Graphics\Header\orange-uninstall-r-nsis.bmp"
; MUI Settings / Wizard
!define MUI_WELCOMEFINISHPAGE_BITMAP "left_side.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "left_side.bmp"
;Name and file
Name "${PROJECT_NAME}"
OutFile "${OUTPUT_DIR}/${PROJECT_NAME}-${PROJECT_VERSION}-installer.exe"
Unicode True
;Default installation folder
InstallDir "$PROGRAMFILES\${PROJECT_NAME}"
;Get installation folder from registry if available
InstallDirRegKey HKLM "Software\${PROJECT_NAME}" ""
;Request application privileges for Windows Vista
RequestExecutionLevel admin
;--------------------------------
;Interface Settings
!define MUI_ABORTWARNING
;--------------------------------
;Pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_TEXT "Start ${PROJECT_NAME}"
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_COMPONENTS
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
;Installer Sections
Section "Install ${PROJECT_NAME}" SEC0000
SectionIn RO ;Make it read-only
SetOutPath "$INSTDIR"
SetOverwrite on
;Files
File "${MAIN_JAR_FILE}"
File logo.ico
File /r lib
;Store installation folder
WriteRegStr HKLM "SOFTWARE\${PROJECT_NAME}" "Install_Dir" "$INSTDIR"
;Create uninstaller
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "DisplayName" "${PROJECT_NAME} (remove only)"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteUninstaller "$INSTDIR\Uninstall.exe"
SectionEnd
Section "Create Desktop Shortcut" SEC0001
SetOutPath "$APPDATA\${PROJECT_NAME}"
CreateShortCut "$DESKTOP\${PROJECT_NAME}.lnk" "$INSTDIR\${MAIN_JAR_FILE}" "" "$INSTDIR\logo.ico"
SectionEnd
Section "Start Menu Shortcuts" SEC0002
CreateDirectory "$SMPROGRAMS\${PROJECT_NAME}"
CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\${PROJECT_NAME}.lnk" "$INSTDIR\${MAIN_JAR_FILE}" "" "$INSTDIR\logo.ico"
SectionEnd
;--------------------------------
;Uninstaller Section
Section "Uninstall"
;ADD YOUR OWN FILES HERE...
Delete $INSTDIR\Uninstall.exe
Delete "$INSTDIR\${MAIN_JAR_FILE}"
Delete $INSTDIR\lib\*.*
Delete $INSTDIR\logo.ico
RMDir $INSTDIR\lib
Delete $DESKTOP\${PROJECT_NAME}.lnk
Delete $SMPROGRAMS\${PROJECT_NAME}\Uninstall.lnk
Delete $SMPROGRAMS\${PROJECT_NAME}\${PROJECT_NAME}.lnk
RMDir $INSTDIR
RMDir /r $SMPROGRAMS\${PROJECT_NAME}
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}"
DeleteRegKey HKLM "Software\${PROJECT_NAME}"
SectionEnd
Section "un.Remove user data"
RMDir /r "$APPDATA\${PROJECT_NAME}"
SectionEnd
;--------------------------------
;Functions
Function LaunchLink
SetOutPath "$APPDATA\${PROJECT_NAME}"
ExecShell "" "$INSTDIR\${MAIN_JAR_FILE}"
FunctionEnd
;--------------------------------
;Descriptions
;Language strings
LangString DESC_SecDummy ${LANG_ENGLISH} "Install ${PROJECT_NAME}."
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC0000} $(DESC_SecDummy)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -0,0 +1,2 @@
@ECHO OFF
java -jar "@mainJarFile@"

11
src/packaging/zip/start.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
jvmFlags=""
case "$OSTYPE" in
"darwin"*)
# On MacOS, use -XstartOnFirstThread to resolve an issue with OpenGL contexts
jvmFlags="$jvmFlags -XstartOnFirstThread"
esac
java $jvmFlags -jar "@mainJarFile@"