Merge branch 'master' into moduleSystem

This commit is contained in:
Евгений Смирнов 2021-06-12 21:05:15 +03:00
commit 513feb1093
503 changed files with 37550 additions and 28566 deletions

3
.gitattributes vendored
View File

@ -2,5 +2,8 @@
# https://help.github.com/articles/dealing-with-line-endings/ # https://help.github.com/articles/dealing-with-line-endings/
# #
# These are explicitly windows files and should use crlf # These are explicitly windows files and should use crlf
* text=auto eol=lf
*.bat text eol=crlf *.bat text eol=crlf

17
.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/*
@ -25,12 +30,10 @@ build_packages/*
!build_packages/NSIS !build_packages/NSIS
build_packages/NSIS/* build_packages/NSIS/*
!build_packages/NSIS/ProgressiaInstaller.nsi !build_packages/NSIS/ProgressiaInstaller.nsi
!build_packages/NSIS/logo.ico
!build_packages/NSIS/left_side.bmp
# ... and except build_packages/DEB/progressia-*/DEBIAN/control # ... and except build_packages/DEB/template
!build_packages/DEB !build_packages/DEB
build_packages/DEB/* build_packages/DEB/*
!build_packages/DEB/progressia-* !build_packages/DEB/template
build_packages/DEB/progressia-*/*
!build_packages/DEB/progressia-*/DEBIAN
build_packages/DEB/progressia-*/DEBIAN/*
!build_packages/DEB/progressia-*/DEBIAN/control

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 about 0.5 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,5 +1,23 @@
#!/bin/bash #!/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; } echoerr() { echo "$@" 1>&2; }
buildDebianPackage() { buildDebianPackage() {
@ -7,15 +25,20 @@ buildDebianPackage() {
# Commands that must be available to execute this action # Commands that must be available to execute this action
requiredCommands='dpkg-deb fakeroot' requiredCommands='dpkg-deb fakeroot'
# Version that the package will receive # Package name. Sync with control file manually!
version='0.1_all' name='progressia-techdemo'
# Version that the package will receive. Sync with control file manually!
version='1.0_all'
directory="build_packages/DEB/progressia-$version" # This directory will be copied into $tmpDir
templateDirectory="build_packages/DEB/template"
# .deb control file that must be present # Files that must be present
configurationFile="$directory/DEBIAN/control" requiredFiles="$templateDirectory/DEBIAN/control"
outputFile="build_packages/DEB/progressia-$version.deb" nameAndVersion="$name-$version"
tmpDir="build_packages/DEB/$nameAndVersion"
outputFile="build_packages/DEB/$nameAndVersion.deb"
echo "Checking environment to build Debian package" echo "Checking environment to build Debian package"
@ -28,25 +51,28 @@ buildDebianPackage() {
fi fi
done done
if ! [ -r "$configurationFile" ]; then for file in $requiredFiles; do
echoerr "$configurationFile is missing or not readable, cannot package" if ! [ -r "$file" ]; then
echoerr "$file is missing or not readable, cannot package"
exit 101 exit 101
else else
echo "- $configurationFile is present and readable" echo "- $file is present and readable"
fi fi
done
echo "Environment OK; packaging Debian package" echo "Environment OK; packaging Debian package"
exitCode=0 exitCode=0
{ {
user=`whoami` shareDir="$tmpDir/usr/share/progressia"
homeDir="$directory/home/$user/Progressia/"
mkdir -p "$homeDir" && mkdir -p "$tmpDir" &&
cp -r 'build/libs/lib' "$homeDir/lib" && mkdir -p "$shareDir" &&
cp 'build/libs/Progressia.jar' "$homeDir/Progressia.jar" && cp -r "$templateDirectory"/* "$tmpDir" &&
cp -r 'build/libs/lib' "$shareDir/lib" &&
cp 'build/libs/Progressia.jar' "$shareDir/Progressia.jar" &&
echo "------ DPKG-DEB ------" && echo "------ DPKG-DEB ------" &&
fakeroot dpkg-deb --build "$directory" && fakeroot dpkg-deb --build "$tmpDir" &&
echo "---- DPKG-DEB END ----" && echo "---- DPKG-DEB END ----" &&
mv "$outputFile" build_packages mv "$outputFile" build_packages
} || { } || {
@ -55,8 +81,8 @@ buildDebianPackage() {
} }
{ {
if [ -d "$homeDir" ]; then if [ -d "$tmpDir" ]; then
rm -r "$homeDir" rm -r "$tmpDir"
fi fi
echo "Cleaned up" echo "Cleaned up"
} || { } || {
@ -102,6 +128,7 @@ buildWindowsInstaller() {
{ {
cp -r 'build/libs/lib' 'build_packages/NSIS/lib' && cp -r 'build/libs/lib' 'build_packages/NSIS/lib' &&
cp 'build/libs/Progressia.jar' 'build_packages/NSIS/Progressia.jar' && cp 'build/libs/Progressia.jar' 'build_packages/NSIS/Progressia.jar' &&
cp 'LICENSE' 'build_packages/NSIS/LICENSE.txt' &&
echo "------ NSIS ------" && echo "------ NSIS ------" &&
makensis "$configurationFile" && makensis "$configurationFile" &&
echo "---- NSIS END ----" && echo "---- NSIS END ----" &&
@ -118,6 +145,9 @@ buildWindowsInstaller() {
if [ -e 'build_packages/NSIS/Progressia.jar' ]; then if [ -e 'build_packages/NSIS/Progressia.jar' ]; then
rm 'build_packages/NSIS/Progressia.jar' rm 'build_packages/NSIS/Progressia.jar'
fi fi
if [ -e 'build_packages/NSIS/LICENSE.txt' ]; then
rm 'build_packages/NSIS/LICENSE.txt'
fi
echo "Cleaned up" echo "Cleaned up"
} || { } || {
echoerr "Could not clean up after building Windows installer" echoerr "Could not clean up after building Windows installer"

View File

@ -1,9 +0,0 @@
Package: Progressia
Version: 0.1
Section: custom
Priority: optional
Architecture: all
Essential: no
Maintainer: Test
Depends: default-jdk
Description: Test package

View File

@ -0,0 +1,8 @@
Package: progressia-techdemo
Version: 1.0
Section: custom
Priority: optional
Architecture: all
Maintainer: Javapony <kvadropups@gmail.com>
Depends: java8-runtime
Description: Progressia Techdemo release

View File

@ -10,16 +10,32 @@
;-------------------------------- ;--------------------------------
;General ;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 and file
Name "Progressia" Name "${PROJECT_NAME}"
OutFile "ProgressiaInstaller.exe" OutFile "${PROJECT_NAME}Installer.exe"
Unicode True Unicode True
;Default installation folder ;Default installation folder
InstallDir "$PROGRAMFILES\Progressia" InstallDir "$PROGRAMFILES\${PROJECT_NAME}"
;Get installation folder from registry if available ;Get installation folder from registry if available
InstallDirRegKey HKLM "Software\Progressia" "Install_Dir" InstallDirRegKey HKLM "Software\${PROJECT_NAME}" ""
;Request application privileges for Windows Vista ;Request application privileges for Windows Vista
RequestExecutionLevel admin RequestExecutionLevel admin
@ -33,14 +49,18 @@
;Pages ;Pages
!insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_WELCOME
;!insertmacro MUI_PAGE_LICENSE "${NSISDIR}\Docs\Modern UI\License.txt" !insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES !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_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_COMPONENTS
!insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH !insertmacro MUI_UNPAGE_FINISH
@ -52,12 +72,15 @@
;-------------------------------- ;--------------------------------
;Installer Sections ;Installer Sections
Section "Install Progressia" SecDummy Section "Install ${PROJECT_NAME}" SEC0000
SectionIn RO ;Make it read-only
SetOutPath "$INSTDIR" SetOutPath "$INSTDIR"
SetOverwrite on
;Files ;Files
File Progressia.jar File Progressia.jar
File logo.ico
File /r lib File /r lib
;Store installation folder ;Store installation folder
@ -65,22 +88,24 @@ Section "Install Progressia" SecDummy
;Create uninstaller ;Create uninstaller
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Progressia" "DisplayName" "Progressia (remove only)" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "DisplayName" "${PROJECT_NAME} (remove only)"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Progressia" "UninstallString" "$INSTDIR\Uninstall.exe" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteUninstaller "$INSTDIR\Uninstall.exe" WriteUninstaller "$INSTDIR\Uninstall.exe"
SectionEnd SectionEnd
;-------------------------------- Section "Create Desktop Shortcut" SEC0001
;Descriptions SetOutPath "$APPDATA\${PROJECT_NAME}"
CreateShortCut "$DESKTOP\${PROJECT_NAME}.lnk" "$INSTDIR\${PROJECT_NAME}.jar" "" "$INSTDIR\logo.ico"
SectionEnd
;Language strings Section "Start Menu Shortcuts" SEC0002
LangString DESC_SecDummy ${LANG_ENGLISH} "A test section."
;Assign language strings to sections CreateDirectory "$SMPROGRAMS\${PROJECT_NAME}"
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
!insertmacro MUI_DESCRIPTION_TEXT ${SecDummy} $(DESC_SecDummy) CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\${PROJECT_NAME}.lnk" "$INSTDIR\${PROJECT_NAME}.jar" "" "$INSTDIR\logo.ico"
!insertmacro MUI_FUNCTION_DESCRIPTION_END
SectionEnd
;-------------------------------- ;--------------------------------
;Uninstaller Section ;Uninstaller Section
@ -92,9 +117,45 @@ Section "Uninstall"
Delete $INSTDIR\Uninstall.exe Delete $INSTDIR\Uninstall.exe
Delete $INSTDIR\Progressia.jar Delete $INSTDIR\Progressia.jar
Delete $INSTDIR\lib\*.* Delete $INSTDIR\lib\*.*
Delete $INSTDIR\logo.ico
RMDir /r "$INSTDIR" RMDir $INSTDIR\lib
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Progressia"
DeleteRegKey HKLM "Software\Progressia" 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 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

69
docs/CONTRIBUTING.md Normal file
View File

@ -0,0 +1,69 @@
# Contributing Guidelines
This document lists conventions adopted by Progressia developers.
## git
### Branches
Progressia repository contains a `master` branch and several "feature" branches.
`master` is expected to contain a version of the game suitable for demonstration and forking/branching. Do not commit directly to `master` without OLEGSHA's approval.
- `master` must always correctly build without compiler warnings (see below).
- `master` must always pass all unit tests.
- `master` must always be able to launch successfully.
- `master` must always only contain working features.
- `master` should not contain excessive debug code.
- `master` must always have its code and filenames formatted (see below).
"Feature" branches are branches dedicated to the development of a single feature. When the feature reaches completion the branch is merged into `master` and removed. Intermediate merges into `master` may occur when some fitting milestone is reached. Intermediate merges from `master` may be done as necessary. Merges between "feature" branches should generally be avoided.
When beginning work on a new feature, create a new branch based on `master` (or on another "feature" branch if absolutely necessary). Use `all-small-with-dashes` to name the branch: `add-trees` or `rebalance-plastics` are good names. Do not fix unrelated bugs or work on unrelated features in a "feature" branch - create a new one, switch to an existing one or commit directly to `master` if the changes are small enough.
"Feature" branches may not be formatted properly. Formatting is required before merging into `master` or other branches.
### Commits
- Commits must leave the branch in a state that builds without compiler warnings (see below).
- Changes should be grouped in commits semantically. Avoid committing many small related changes in sequence; if necessary, wait and accumulate them. Avoid committing unrelated changes together; if necessary, split staged changes into several commits. This should normally result in about 1-2 commits for a day's work.
- Commit bulk changes (renaming, formatting, ...) separately. Don't ever commit whitespace changes outside formatting commits.
- Message format:
```
Short description of changes
<empty line>
- Enumeration of changes
- Nest when appropriate
- Use dashes only
- List not needed for small commits
```
Example:
```
Changed packages for relations, renamed Face to ShapePart
- Added BlockRelation as an abstract superclass to existing relations
- Must be given an absolute "up" direction before use
- Moved AbsFace, AbsRelation and BlockRelation to .world.rels
- Renamed Face to ShapePart to reduce confusion with AbsFace
```
- Only commit changes described in the commit message. Please double-check staged files before committing.
- Avoid merge conflicts. Pull before committing.
- Better sign commits than not. See: [git](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work), [GitHub](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification).
## Code
### Warnings
Make sure that all committed code contains no compiler warnings. This specifically includes unused imports, unused private members, missing `@Override`s and warnings related to generics.
Warnings about unknown tokens in `@SuppressWarnings` are temporarily ignored. Please disable them in your IDE.
### Code Style
Formatting code is important.
- The format is specified within the files inside `/templates_and_presets/eclipse_ide`. Import the specifications into Eclipse or IntelliJ IDEA and use the IDEs' format feature. Alternatively format the code manually in accordance with existing files.
- Only use tabs for indentation. Never indent with spaces even when wrapping lines. This is to ensure that indentation does not break when tab width is different.
- Don't use `I` prefix for interfaces (not `IDoable` but `Doable`).
- Prioritize readability over compactness. Do not hesitate to use (very) long identifiers if they aid comprehension.
- Document all mathematics unless it is trivial, especially when using math notation for variable names.
- Use proper English when writing comments. Avoid boxes in comments. Use `//` for single-line comments.

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,125 @@
# 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.
### Applying formatting templates
Windcorp's Progressia repository is formatted with a style defined for Eclipse IDE in
`templates_and_presets/eclipse_ide`.
Please apply these templates to the project to automatically format the source in a similar fashion.
1. In project context menu, click 'Properties'.
2. In 'Java Code Style' > 'Code Templates', check 'Enable project specific settings', then click 'Import' and select
`templates_and_presets/eclipse_ide/CodeTemplates.xml`.
3. In 'Java Code Style' > 'Formatter', check 'Enable project specific settings', then click 'Import' and select
`templates_and_presets/eclipse_ide/FormatterProfile.xml`.
## 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.

View File

@ -0,0 +1,44 @@
# Intellij IDEA Guide
This document is a guide to configuring Intellij IDEA 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 pre-installed Intellij IDEA Git extension. If you choose not to, skip the following subsection.
#### Using Git Extension
[Git extension](https://plugins.jetbrains.com/plugin/13173-git) is a git interface for Intellij IDEA. It is currently shipped with Intellij IDEA.
1. Open Intellij IDEA welcome screen, click the 'Get from VCS' button. Alternatively, use 'File' menu > 'New' > 'Project From Version Control...'.
2. Insert `https://github.com/OLEGSHA/Progressia.git` in the 'URL' field.
3. Change the local repository path, if necessary, and click 'Clone'.
### Creating a Run Configuration
Run configurations are used by Intellij IDEA to specify how a project must be run.
#### Using GUI shortcut
1. In Project Explorer, open `ru.windcorp.progressia.client.ProgressiaClientMain`.
2. Press small green triangle button in code editor window.
3. In the drop-down menu, click 'Modify Run Configuration...'.
4. Append `\run` to the 'Working directory' field. Alternatively, specify another location outside of the project's root directory.
5. Click 'Apply' to save changes.
#### Using 'Add Configuration' menu
1. Click 'Add Configuration...'.
2. In 'Run/Debug Configurations', click 'Add new configuration' with the plus icon.
3. In the drop-down list, select 'Application'.
4. Enter the configuration name .
5. Select a JRE from the drop-down list.
6. Select the module whose classpath should be used to run the application: `Progressia.main`.
7. Enter `ru.windcorp.progressia.client.ProgressiaClientMain` in the 'Main Class' field.
8. Append `\run` to the 'Working directory' field. Alternatively, specify another location outside of the project's root directory.
9. Click 'Apply' to save changes.
Step 8 is required to specify that the game must run in some directory other than the project root, which is the default in Intellij IDEA.

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

@ -3,9 +3,11 @@ package kdotjpg.opensimplex2.areagen;
* This file has been modified in the following ways: * This file has been modified in the following ways:
* - added a package declaration at line 1; * - added a package declaration at line 1;
* - added missing @Override annotations; * - added missing @Override annotations;
* - commented out line 965 due to unused variables. * - commented out line 967 due to unused variables.
* The original version of this file can be found at * The original version of this file can be found at
* https://raw.githubusercontent.com/KdotJPG/OpenSimplex2/master/java/areagen/OpenSimplex2S.java * https://raw.githubusercontent.com/KdotJPG/OpenSimplex2/master/java/areagen/OpenSimplex2S.java
*
* @formatter:off
*/ */
/** /**
@ -983,16 +985,3 @@ public class OpenSimplex2S {
} }
} }
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil; package ru.windcorp.jputil;
import java.lang.reflect.Array; import java.lang.reflect.Array;
@ -23,7 +24,8 @@ import java.util.Objects;
public class ArrayUtil { public class ArrayUtil {
private ArrayUtil() {} private ArrayUtil() {
}
public static int firstIndexOf(byte[] array, byte element) { public static int firstIndexOf(byte[] array, byte element) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
@ -68,7 +70,8 @@ public class ArrayUtil {
public static boolean isSorted(byte[] array, boolean ascending) { public static boolean isSorted(byte[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
if ((array[i] < array[i + 1]) != ascending) { if ((array[i] < array[i + 1]) != ascending) {
return false; return false;
@ -121,7 +124,8 @@ public class ArrayUtil {
public static boolean isSorted(short[] array, boolean ascending) { public static boolean isSorted(short[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
if ((array[i] < array[i + 1]) != ascending) { if ((array[i] < array[i + 1]) != ascending) {
return false; return false;
@ -174,7 +178,8 @@ public class ArrayUtil {
public static boolean isSorted(int[] array, boolean ascending) { public static boolean isSorted(int[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
if ((array[i] < array[i + 1]) != ascending) { if ((array[i] < array[i + 1]) != ascending) {
return false; return false;
@ -227,7 +232,8 @@ public class ArrayUtil {
public static boolean isSorted(long[] array, boolean ascending) { public static boolean isSorted(long[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
if ((array[i] < array[i + 1]) != ascending) { if ((array[i] < array[i + 1]) != ascending) {
return false; return false;
@ -280,7 +286,8 @@ public class ArrayUtil {
public static boolean isSorted(float[] array, boolean ascending) { public static boolean isSorted(float[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
if ((array[i] < array[i + 1]) != ascending) { if ((array[i] < array[i + 1]) != ascending) {
return false; return false;
@ -333,7 +340,8 @@ public class ArrayUtil {
public static boolean isSorted(double[] array, boolean ascending) { public static boolean isSorted(double[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
if ((array[i] < array[i + 1]) != ascending) { if ((array[i] < array[i + 1]) != ascending) {
return false; return false;
@ -414,7 +422,8 @@ public class ArrayUtil {
public static boolean isSorted(char[] array, boolean ascending) { public static boolean isSorted(char[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
if ((array[i] < array[i + 1]) != ascending) { if ((array[i] < array[i + 1]) != ascending) {
return false; return false;
@ -508,7 +517,8 @@ public class ArrayUtil {
public static <T extends Comparable<T>> boolean isSorted(T[] array, boolean ascending) { public static <T extends Comparable<T>> boolean isSorted(T[] array, boolean ascending) {
for (int i = 0; i < array.length - 1; ++i) { for (int i = 0; i < array.length - 1; ++i) {
if (array[i] == array[i + 1]) continue; if (array[i] == array[i + 1])
continue;
int order = array[i].compareTo(array[i + 1]); int order = array[i].compareTo(array[i + 1]);
@ -600,7 +610,9 @@ public class ArrayUtil {
int end = offset + length; int end = offset + length;
if (end > arrayLength || offset < 0) if (end > arrayLength || offset < 0)
throw new IllegalArgumentException("Array contains [0; " + arrayLength + "), requested [" + offset + "; " + end + ")"); throw new IllegalArgumentException(
"Array contains [0; " + arrayLength + "), requested [" + offset + "; " + end + ")"
);
return length; return length;
} }
@ -615,7 +627,9 @@ public class ArrayUtil {
throw new IllegalArgumentException("Start > end: " + start + " > " + end); throw new IllegalArgumentException("Start > end: " + start + " > " + end);
if (end > arrayLength || start < 0) if (end > arrayLength || start < 0)
throw new IllegalArgumentException("Array contains [0; " + arrayLength + "), requested [" + start + "; " + end + ")"); throw new IllegalArgumentException(
"Array contains [0; " + arrayLength + "), requested [" + start + "; " + end + ")"
);
return end; return end;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil; package ru.windcorp.jputil;
import java.io.OutputStream; import java.io.OutputStream;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil; package ru.windcorp.jputil;
import java.util.HashMap; import java.util.HashMap;
@ -22,16 +23,25 @@ import java.util.Map;
public class PrimitiveUtil { public class PrimitiveUtil {
private PrimitiveUtil() {} private PrimitiveUtil() {
}
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_BOXED = new HashMap<>(); private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_BOXED = new HashMap<>();
private static final Map<Class<?>, Object> PRIMITIVE_TO_NULL = new HashMap<>(); private static final Map<Class<?>, Object> PRIMITIVE_TO_NULL = new HashMap<>();
static { static {
for (Class<?> boxed : new Class<?>[] { for (
Boolean.class, Byte.class, Short.class, Character.class, Class<?> boxed : new Class<?>[] {
Integer.class, Long.class, Float.class, Double.class Boolean.class,
}) { Byte.class,
Short.class,
Character.class,
Integer.class,
Long.class,
Float.class,
Double.class
}
) {
try { try {
PRIMITIVE_TO_BOXED.put((Class<?>) boxed.getField("TYPE").get(null), boxed); PRIMITIVE_TO_BOXED.put((Class<?>) boxed.getField("TYPE").get(null), boxed);
} catch (Exception e) { } catch (Exception e) {

View File

@ -1,6 +1,6 @@
/* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -11,7 +11,11 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * 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.jputil; package ru.windcorp.jputil;
import java.util.function.*; import java.util.function.*;
@ -35,10 +39,14 @@ import java.util.stream.LongStream;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
* Contains static methods to create {@link Stream Streams} that synchronize their * Contains static methods to create {@link Stream Streams} that synchronize
* <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps"> * their
* <a href=
* "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps">
* terminal operations</a> on a given monitor. * terminal operations</a> on a given monitor.
* @author Javapony (<a href="mailto:kvadropups@gmail.com">kvadropups@gmail.com</a>) *
* @author Javapony
* (<a href="mailto:kvadropups@gmail.com">kvadropups@gmail.com</a>)
*/ */
// SonarLint: "Stream.peek" should be used with caution (java:S3864) // SonarLint: "Stream.peek" should be used with caution (java:S3864)
@ -1063,20 +1071,30 @@ public class SyncStreams {
/** /**
* Wraps the given {@link Stream} to make all * Wraps the given {@link Stream} to make all
* <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps"> * <a href=
* terminal operations</a> acquire the provided monitor's lock before execution. Intermediate operations * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps">
* return streams that are also synchronized on the same object. The created stream will behave identically * terminal operations</a> acquire the provided monitor's lock before
* to the provided stream in all other aspects. Use this to synchronize access to stream's source. * execution. Intermediate operations
* <p><i>The returned {@code Stream}'s {@link Stream#iterator() iterator()} and {@link Stream#spliterator() * return streams that are also synchronized on the same object. The created
* spliterator()} methods return regular non-synchronized iterators and spliterators respectively</i>. It * stream will behave identically
* to the provided stream in all other aspects. Use this to synchronize
* access to stream's source.
* <p>
* <i>The returned {@code Stream}'s {@link Stream#iterator() iterator()} and
* {@link Stream#spliterator()
* spliterator()} methods return regular non-synchronized iterators and
* spliterators respectively</i>. It
* is the user's responsibility to avoid concurrency issues: * is the user's responsibility to avoid concurrency issues:
*
* <pre> * <pre>
* synchronized (stream.getMonitor()) { * synchronized (stream.getMonitor()) {
* Iterator<T> it = stream.iterator(); * Iterator<T> it = stream.iterator();
* ... * ...
* } * }
* </pre> * </pre>
*
* Usage example: * Usage example:
*
* <pre> * <pre>
* Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;()); * Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;());
* ... * ...
@ -1087,9 +1105,11 @@ public class SyncStreams {
* *
* @param <T> the class of objects in the Stream * @param <T> the class of objects in the Stream
* @param stream the stream to wrap. * @param stream the stream to wrap.
* @param monitor the object that the stream will use for synchronization. When {@code null}, the stream * @param monitor the object that the stream will use for synchronization.
* When {@code null}, the stream
* will synchronize on itself. * will synchronize on itself.
* @return a {@link SyncStream SyncStream&lt;T&gt;} synchronized on {@code monitor} and backed by {@code stream}. * @return a {@link SyncStream SyncStream&lt;T&gt;} synchronized on
* {@code monitor} and backed by {@code stream}.
* @throws NullPointerException if {@code stream == null}. * @throws NullPointerException if {@code stream == null}.
*/ */
public static <T> SyncStream<T> synchronizedStream(Stream<T> stream, Object monitor) { public static <T> SyncStream<T> synchronizedStream(Stream<T> stream, Object monitor) {
@ -1099,20 +1119,31 @@ public class SyncStreams {
/** /**
* Wraps the given {@link IntStream} to make all * Wraps the given {@link IntStream} to make all
* <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps"> * <a href=
* terminal operations</a> acquire the provided monitor's lock before execution. Intermediate operations * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps">
* return streams that are also synchronized on the same object. The created stream will behave identically * terminal operations</a> acquire the provided monitor's lock before
* to the provided stream in all other aspects. Use this to synchronize access to stream's source. * execution. Intermediate operations
* <p><i>The returned {@code IntStream}'s {@link IntStream#iterator() iterator()} and * return streams that are also synchronized on the same object. The created
* {@link IntStream#spliterator() spliterator()} methods return regular non-synchronized iterators and * stream will behave identically
* spliterators respectively</i>. It is the user's responsibility to avoid concurrency issues: * to the provided stream in all other aspects. Use this to synchronize
* access to stream's source.
* <p>
* <i>The returned {@code IntStream}'s {@link IntStream#iterator()
* iterator()} and
* {@link IntStream#spliterator() spliterator()} methods return regular
* non-synchronized iterators and
* spliterators respectively</i>. It is the user's responsibility to avoid
* concurrency issues:
*
* <pre> * <pre>
* synchronized (stream.getMonitor()) { * synchronized (stream.getMonitor()) {
* PrimitiveIterator.OfInt it = stream.iterator(); * PrimitiveIterator.OfInt it = stream.iterator();
* ... * ...
* } * }
* </pre> * </pre>
*
* Usage example: * Usage example:
*
* <pre> * <pre>
* Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;()); * Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;());
* ... * ...
@ -1122,9 +1153,11 @@ public class SyncStreams {
* </pre> * </pre>
* *
* @param stream the stream to wrap. * @param stream the stream to wrap.
* @param monitor the object that the stream will use for synchronization. When {@code null}, the stream * @param monitor the object that the stream will use for synchronization.
* When {@code null}, the stream
* will synchronize on itself. * will synchronize on itself.
* @return a {@link SyncIntStream} synchronized on {@code monitor} and backed by {@code stream}. * @return a {@link SyncIntStream} synchronized on {@code monitor} and
* backed by {@code stream}.
* @throws NullPointerException if {@code stream == null}. * @throws NullPointerException if {@code stream == null}.
*/ */
public static SyncIntStream synchronizedStream(IntStream stream, Object monitor) { public static SyncIntStream synchronizedStream(IntStream stream, Object monitor) {
@ -1134,20 +1167,31 @@ public class SyncStreams {
/** /**
* Wraps the given {@link LongStream} to make all * Wraps the given {@link LongStream} to make all
* <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps"> * <a href=
* terminal operations</a> acquire the provided monitor's lock before execution. Intermediate operations * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps">
* return streams that are also synchronized on the same object. The created stream will behave identically * terminal operations</a> acquire the provided monitor's lock before
* to the provided stream in all other aspects. Use this to synchronize access to stream's source. * execution. Intermediate operations
* <p><i>The returned {@code LongStream}'s {@link LongStream#iterator() iterator()} and * return streams that are also synchronized on the same object. The created
* {@link LongStream#spliterator() spliterator()} methods return regular non-synchronized iterators and * stream will behave identically
* spliterators respectively</i>. It is the user's responsibility to avoid concurrency issues: * to the provided stream in all other aspects. Use this to synchronize
* access to stream's source.
* <p>
* <i>The returned {@code LongStream}'s {@link LongStream#iterator()
* iterator()} and
* {@link LongStream#spliterator() spliterator()} methods return regular
* non-synchronized iterators and
* spliterators respectively</i>. It is the user's responsibility to avoid
* concurrency issues:
*
* <pre> * <pre>
* synchronized (stream.getMonitor()) { * synchronized (stream.getMonitor()) {
* PrimitiveIterator.OfLong it = stream.iterator(); * PrimitiveIterator.OfLong it = stream.iterator();
* ... * ...
* } * }
* </pre> * </pre>
*
* Usage example: * Usage example:
*
* <pre> * <pre>
* Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;()); * Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;());
* ... * ...
@ -1157,9 +1201,11 @@ public class SyncStreams {
* </pre> * </pre>
* *
* @param stream the stream to wrap. * @param stream the stream to wrap.
* @param monitor the object that the stream will use for synchronization. When {@code null}, the stream * @param monitor the object that the stream will use for synchronization.
* When {@code null}, the stream
* will synchronize on itself. * will synchronize on itself.
* @return a {@link SyncLongStream} synchronized on {@code monitor} and backed by {@code stream}. * @return a {@link SyncLongStream} synchronized on {@code monitor} and
* backed by {@code stream}.
* @throws NullPointerException if {@code stream == null}. * @throws NullPointerException if {@code stream == null}.
*/ */
public static SyncLongStream synchronizedStream(LongStream stream, Object monitor) { public static SyncLongStream synchronizedStream(LongStream stream, Object monitor) {
@ -1169,20 +1215,31 @@ public class SyncStreams {
/** /**
* Wraps the given {@link DoubleStream} to make all * Wraps the given {@link DoubleStream} to make all
* <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps"> * <a href=
* terminal operations</a> acquire the provided monitor's lock before execution. Intermediate operations * "https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps">
* return streams that are also synchronized on the same object. The created stream will behave identically * terminal operations</a> acquire the provided monitor's lock before
* to the provided stream in all other aspects. Use this to synchronize access to stream's source. * execution. Intermediate operations
* <p><i>The returned {@code DoubleStream}'s {@link DoubleStream#iterator() iterator()} and * return streams that are also synchronized on the same object. The created
* {@link DoubleStream#spliterator() spliterator()} methods return regular non-synchronized iterators and * stream will behave identically
* spliterators respectively</i>. It is the user's responsibility to avoid concurrency issues: * to the provided stream in all other aspects. Use this to synchronize
* access to stream's source.
* <p>
* <i>The returned {@code DoubleStream}'s {@link DoubleStream#iterator()
* iterator()} and
* {@link DoubleStream#spliterator() spliterator()} methods return regular
* non-synchronized iterators and
* spliterators respectively</i>. It is the user's responsibility to avoid
* concurrency issues:
*
* <pre> * <pre>
* synchronized (stream.getMonitor()) { * synchronized (stream.getMonitor()) {
* PrimitiveIterator.OfDouble it = stream.iterator(); * PrimitiveIterator.OfDouble it = stream.iterator();
* ... * ...
* } * }
* </pre> * </pre>
*
* Usage example: * Usage example:
*
* <pre> * <pre>
* Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;()); * Set&lt;Object&gt; s = Collections.synchronizedSet(new HashSet&lt;&gt;());
* ... * ...
@ -1192,9 +1249,11 @@ public class SyncStreams {
* </pre> * </pre>
* *
* @param stream the stream to wrap. * @param stream the stream to wrap.
* @param monitor the object that the stream will use for synchronization. When {@code null}, the stream * @param monitor the object that the stream will use for synchronization.
* When {@code null}, the stream
* will synchronize on itself. * will synchronize on itself.
* @return a {@link SyncDoubleStream} synchronized on {@code monitor} and backed by {@code stream}. * @return a {@link SyncDoubleStream} synchronized on {@code monitor} and
* backed by {@code stream}.
* @throws NullPointerException if {@code stream == null}. * @throws NullPointerException if {@code stream == null}.
*/ */
public static SyncDoubleStream synchronizedStream(DoubleStream stream, Object monitor) { public static SyncDoubleStream synchronizedStream(DoubleStream stream, Object monitor) {
@ -1205,6 +1264,7 @@ public class SyncStreams {
/* /*
* Private constructor * Private constructor
*/ */
private SyncStreams() {} private SyncStreams() {
}
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil; package ru.windcorp.jputil;
public class SyntaxException extends Exception { public class SyntaxException extends Exception {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.text.CharacterIterator; import java.text.CharacterIterator;
@ -110,9 +111,12 @@ public class CharArrayIterator implements CharacterIterator {
// @SuppressWarnings("all") Just STFU, this _is_ terrific // @SuppressWarnings("all") Just STFU, this _is_ terrific
// SonarLint: "clone" should not be overridden (java:S2975) // SonarLint: "clone" should not be overridden (java:S2975)
// And I wouldn't have done that if only CharacterIterator had not required exception safety. // And I wouldn't have done that if only CharacterIterator had not required
// SonarLint: "toString()" and "clone()" methods should not return null (java:S2225) // exception safety.
// The clause is unreachable: CharacterArrayIterator implements Cloneable and superclass is Object. // SonarLint: "toString()" and "clone()" methods should not return null
// (java:S2225)
// The clause is unreachable: CharacterArrayIterator implements Cloneable
// and superclass is Object.
@SuppressWarnings({ "squid:S2975", "squid:S2225" }) @SuppressWarnings({ "squid:S2975", "squid:S2225" })
@Override @Override

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.util.function.IntConsumer; import java.util.function.IntConsumer;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.util.Objects; import java.util.Objects;
@ -23,11 +24,11 @@ import ru.windcorp.jputil.ArrayUtil;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public class CharConsumers { public class CharConsumers {
private CharConsumers() {} private CharConsumers() {
}
public static CharConsumer fillArray(char[] array, int offset, int length) { public static CharConsumer fillArray(char[] array, int offset, int length) {
return new ArrayFiller(array, offset, length); return new ArrayFiller(array, offset, length);

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.util.Arrays; import java.util.Arrays;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
public class EscapeException extends Exception { public class EscapeException extends Exception {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.text.CharacterIterator; import java.text.CharacterIterator;
@ -102,7 +103,14 @@ public class Escaper {
} }
public static final Escaper JAVA = new Escaper('\\', 'u', "tbnrf'\"".toCharArray(), "\t\b\n\r\f\'\"".toCharArray(), true, true); public static final Escaper JAVA = new Escaper(
'\\',
'u',
"tbnrf'\"".toCharArray(),
"\t\b\n\r\f\'\"".toCharArray(),
true,
true
);
private final char escapeChar; private final char escapeChar;
private final char unicodeEscapeChar; private final char unicodeEscapeChar;
@ -113,9 +121,13 @@ public class Escaper {
private final boolean strict; private final boolean strict;
protected Escaper( protected Escaper(
char escapeChar, char unicodeEscapeChar, char escapeChar,
char[] safes, char[] unsafes, char unicodeEscapeChar,
boolean preferUnicode, boolean strict) { char[] safes,
char[] unsafes,
boolean preferUnicode,
boolean strict
) {
this.escapeChar = escapeChar; this.escapeChar = escapeChar;
this.unicodeEscapeChar = unicodeEscapeChar; this.unicodeEscapeChar = unicodeEscapeChar;
this.safes = safes; this.safes = safes;
@ -131,13 +143,19 @@ public class Escaper {
throw new IllegalArgumentException("Duplicate unsafe character '" + unsafes[duplicate] + "'"); throw new IllegalArgumentException("Duplicate unsafe character '" + unsafes[duplicate] + "'");
for (char c : safes) { for (char c : safes) {
if (c == escapeChar) throw new IllegalArgumentException("Safe characters contain escape chatacter"); if (c == escapeChar)
if (c == unicodeEscapeChar) throw new IllegalArgumentException("Safe characters contain Unicode escape chatacter"); throw new IllegalArgumentException("Safe characters contain escape chatacter");
if (c == unicodeEscapeChar)
throw new IllegalArgumentException("Safe characters contain Unicode escape chatacter");
} }
for (char c : unsafes) { for (char c : unsafes) {
if (c == escapeChar) throw new IllegalArgumentException("Unsafe characters contain escape chatacter (escape character is escaped automatically)"); if (c == escapeChar)
if (c == unicodeEscapeChar) throw new IllegalArgumentException("Unsafe characters contain Unicode escape chatacter"); throw new IllegalArgumentException(
"Unsafe characters contain escape chatacter (escape character is escaped automatically)"
);
if (c == unicodeEscapeChar)
throw new IllegalArgumentException("Unsafe characters contain Unicode escape chatacter");
} }
} }
@ -151,11 +169,15 @@ public class Escaper {
public void escape(CharReader src, int length, CharPredicate until, CharConsumer output) { public void escape(CharReader src, int length, CharPredicate until, CharConsumer output) {
int end; int end;
if (length < 0) end = Integer.MAX_VALUE; if (length < 0)
else end = src.getPosition() + length; end = Integer.MAX_VALUE;
while (src.has() && else
end = src.getPosition() + length;
while (
src.has() &&
src.getPosition() < end && src.getPosition() < end &&
(until == null || !until.test(src.current()))) (until == null || !until.test(src.current()))
)
escape(src.consume(), output); escape(src.consume(), output);
} }
@ -180,7 +202,8 @@ public class Escaper {
} }
} }
// SonarLint: Assignments should not be made from within sub-expressions (java:S1121) // SonarLint: Assignments should not be made from within sub-expressions
// (java:S1121)
// Seems self-evident enough // Seems self-evident enough
@SuppressWarnings("squid:S1121") @SuppressWarnings("squid:S1121")
@ -195,14 +218,18 @@ public class Escaper {
public int getEscapedLength(CharReader src, int length, CharPredicate until) { public int getEscapedLength(CharReader src, int length, CharPredicate until) {
int end; int end;
if (length < 0) end = Integer.MAX_VALUE; if (length < 0)
else end = src.getPosition() + length; end = Integer.MAX_VALUE;
else
end = src.getPosition() + length;
int result = 0; int result = 0;
while (src.has() && while (
src.has() &&
src.getPosition() < end && src.getPosition() < end &&
(until == null || !until.test(src.current()))) { (until == null || !until.test(src.current()))
) {
result += getEscapedLength(src.consume()); result += getEscapedLength(src.consume());
} }
@ -226,11 +253,15 @@ public class Escaper {
public void unescape(CharReader src, int length, CharPredicate until, CharConsumer output) throws EscapeException { public void unescape(CharReader src, int length, CharPredicate until, CharConsumer output) throws EscapeException {
int end; int end;
if (length < 0) end = Integer.MAX_VALUE; if (length < 0)
else end = src.getPosition() + length; end = Integer.MAX_VALUE;
while (src.has() && else
end = src.getPosition() + length;
while (
src.has() &&
src.getPosition() < end && src.getPosition() < end &&
(until == null || !until.test(src.current()))) { (until == null || !until.test(src.current()))
) {
output.accept(unescapeOneSequence(src)); output.accept(unescapeOneSequence(src));
} }
} }
@ -251,12 +282,10 @@ public class Escaper {
if (src.current() == unicodeEscapeChar) { if (src.current() == unicodeEscapeChar) {
src.next(); src.next();
return (char) ( return (char) (hexValue(src.consume()) << (4 * 3) |
hexValue(src.consume()) << (4 * 3) |
hexValue(src.consume()) << (4 * 2) | hexValue(src.consume()) << (4 * 2) |
hexValue(src.consume()) << (4 * 1) | hexValue(src.consume()) << (4 * 1) |
hexValue(src.consume()) << (4 * 0) hexValue(src.consume()) << (4 * 0));
);
} }
int index = ArrayUtil.firstIndexOf(safes, src.current()); int index = ArrayUtil.firstIndexOf(safes, src.current());
@ -279,14 +308,18 @@ public class Escaper {
public int getUnescapedLength(CharReader src, int length, CharPredicate until) { public int getUnescapedLength(CharReader src, int length, CharPredicate until) {
int end; int end;
if (length < 0) end = Integer.MAX_VALUE; if (length < 0)
else end = src.getPosition() + length; end = Integer.MAX_VALUE;
else
end = src.getPosition() + length;
int result = 0; int result = 0;
while (src.has() && while (
src.has() &&
src.getPosition() < end && src.getPosition() < end &&
(until == null || !until.test(src.current()))) { (until == null || !until.test(src.current()))
) {
skipOneSequence(src); skipOneSequence(src);
result++; result++;
} }
@ -425,13 +458,20 @@ public class Escaper {
*/ */
private static int hexValue(char c) throws EscapeException { private static int hexValue(char c) throws EscapeException {
if (c < '0') throw thisIsNotAHexDigit(c); if (c < '0')
if (c <= '9') return c - '0'; throw thisIsNotAHexDigit(c);
if (c < 'A') throw thisIsNotAHexDigit(c); if (c <= '9')
if (c <= 'F') return c - 'A'; return c - '0';
if (c < 'a') throw thisIsNotAHexDigit(c); if (c < 'A')
if (c <= 'f') return c - 'a'; throw thisIsNotAHexDigit(c);
if (c == CharReader.DONE) throw new EscapeException("Incomplete Unicode escape sequence at the end"); if (c <= 'F')
return c - 'A';
if (c < 'a')
throw thisIsNotAHexDigit(c);
if (c <= 'f')
return c - 'a';
if (c == CharReader.DONE)
throw new EscapeException("Incomplete Unicode escape sequence at the end");
throw thisIsNotAHexDigit(c); throw thisIsNotAHexDigit(c);
} }

View File

@ -1,6 +1,6 @@
/* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -11,7 +11,11 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * 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.jputil.chars; package ru.windcorp.jputil.chars;
import java.text.CharacterIterator; import java.text.CharacterIterator;
@ -76,7 +80,8 @@ public class FancyCharacterIterator implements CharacterIterator {
StringBuilder sb = new StringBuilder("\""); StringBuilder sb = new StringBuilder("\"");
sb.append(data); sb.append(data);
sb.append("\"\n "); sb.append("\"\n ");
for (int i = 0; i < obj.getIndex(); ++i) sb.append(' '); for (int i = 0; i < obj.getIndex(); ++i)
sb.append(' ');
sb.append("^ Here."); sb.append("^ Here.");
return sb.toString(); return sb.toString();
} }
@ -84,9 +89,12 @@ public class FancyCharacterIterator implements CharacterIterator {
// @SuppressWarnings("all") Just STFU, this _is_ terrific // @SuppressWarnings("all") Just STFU, this _is_ terrific
// SonarLint: "clone" should not be overridden (java:S2975) // SonarLint: "clone" should not be overridden (java:S2975)
// And I wouldn't have done that if only CharacterIterator had not required exception safety. // And I wouldn't have done that if only CharacterIterator had not required
// SonarLint: "toString()" and "clone()" methods should not return null (java:S2225) // exception safety.
// The clause is unreachable: CharacterArrayIterator implements Cloneable and superclass is Object. // SonarLint: "toString()" and "clone()" methods should not return null
// (java:S2225)
// The clause is unreachable: CharacterArrayIterator implements Cloneable
// and superclass is Object.
@SuppressWarnings({ "squid:S2975", "squid:S2225" }) @SuppressWarnings({ "squid:S2975", "squid:S2225" })
@Override @Override

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
public class IndentedStringBuilder { public class IndentedStringBuilder {
@ -65,7 +66,8 @@ public class IndentedStringBuilder {
protected void updateIndent() { protected void updateIndent() {
if (indentLevel < indentCache.length) { if (indentLevel < indentCache.length) {
indent = indentCache[indentLevel]; indent = indentCache[indentLevel];
if (indent != null) return; if (indent != null)
return;
} }
char[] fill = getIndentFill(); char[] fill = getIndentFill();
@ -115,7 +117,8 @@ public class IndentedStringBuilder {
} }
public IndentedStringBuilder appendRaw(String str) { public IndentedStringBuilder appendRaw(String str) {
if (str.isEmpty()) return this; // Do not append indent if (str.isEmpty())
return this; // Do not append indent
if (!indentApplied) { if (!indentApplied) {
sb.append(indent); sb.append(indent);

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.io.IOException; import java.io.IOException;
@ -33,7 +34,8 @@ import ru.windcorp.jputil.ArrayUtil;
public class StringUtil { public class StringUtil {
private StringUtil() {} private StringUtil() {
}
private static final String NULL_PLACEHOLDER = "[null]"; private static final String NULL_PLACEHOLDER = "[null]";
private static final String EMPTY_PLACEHOLDER = "[empty]"; private static final String EMPTY_PLACEHOLDER = "[empty]";
@ -153,9 +155,12 @@ public class StringUtil {
String nullSupplier String nullSupplier
) { ) {
if (separator == null) throw new IllegalArgumentException(new NullPointerException()); if (separator == null)
if (supplier == null) return nullSupplier; throw new IllegalArgumentException(new NullPointerException());
if (length == 0) return empty; if (supplier == null)
return nullSupplier;
if (length == 0)
return empty;
if (length > 0) { if (length > 0) {
return supplierToStringExactly( return supplierToStringExactly(
@ -258,9 +263,12 @@ public class StringUtil {
} }
public static String[] split(String src, char separator, int arrayLength) { public static String[] split(String src, char separator, int arrayLength) {
if (arrayLength < 0) throw illegalArrayLength(arrayLength); if (arrayLength < 0)
else if (arrayLength == 0) return new String[0]; throw illegalArrayLength(arrayLength);
else if (arrayLength == 1) return new String[] { src }; else if (arrayLength == 0)
return new String[0];
else if (arrayLength == 1)
return new String[] { src };
String[] result = new String[arrayLength]; String[] result = new String[arrayLength];
@ -299,17 +307,19 @@ public class StringUtil {
} }
public static String[] split(String src, int arrayLength, char... separator) { public static String[] split(String src, int arrayLength, char... separator) {
if (arrayLength < 0) throw illegalArrayLength(arrayLength); if (arrayLength < 0)
else if (arrayLength == 0) return new String[0]; throw illegalArrayLength(arrayLength);
else if (arrayLength == 1) return new String[] { src }; else if (arrayLength == 0)
return new String[0];
else if (arrayLength == 1)
return new String[] { src };
String[] result = new String[arrayLength]; String[] result = new String[arrayLength];
int resultIndex = 0; int resultIndex = 0;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
charLoop: charLoop: for (char c : src.toCharArray()) {
for (char c : src.toCharArray()) {
if ((resultIndex + 1) < arrayLength) { if ((resultIndex + 1) < arrayLength) {
for (char h : separator) { for (char h : separator) {
if (c == h) { if (c == h) {
@ -331,7 +341,8 @@ public class StringUtil {
public static int count(String src, CharPredicate test) { public static int count(String src, CharPredicate test) {
int i = 0; int i = 0;
for (char c : src.toCharArray()) { for (char c : src.toCharArray()) {
if (test.test(c)) i++; if (test.test(c))
i++;
} }
return i; return i;
@ -342,17 +353,19 @@ public class StringUtil {
} }
public static String[] split(String src, int arrayLength, CharPredicate test) { public static String[] split(String src, int arrayLength, CharPredicate test) {
if (arrayLength < 0) throw illegalArrayLength(arrayLength); if (arrayLength < 0)
else if (arrayLength == 0) return new String[0]; throw illegalArrayLength(arrayLength);
else if (arrayLength == 1) return new String[] { src }; else if (arrayLength == 0)
return new String[0];
else if (arrayLength == 1)
return new String[] { src };
String[] result = new String[arrayLength]; String[] result = new String[arrayLength];
int resultIndex = 0; int resultIndex = 0;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
charLoop: charLoop: for (char c : src.toCharArray()) {
for (char c : src.toCharArray()) {
if ( if (
(resultIndex + 1) < arrayLength (resultIndex + 1) < arrayLength
&& &&
@ -372,15 +385,20 @@ public class StringUtil {
} }
/** /**
* Splits {@code src} at index {@code at} discarding the character at that index. * Splits {@code src} at index {@code at} discarding the character at that
* index.
* <p> * <p>
* Indices {@code 0} and {@code src.length() - 1} produce {@code str} excluding * Indices {@code 0} and {@code src.length() - 1} produce {@code str}
* excluding
* the specified character and {@code ""}. * the specified character and {@code ""}.
* <p> * <p>
*
* @param src the String to split * @param src the String to split
* @param at index to split at * @param at index to split at
* @throws IllegalArgumentException if the index is out of bounds for {@code src} * @throws IllegalArgumentException if the index is out of bounds for
* @return an array containing the substrings, in order of encounter in {@code src}. * {@code src}
* @return an array containing the substrings, in order of encounter in
* {@code src}.
* Its length is always 2. * Its length is always 2.
*/ */
public static String[] splitAt(String src, int at) { public static String[] splitAt(String src, int at) {
@ -405,30 +423,38 @@ public class StringUtil {
} }
/** /**
* Splits {@code src} at indices {@code at} discarding characters at those indices. * Splits {@code src} at indices {@code at} discarding characters at those
* indices.
* <p> * <p>
* Indices {@code 0} and {@code src.length() - 1} produce extra zero-length outputs. * Indices {@code 0} and {@code src.length() - 1} produce extra zero-length
* outputs.
* Duplicate indices produce extra zero-length outputs. * Duplicate indices produce extra zero-length outputs.
* <p> * <p>
* Examples: * Examples:
*
* <pre> * <pre>
* splitAt("a.b.c", new int[] {1, 3}) -> {"a", "b", "c"} * splitAt("a.b.c", 1, 3) -> {"a", "b", "c"}
* splitAt("a..b", new int[] {1, 2}) -> {"a", "", "b"} * splitAt("a..b", 1, 2) -> {"a", "", "b"}
* splitAt(".b.", new int[] {0, 2}) -> {"", "b", ""} * splitAt(".b.", 0, 2) -> {"", "b", ""}
* splitAt("a.b", new int[] {1, 1, 1}) -> {"a", "", "", "b"} * splitAt("a.b", 1, 1, 1) -> {"a", "", "", "b"}
* </pre> * </pre>
*
* @param src the String to split * @param src the String to split
* @param at indices to split at, in any order * @param at indices to split at, in any order
* @throws IllegalArgumentException if some index is out of bounds for {@code src} * @throws IllegalArgumentException if some index is out of bounds for
* @return an array containing the substrings, in order of encounter in {@code src}. * {@code src}
* @return an array containing the substrings, in order of encounter in
* {@code src}.
* Its length is always {@code at.length + 1}. * Its length is always {@code at.length + 1}.
*/ */
public static String[] splitAt(String src, int... at) { public static String[] splitAt(String src, int... at) {
Objects.requireNonNull(src, "src"); Objects.requireNonNull(src, "src");
Objects.requireNonNull(at, "at"); Objects.requireNonNull(at, "at");
if (at.length == 0) return new String[] {src}; if (at.length == 0)
if (at.length == 1) return splitAt(src, at[0]); return new String[] { src };
if (at.length == 1)
return splitAt(src, at[0]);
int[] indices; // Always sorted int[] indices; // Always sorted
@ -481,8 +507,7 @@ public class StringUtil {
char current; char current;
int resultIndex = 0; int resultIndex = 0;
mainLoop: mainLoop: for (int srcIndex = 0; srcIndex < src.length(); ++srcIndex) {
for (int srcIndex = 0; srcIndex < src.length(); ++srcIndex) {
current = src.charAt(srcIndex); current = src.charAt(srcIndex);
for (char c : remove) { for (char c : remove) {
@ -528,12 +553,15 @@ public class StringUtil {
} }
if (endPos < beginPos) { if (endPos < beginPos) {
throw new IllegalArgumentException("endPos must be greater than or equal to beginPos (endPos=" throw new IllegalArgumentException(
+ endPos + ", beginPos=" + beginPos + ")"); "endPos must be greater than or equal to beginPos (endPos="
+ endPos + ", beginPos=" + beginPos + ")"
);
} }
if (endPos >= Math.min(a.length, b.length)) { if (endPos >= Math.min(a.length, b.length)) {
return false; // At least one of the arrays does not contain at least one of the required elements return false; // At least one of the arrays does not contain at
// least one of the required elements
} }
for (int i = beginPos; i < endPos; ++i) { for (int i = beginPos; i < endPos; ++i) {
@ -563,9 +591,12 @@ public class StringUtil {
} }
/** /**
* Finds and returns the index of the specified appearance of the specified character * Finds and returns the index of the specified appearance of the specified
* in the given array. The search starts at index 0.<p> * character
* Examples:<p> * in the given array. The search starts at index 0.
* <p>
* Examples:
* <p>
* <table border="1"> * <table border="1">
* <tr> * <tr>
* <th align="center"><code>src</code></th> * <th align="center"><code>src</code></th>
@ -573,15 +604,38 @@ public class StringUtil {
* <th align="center"><code>skip</code></th> * <th align="center"><code>skip</code></th>
* <th align="center">returns</th> * <th align="center">returns</th>
* </tr> * </tr>
* <tr align="center"><td><code>a<u>.</u>b.c</code></td><td><code>'.'</code></td><td><code>0</code></td><td><code>1</code></td></tr> * <tr align="center">
* <tr align="center"><td><code>a.b<u>.</u>c</code></td><td><code>'.'</code></td><td><code>1</code></td><td><code>3</code></td></tr> * <td><code>a<u>.</u>b.c</code></td>
* <tr align="center"><td><code>a.b.c</code></td><td><code>'.'</code></td><td><code>2</code></td><td><code>-1</code></td></tr> * <td><code>'.'</code></td>
* <tr align="center"><td><code>a.b.c</code></td><td><code>'d'</code></td><td><i>any</i></td><td><code>-1</code></td></tr> * <td><code>0</code></td>
* <td><code>1</code></td>
* </tr>
* <tr align="center">
* <td><code>a.b<u>.</u>c</code></td>
* <td><code>'.'</code></td>
* <td><code>1</code></td>
* <td><code>3</code></td>
* </tr>
* <tr align="center">
* <td><code>a.b.c</code></td>
* <td><code>'.'</code></td>
* <td><code>2</code></td>
* <td><code>-1</code></td>
* </tr>
* <tr align="center">
* <td><code>a.b.c</code></td>
* <td><code>'d'</code></td>
* <td><i>any</i></td>
* <td><code>-1</code></td>
* </tr>
* </table> * </table>
*
* @param src - the array to search in. * @param src - the array to search in.
* @param target - the character to search for. * @param target - the character to search for.
* @param skip - the amount of <code>target</code> characters to be skipped. * @param skip - the amount of <code>target</code> characters to be
* @return The index of the <code>skip+1</code>th <code>target</code> character or -1, if none found. * skipped.
* @return The index of the <code>skip+1</code>th <code>target</code>
* character or -1, if none found.
* @see StringUtil#indexFromEnd(char[], char, int) * @see StringUtil#indexFromEnd(char[], char, int)
*/ */
public static int indexFromBeginning(char[] src, char target, int skip) { public static int indexFromBeginning(char[] src, char target, int skip) {
@ -598,9 +652,13 @@ public class StringUtil {
} }
/** /**
* Finds and returns the index of the specified appearance of the specified character * Finds and returns the index of the specified appearance of the specified
* in the given array. The search starts at index <code>src.length - 1</code>.<p> * character
* Examples:<p> * in the given array. The search starts at index
* <code>src.length - 1</code>.
* <p>
* Examples:
* <p>
* <table border="1"> * <table border="1">
* <tr> * <tr>
* <th align="center"><code>src</code></th> * <th align="center"><code>src</code></th>
@ -608,15 +666,38 @@ public class StringUtil {
* <th align="center"><code>skip</code></th> * <th align="center"><code>skip</code></th>
* <th align="center">returns</th> * <th align="center">returns</th>
* </tr> * </tr>
* <tr align="center"><td><code>a.b<u>.</u>c</code></td><td><code>'.'</code></td><td><code>0</code></td><td><code>3</code></td></tr> * <tr align="center">
* <tr align="center"><td><code>a<u>.</u>b.c</code></td><td><code>'.'</code></td><td><code>1</code></td><td><code>1</code></td></tr> * <td><code>a.b<u>.</u>c</code></td>
* <tr align="center"><td><code>a.b.c</code></td><td><code>'.'</code></td><td><code>2</code></td><td><code>-1</code></td></tr> * <td><code>'.'</code></td>
* <tr align="center"><td><code>a.b.c</code></td><td><code>'d'</code></td><td><i>any</i></td><td><code>-1</code></td></tr> * <td><code>0</code></td>
* <td><code>3</code></td>
* </tr>
* <tr align="center">
* <td><code>a<u>.</u>b.c</code></td>
* <td><code>'.'</code></td>
* <td><code>1</code></td>
* <td><code>1</code></td>
* </tr>
* <tr align="center">
* <td><code>a.b.c</code></td>
* <td><code>'.'</code></td>
* <td><code>2</code></td>
* <td><code>-1</code></td>
* </tr>
* <tr align="center">
* <td><code>a.b.c</code></td>
* <td><code>'d'</code></td>
* <td><i>any</i></td>
* <td><code>-1</code></td>
* </tr>
* </table> * </table>
*
* @param src - the array to search in. * @param src - the array to search in.
* @param target - the character to search for. * @param target - the character to search for.
* @param skip - the amount of <code>target</code> characters to be skipped. * @param skip - the amount of <code>target</code> characters to be
* @return The index of the <code>skip+1</code>th <code>target</code>character * skipped.
* @return The index of the <code>skip+1</code>th
* <code>target</code>character
* from the end of the array or -1, if none found. * from the end of the array or -1, if none found.
* @see StringUtil#indexFromBeginning(char[], char, int) * @see StringUtil#indexFromBeginning(char[], char, int)
*/ */
@ -792,8 +873,12 @@ public class StringUtil {
return result; return result;
} }
private static void buildCombinations(StringBuilder sb, Collection<String> result, Iterable<String>[] parts, private static void buildCombinations(
int index) { StringBuilder sb,
Collection<String> result,
Iterable<String>[] parts,
int index
) {
if (index >= parts.length) { if (index >= parts.length) {
result.add(sb.toString()); result.add(sb.toString());
} else { } else {
@ -811,15 +896,21 @@ public class StringUtil {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
int length = 1; int length = 1;
for (String[] array : parts) length *= array.length; for (String[] array : parts)
length *= array.length;
String[] result = new String[length]; String[] result = new String[length];
buildCombinations(sb, result, new int[] { 0 }, parts, 0); buildCombinations(sb, result, new int[] { 0 }, parts, 0);
return result; return result;
} }
private static void buildCombinations(StringBuilder sb, String[] result, int[] resultIndex, String[][] parts, private static void buildCombinations(
int index) { StringBuilder sb,
String[] result,
int[] resultIndex,
String[][] parts,
int index
) {
if (index >= parts.length) { if (index >= parts.length) {
result[resultIndex[0]++] = sb.toString(); result[resultIndex[0]++] = sb.toString();
} else { } else {
@ -887,8 +978,7 @@ public class StringUtil {
result[1] = 'x'; result[1] = 'x';
for (int digit = 0; digit < digits; ++digit) { for (int digit = 0; digit < digits; ++digit) {
result[(digits - digit - 1) + 2] = result[(digits - digit - 1) + 2] = hexDigit(x, digit);
hexDigit(x, digit);
} }
return result; return result;
@ -902,8 +992,10 @@ public class StringUtil {
} }
public static char hexDigit(int value) { public static char hexDigit(int value) {
if (value < 0xA) return (char) ('0' + value); if (value < 0xA)
else return (char) ('A' - 0xA + value); return (char) ('0' + value);
else
return (char) ('A' - 0xA + value);
} }
public static String replaceAll(String source, String substring, String replacement) { public static String replaceAll(String source, String substring, String replacement) {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
public class UncheckedEscapeException extends RuntimeException { public class UncheckedEscapeException extends RuntimeException {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars; package ru.windcorp.jputil.chars;
import java.io.IOException; import java.io.IOException;
@ -85,11 +86,14 @@ public class WordReader implements Iterator<String> {
while (true) { while (true) {
c = nextChar(); c = nextChar();
if (isExhausted) break; if (isExhausted)
break;
if (Character.isWhitespace(c)) { if (Character.isWhitespace(c)) {
if (length == 0) continue; if (length == 0)
else break; continue;
else
break;
} }
if (wordBuffer.length == length) { if (wordBuffer.length == length) {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,20 +14,22 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars.reader; package ru.windcorp.jputil.chars.reader;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public abstract class AbstractCharReader implements CharReader { public abstract class AbstractCharReader implements CharReader {
protected static final int DEFAULT_MARK_STACK_SIZE = 8; protected static final int DEFAULT_MARK_STACK_SIZE = 8;
/** /**
* Current position of this CharReader. The reader maps its input to positions starting from 0. * Current position of this CharReader. The reader maps its input to
* Positions that are negative or lower than 0 are invalid. {@link #current()} * positions starting from 0.
* Positions that are negative or lower than 0 are invalid.
* {@link #current()}
* will throw an exception if position is invalid. * will throw an exception if position is invalid.
*/ */
protected int position = 0; protected int position = 0;
@ -80,7 +82,8 @@ public abstract class AbstractCharReader implements CharReader {
} }
private void ensureMarksCapacity() { private void ensureMarksCapacity() {
if (nextMark < marks.length) return; if (nextMark < marks.length)
return;
int[] newMarks = new int[closestGreaterPowerOf2(nextMark)]; int[] newMarks = new int[closestGreaterPowerOf2(nextMark)];
System.arraycopy(marks, 0, newMarks, 0, nextMark); System.arraycopy(marks, 0, newMarks, 0, nextMark);
marks = newMarks; marks = newMarks;
@ -96,7 +99,8 @@ public abstract class AbstractCharReader implements CharReader {
reset(); reset();
sb.append("\"\n "); sb.append("\"\n ");
for (int i = 0; i < position; ++i) sb.append(' '); for (int i = 0; i < position; ++i)
sb.append(' ');
sb.append("^ (pos " + position + ")"); sb.append("^ (pos " + position + ")");
return sb.toString(); return sb.toString();
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars.reader; package ru.windcorp.jputil.chars.reader;
import java.util.Objects; import java.util.Objects;
@ -23,7 +24,6 @@ import ru.windcorp.jputil.ArrayUtil;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public class ArrayCharReader extends AbstractCharReader { public class ArrayCharReader extends AbstractCharReader {
@ -42,7 +42,8 @@ public class ArrayCharReader extends AbstractCharReader {
*/ */
@Override @Override
public char current() { public char current() {
if (position >= length) return DONE; if (position >= length)
return DONE;
if (position < 0) if (position < 0)
throw new IllegalStateException("Position " + position + " is invalid"); throw new IllegalStateException("Position " + position + " is invalid");
return array[position + offset]; return array[position + offset];

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,12 +14,12 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars.reader; package ru.windcorp.jputil.chars.reader;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public abstract class BufferedCharReader extends AbstractCharReader { public abstract class BufferedCharReader extends AbstractCharReader {
@ -42,7 +42,9 @@ public abstract class BufferedCharReader extends AbstractCharReader {
/** /**
* Acquires the next character. * Acquires the next character.
* @return the character or {@link #DONE} if the end of the reader has been reached *
* @return the character or {@link #DONE} if the end of the reader has been
* reached
*/ */
protected abstract char pullChar(); protected abstract char pullChar();
@ -65,7 +67,8 @@ public abstract class BufferedCharReader extends AbstractCharReader {
} }
private int pullChars(int offset, int length) { private int pullChars(int offset, int length) {
if (exhausted || length == 0) return 0; if (exhausted || length == 0)
return 0;
int pulled = pullChars(buffer, offset, length); int pulled = pullChars(buffer, offset, length);
if (pulled != length) { if (pulled != length) {
@ -82,7 +85,8 @@ public abstract class BufferedCharReader extends AbstractCharReader {
} }
if (getPosition() >= bufferNextIndex) { if (getPosition() >= bufferNextIndex) {
if (exhausted) return DONE; if (exhausted)
return DONE;
ensureBufferCapacity(); ensureBufferCapacity();
@ -92,7 +96,8 @@ public abstract class BufferedCharReader extends AbstractCharReader {
int pulled = pullChars(bufferNextIndex, needToPull); int pulled = pullChars(bufferNextIndex, needToPull);
bufferNextIndex += pulled; bufferNextIndex += pulled;
if (exhausted) return DONE; if (exhausted)
return DONE;
} }
// TODO test the shit out of current() // TODO test the shit out of current()
@ -101,7 +106,8 @@ public abstract class BufferedCharReader extends AbstractCharReader {
} }
private void ensureBufferCapacity() { private void ensureBufferCapacity() {
if (getPosition() < buffer.length) return; if (getPosition() < buffer.length)
return;
char[] newBuffer = new char[closestGreaterPowerOf2(getPosition())]; char[] newBuffer = new char[closestGreaterPowerOf2(getPosition())];
System.arraycopy(buffer, 0, newBuffer, 0, bufferNextIndex); System.arraycopy(buffer, 0, newBuffer, 0, bufferNextIndex);
buffer = newBuffer; buffer = newBuffer;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars.reader; package ru.windcorp.jputil.chars.reader;
import java.io.IOException; import java.io.IOException;
@ -26,7 +27,6 @@ import ru.windcorp.jputil.chars.Escaper;
/** /**
* @author Javapony * @author Javapony
*
*/ */
// SonarLint: Constants should not be defined in interfaces (java:S1214) // SonarLint: Constants should not be defined in interfaces (java:S1214)
@ -38,7 +38,9 @@ public interface CharReader {
char DONE = '\uFFFF'; char DONE = '\uFFFF';
char current(); char current();
int getPosition(); int getPosition();
int setPosition(int position); int setPosition(int position);
default char next() { default char next() {
@ -94,7 +96,8 @@ public interface CharReader {
default char[] getChars(int length) { default char[] getChars(int length) {
char[] result = new char[length]; char[] result = new char[length];
int from = getChars(result); int from = getChars(result);
if (from != length) Arrays.fill(result, from, length, DONE); if (from != length)
Arrays.fill(result, from, length, DONE);
return result; return result;
} }
@ -104,7 +107,8 @@ public interface CharReader {
default String getString(int length) { default String getString(int length) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i = 0; i < length && !isEnd(); ++i) sb.append(consume()); for (int i = 0; i < length && !isEnd(); ++i)
sb.append(consume());
return sb.toString(); return sb.toString();
} }
@ -114,8 +118,10 @@ public interface CharReader {
default boolean match(CharSequence seq) { default boolean match(CharSequence seq) {
for (int i = 0; i < seq.length(); ++i) { for (int i = 0; i < seq.length(); ++i) {
if (isEnd()) return false; if (isEnd())
if (current() != seq.charAt(i)) return false; return false;
if (current() != seq.charAt(i))
return false;
next(); next();
} }
@ -135,8 +141,10 @@ public interface CharReader {
default boolean match(char[] array) { default boolean match(char[] array) {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
if (isEnd()) return false; if (isEnd())
if (current() != array[i]) return false; return false;
if (current() != array[i])
return false;
next(); next();
} }
@ -170,8 +178,10 @@ public interface CharReader {
} }
/** /**
* Skips to the end of the current line. Both <code>"\n"</code>, <code>"\r"</code> * Skips to the end of the current line. Both <code>"\n"</code>,
* <code>"\r"</code>
* and <code>"\r\n"</code> are considered line separators. * and <code>"\r\n"</code> are considered line separators.
*
* @return the amount of characters in the skipped line * @return the amount of characters in the skipped line
*/ */
default int skipLine() { default int skipLine() {
@ -209,7 +219,8 @@ public interface CharReader {
reset(); reset();
char[] result = new char[length]; char[] result = new char[length];
for (int i = 0; i < length; ++i) result[i] = consume(); for (int i = 0; i < length; ++i)
result[i] = consume();
return result; return result;
} }
@ -234,7 +245,8 @@ public interface CharReader {
reset(); reset();
char[] result = new char[length]; char[] result = new char[length];
for (int i = 0; i < result.length; ++i) result[i] = consume(); for (int i = 0; i < result.length; ++i)
result[i] = consume();
return result; return result;
} }
@ -242,13 +254,15 @@ public interface CharReader {
mark(); mark();
int result = 0; int result = 0;
while (consume() != DONE) result++; while (consume() != DONE)
result++;
reset(); reset();
return result; return result;
} }
int mark(); int mark();
int forget(); int forget();
default int reset() { default int reset() {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars.reader; package ru.windcorp.jputil.chars.reader;
import java.io.InputStream; import java.io.InputStream;
@ -29,11 +30,11 @@ import ru.windcorp.jputil.chars.CharSupplier;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public class CharReaders { public class CharReaders {
private CharReaders() {} private CharReaders() {
}
public static CharReader wrap(char[] array, int offset, int length) { public static CharReader wrap(char[] array, int offset, int length) {
return new ArrayCharReader(array, offset, length); return new ArrayCharReader(array, offset, length);

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars.reader; package ru.windcorp.jputil.chars.reader;
import java.io.IOException; import java.io.IOException;
@ -22,7 +23,6 @@ import java.io.Reader;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public class ReaderCharReader extends BufferedCharReader { public class ReaderCharReader extends BufferedCharReader {
@ -47,7 +47,8 @@ public class ReaderCharReader extends BufferedCharReader {
} }
/** /**
* @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChars(char[], int, int) * @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChars(char[],
* int, int)
*/ */
@Override @Override
protected int pullChars(char[] buffer, int offset, int length) { protected int pullChars(char[] buffer, int offset, int length) {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,14 +14,14 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.chars.reader; package ru.windcorp.jputil.chars.reader;
import java.util.Objects; import java.util.Objects;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public class StringCharReader extends AbstractCharReader { public class StringCharReader extends AbstractCharReader {
@ -37,7 +37,9 @@ public class StringCharReader extends AbstractCharReader {
int end = offset + length; int end = offset + length;
if (end > str.length() || offset < 0) if (end > str.length() || offset < 0)
throw new IllegalArgumentException("String contains [0; " + str.length() + "), requested [" + offset + "; " + end + ")"); throw new IllegalArgumentException(
"String contains [0; " + str.length() + "), requested [" + offset + "; " + end + ")"
);
this.offset = offset; this.offset = offset;
this.length = length; this.length = length;
@ -48,7 +50,8 @@ public class StringCharReader extends AbstractCharReader {
*/ */
@Override @Override
public char current() { public char current() {
if (position >= length) return DONE; if (position >= length)
return DONE;
if (position < 0) if (position < 0)
throw new IllegalStateException("Position " + position + " is invalid"); throw new IllegalStateException("Position " + position + " is invalid");
return str.charAt(position + offset); return str.charAt(position + offset);

View File

@ -1,3 +1,21 @@
/*
* JPUtil
* Copyright (C) 2019-2021 OLEGSHA/Javapony 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.jputil.functions; package ru.windcorp.jputil.functions;
@FunctionalInterface @FunctionalInterface

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.functions; package ru.windcorp.jputil.functions;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -44,7 +45,8 @@ public interface ThrowingBiConsumer<T, U, E extends Exception> {
public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat( public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat(
ThrowingBiConsumer<? super T, ? super U, ? extends E> first, ThrowingBiConsumer<? super T, ? super U, ? extends E> first,
ThrowingBiConsumer<? super T, ? super U, ? extends E> second) { ThrowingBiConsumer<? super T, ? super U, ? extends E> second
) {
return (t, u) -> { return (t, u) -> {
first.accept(t, u); first.accept(t, u);
second.accept(t, u); second.accept(t, u);
@ -53,7 +55,8 @@ public interface ThrowingBiConsumer<T, U, E extends Exception> {
public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat( public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat(
BiConsumer<? super T, ? super U> first, BiConsumer<? super T, ? super U> first,
ThrowingBiConsumer<? super T, ? super U, E> second) { ThrowingBiConsumer<? super T, ? super U, E> second
) {
return (t, u) -> { return (t, u) -> {
first.accept(t, u); first.accept(t, u);
second.accept(t, u); second.accept(t, u);
@ -62,7 +65,8 @@ public interface ThrowingBiConsumer<T, U, E extends Exception> {
public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat( public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat(
ThrowingBiConsumer<? super T, ? super U, E> first, ThrowingBiConsumer<? super T, ? super U, E> first,
BiConsumer<? super T, ? super U> second) { BiConsumer<? super T, ? super U> second
) {
return (t, u) -> { return (t, u) -> {
first.accept(t, u); first.accept(t, u);
second.accept(t, u); second.accept(t, u);

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.functions; package ru.windcorp.jputil.functions;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -38,21 +39,30 @@ public interface ThrowingConsumer<T, E extends Exception> {
}; };
} }
public static <T, E extends Exception> ThrowingConsumer<T, E> concat(ThrowingConsumer<? super T, ? extends E> first, ThrowingConsumer<? super T, ? extends E> second) { public static <T, E extends Exception> ThrowingConsumer<T, E> concat(
ThrowingConsumer<? super T, ? extends E> first,
ThrowingConsumer<? super T, ? extends E> second
) {
return t -> { return t -> {
first.accept(t); first.accept(t);
second.accept(t); second.accept(t);
}; };
} }
public static <T, E extends Exception> ThrowingConsumer<T, E> concat(Consumer<? super T> first, ThrowingConsumer<? super T, ? extends E> second) { public static <T, E extends Exception> ThrowingConsumer<T, E> concat(
Consumer<? super T> first,
ThrowingConsumer<? super T, ? extends E> second
) {
return t -> { return t -> {
first.accept(t); first.accept(t);
second.accept(t); second.accept(t);
}; };
} }
public static <T, E extends Exception> ThrowingConsumer<T, E> concat(ThrowingConsumer<? super T, ? extends E> first, Consumer<? super T> second) { public static <T, E extends Exception> ThrowingConsumer<T, E> concat(
ThrowingConsumer<? super T, ? extends E> first,
Consumer<? super T> second
) {
return t -> { return t -> {
first.accept(t); first.accept(t);
second.accept(t); second.accept(t);

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.functions; package ru.windcorp.jputil.functions;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -27,14 +28,18 @@ public interface ThrowingFunction<T, R, E extends Exception> {
R apply(T t) throws E; R apply(T t) throws E;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler, Function<? super T, ? extends R> value) { default Function<T, R> withHandler(
BiConsumer<? super T, ? super E> handler,
Function<? super T, ? extends R> value
) {
return t -> { return t -> {
try { try {
return apply(t); return apply(t);
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
if (handler != null) handler.accept(t, (E) e); if (handler != null)
handler.accept(t, (E) e);
return value == null ? null : value.apply(t); return value == null ? null : value.apply(t);
} }
}; };
@ -54,19 +59,22 @@ public interface ThrowingFunction<T, R, E extends Exception> {
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose( public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
ThrowingFunction<? super T, I, ? extends E> first, ThrowingFunction<? super T, I, ? extends E> first,
ThrowingFunction<? super I, ? extends R, ? extends E> second) { ThrowingFunction<? super I, ? extends R, ? extends E> second
) {
return t -> second.apply(first.apply(t)); return t -> second.apply(first.apply(t));
} }
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose( public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
Function<? super T, I> first, Function<? super T, I> first,
ThrowingFunction<? super I, ? extends R, E> second) { ThrowingFunction<? super I, ? extends R, E> second
) {
return t -> second.apply(first.apply(t)); return t -> second.apply(first.apply(t));
} }
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose( public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
ThrowingFunction<? super T, I, E> first, ThrowingFunction<? super T, I, E> first,
Function<? super I, ? extends R> second) { Function<? super I, ? extends R> second
) {
return t -> second.apply(first.apply(t)); return t -> second.apply(first.apply(t));
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.functions; package ru.windcorp.jputil.functions;
import java.util.function.Consumer; import java.util.function.Consumer;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.functions; package ru.windcorp.jputil.functions;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -33,7 +34,8 @@ public interface ThrowingSupplier<T, E extends Exception> {
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
if (handler != null) handler.accept((E) e); if (handler != null)
handler.accept((E) e);
return value == null ? null : value.get(); return value == null ? null : value.get();
} }
}; };

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.iterators; package ru.windcorp.jputil.iterators;
import java.util.Iterator; import java.util.Iterator;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.iterators; package ru.windcorp.jputil.iterators;
import java.util.Iterator; import java.util.Iterator;
@ -22,7 +23,6 @@ import java.util.function.Function;
/** /**
* @author Javapony * @author Javapony
*
*/ */
public class FunctionIterator<T, E> implements Iterator<E> { public class FunctionIterator<T, E> implements Iterator<E> {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.iterators; package ru.windcorp.jputil.iterators;
import java.util.Iterator; import java.util.Iterator;
@ -46,7 +47,8 @@ public class PeekingIterator<E> implements Iterator<E> {
return next; return next;
} }
// SonarLint: "Iterator.next()" methods should throw "NoSuchElementException" (java:S2272) // SonarLint: "Iterator.next()" methods should throw
// "NoSuchElementException" (java:S2272)
// peek() throws NoSuchElementException as expected // peek() throws NoSuchElementException as expected
@SuppressWarnings("squid:S2272") @SuppressWarnings("squid:S2272")

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.iterators; package ru.windcorp.jputil.iterators;
import java.util.Iterator; import java.util.Iterator;
@ -48,8 +49,10 @@ public class RangeIterator<E> implements Iterator<E> {
public E next() { public E next() {
update(); update();
if (nextIndex >= from + amount) { if (nextIndex >= from + amount) {
throw new NoSuchElementException("RangeIterator about to retrieve element " + nextIndex throw new NoSuchElementException(
+ " which exceeds upper boundary " + (from + amount)); "RangeIterator about to retrieve element " + nextIndex
+ " which exceeds upper boundary " + (from + amount)
);
} }
E result = parent.next(); E result = parent.next();

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.iterators; package ru.windcorp.jputil.iterators;
import java.util.ArrayList; import java.util.ArrayList;
@ -46,7 +47,8 @@ public class Reiterator<E> implements Iterable<E> {
public E next() { public E next() {
E result; E result;
synchronized (source) { synchronized (source) {
if (!hasNext()) throw new NoSuchElementException(); if (!hasNext())
throw new NoSuchElementException();
result = data.get(index); result = data.get(index);
} }
index++; index++;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
public abstract class AbstractSelectorOperator implements SelectorOperator { public abstract class AbstractSelectorOperator implements SelectorOperator {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import ru.windcorp.jputil.SyntaxException; import ru.windcorp.jputil.SyntaxException;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import ru.windcorp.jputil.SyntaxException; import ru.windcorp.jputil.SyntaxException;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.Deque; import java.util.Deque;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.Deque; import java.util.Deque;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.Deque; import java.util.Deque;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.Deque; import java.util.Deque;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.Deque; import java.util.Deque;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.function.Predicate; import java.util.function.Predicate;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.function.Predicate; import java.util.function.Predicate;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.Deque; import java.util.Deque;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* JPUtil * JPUtil
* Copyright (C) 2019 Javapony/OLEGSHA * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.jputil.selectors; package ru.windcorp.jputil.selectors;
import java.util.ArrayList; import java.util.ArrayList;
@ -33,11 +34,10 @@ public class SelectorSystem<T> {
public static final char EXPRESSION_OPEN = '('; public static final char EXPRESSION_OPEN = '(';
public static final char EXPRESSION_CLOSE = ')'; public static final char EXPRESSION_CLOSE = ')';
private final Collection<Selector<T>> selectors = private final Collection<Selector<T>> selectors = Collections.synchronizedCollection(new ArrayList<Selector<T>>());
Collections.synchronizedCollection(new ArrayList<Selector<T>>());
private final Collection<SelectorOperator> operators = private final Collection<SelectorOperator> operators = Collections
Collections.synchronizedCollection(new ArrayList<SelectorOperator>()); .synchronizedCollection(new ArrayList<SelectorOperator>());
private String stackPrefix = null; private String stackPrefix = null;
@ -125,8 +125,7 @@ public class SelectorSystem<T> {
synchronized (getSelectorOperators()) { synchronized (getSelectorOperators()) {
synchronized (getSelectors()) { synchronized (getSelectors()) {
tokenCycle: tokenCycle: while (tokens.hasNext()) {
while (tokens.hasNext()) {
token = tokens.next(); token = tokens.next();
for (SelectorOperator operator : getSelectorOperators()) { for (SelectorOperator operator : getSelectorOperators()) {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia; package ru.windcorp.progressia;
public class Progressia { public class Progressia {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia; package ru.windcorp.progressia;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
@ -39,7 +40,7 @@ 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()); CrashReports.registerProvider(new ScreenContextProvider());
// Analyzers // Analyzers
CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer()); CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer());

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia; package ru.windcorp.progressia;
public interface Proxy { public interface Proxy {

View File

@ -1,3 +1,21 @@
/*
* 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.client; package ru.windcorp.progressia.client;
import ru.windcorp.progressia.client.comms.DefaultClientCommsListener; import ru.windcorp.progressia.client.comms.DefaultClientCommsListener;
@ -51,9 +69,11 @@ public class Client {
return; return;
} }
getCamera().setAnchor(new EntityAnchor( getCamera().setAnchor(
new EntityAnchor(
getWorld().getEntityRenderable(entity) getWorld().getEntityRenderable(entity)
)); )
);
} }
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,10 +14,12 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
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;
@ -25,10 +27,12 @@ import ru.windcorp.progressia.client.graphics.font.GNUUnifontLoader;
import ru.windcorp.progressia.client.graphics.font.Typefaces; import ru.windcorp.progressia.client.graphics.font.Typefaces;
import ru.windcorp.progressia.client.graphics.texture.Atlases; import ru.windcorp.progressia.client.graphics.texture.Atlases;
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
import ru.windcorp.progressia.client.localization.Localizer;
import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.common.resource.ResourceManager;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.server.ServerState;
import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestContent;
import ru.windcorp.progressia.test.TestMusicPlayer;
public class ClientProxy implements Proxy { public class ClientProxy implements Proxy {
@ -38,17 +42,26 @@ public class ClientProxy implements Proxy {
try { try {
RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init); RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init);
RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init);
RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz")))); RenderTaskQueue.waitAndInvoke(
() -> Typefaces
.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz")))
);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw CrashReports.report(e, "ClientProxy failed"); throw CrashReports.report(e, "ClientProxy failed");
} }
Localizer.getInstance().setLanguage("en-US");
TestContent.registerContent(); TestContent.registerContent();
Atlases.loadAllAtlases(); Atlases.loadAllAtlases();
AudioSystem.initialize();
ServerState.startServer(); ServerState.startServer();
ClientState.connectToLocalServer(); ClientState.connectToLocalServer();
TestMusicPlayer.start();
} }
} }

View File

@ -1,3 +1,21 @@
/*
* 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.client; package ru.windcorp.progressia.client;
import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel;
@ -5,7 +23,7 @@ import ru.windcorp.progressia.client.graphics.GUI;
import ru.windcorp.progressia.client.graphics.world.LayerWorld; import ru.windcorp.progressia.client.graphics.world.LayerWorld;
import ru.windcorp.progressia.common.world.WorldData; import ru.windcorp.progressia.common.world.WorldData;
import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.server.ServerState;
import ru.windcorp.progressia.test.LayerTestGUI; import ru.windcorp.progressia.test.LayerAbout;
import ru.windcorp.progressia.test.LayerTestUI; import ru.windcorp.progressia.test.LayerTestUI;
import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.test.TestContent;
@ -37,10 +55,11 @@ public class ClientState {
GUI.addBottomLayer(new LayerWorld(client)); GUI.addBottomLayer(new LayerWorld(client));
GUI.addTopLayer(new LayerTestUI()); GUI.addTopLayer(new LayerTestUI());
GUI.addTopLayer(new LayerTestGUI()); GUI.addTopLayer(new LayerAbout());
} }
private ClientState() {} private ClientState() {
}
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client; package ru.windcorp.progressia.client;
import ru.windcorp.progressia.ProgressiaLauncher; import ru.windcorp.progressia.ProgressiaLauncher;

View File

@ -1,3 +1,21 @@
/*
* 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.client.audio; package ru.windcorp.progressia.client.audio;
public enum AudioFormat { public enum AudioFormat {

View File

@ -1,3 +1,21 @@
/*
* 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.client.audio; package ru.windcorp.progressia.client.audio;
import org.lwjgl.openal.*; import org.lwjgl.openal.*;
@ -5,6 +23,7 @@ import ru.windcorp.progressia.client.audio.backend.AudioReader;
import ru.windcorp.progressia.client.audio.backend.Listener; import ru.windcorp.progressia.client.audio.backend.Listener;
import ru.windcorp.progressia.client.audio.backend.SoundType; import ru.windcorp.progressia.client.audio.backend.SoundType;
import ru.windcorp.progressia.client.audio.backend.Speaker; import ru.windcorp.progressia.client.audio.backend.Speaker;
import ru.windcorp.progressia.common.resource.Resource;
import static org.lwjgl.openal.AL11.*; import static org.lwjgl.openal.AL11.*;
import static org.lwjgl.openal.ALC10.*; import static org.lwjgl.openal.ALC10.*;
@ -22,7 +41,6 @@ public class AudioManager {
private static List<Speaker> soundSpeakers = new ArrayList<>(SOUNDS_NUM); private static List<Speaker> soundSpeakers = new ArrayList<>(SOUNDS_NUM);
private static Speaker musicSpeaker; private static Speaker musicSpeaker;
private static ArrayList<SoundType> soundsBuffer = new ArrayList<>();
public static void initAL() { public static void initAL() {
String defaultDeviceName = alcGetString( String defaultDeviceName = alcGetString(
@ -57,37 +75,27 @@ public class AudioManager {
lastSoundIndex = 0; lastSoundIndex = 0;
} }
speaker = soundSpeakers.get(lastSoundIndex); speaker = soundSpeakers.get(lastSoundIndex);
} while (speaker.getState() } while (
.equals(Speaker.State.PLAYING_LOOP)); speaker.getState()
.equals(Speaker.State.PLAYING_LOOP)
);
return speaker; return speaker;
} }
private static SoundType findSoundType(String soundID) throws Exception { public static Speaker initSpeaker(SoundType st) {
for (SoundType s : soundsBuffer) {
if (s.getId().equals(soundID)) {
return s;
}
}
throw new Exception("ERROR: The selected sound is not loaded or" +
" not exists");
}
public static Speaker initSpeaker(String soundID) {
Speaker speaker = getLastSpeaker(); Speaker speaker = getLastSpeaker();
try { try {
findSoundType(soundID).initSpeaker(speaker); st.initSpeaker(speaker);
} catch (Exception ex) } catch (Exception ex) {
{
throw new RuntimeException(); throw new RuntimeException();
} }
return speaker; return speaker;
} }
public static Speaker initMusicSpeaker(String soundID) { public static Speaker initMusicSpeaker(SoundType st) {
try { try {
findSoundType(soundID).initSpeaker(musicSpeaker); st.initSpeaker(musicSpeaker);
} catch (Exception ex) } catch (Exception ex) {
{
throw new RuntimeException(); throw new RuntimeException();
} }
return musicSpeaker; return musicSpeaker;
@ -100,12 +108,11 @@ public class AudioManager {
} }
} }
public static void loadSound(String path, String id, AudioFormat format) { public static void loadSound(Resource resource, String id, AudioFormat format) {
if (format == AudioFormat.MONO) { if (format == AudioFormat.MONO) {
soundsBuffer.add(AudioReader.readAsMono(path, id)); AudioRegistry.getInstance().register(AudioReader.readAsMono(resource, id));
} else } else {
{ AudioRegistry.getInstance().register(AudioReader.readAsStereo(resource, id));
soundsBuffer.add(AudioReader.readAsStereo(path, id));
} }
} }
@ -128,8 +135,7 @@ public class AudioManager {
return deviceCapabilities; return deviceCapabilities;
} }
public static void createBuffers() public static void createBuffers() {
{
for (int i = 0; i < SOUNDS_NUM; ++i) { for (int i = 0; i < SOUNDS_NUM; ++i) {
soundSpeakers.add(new Speaker()); soundSpeakers.add(new Speaker());
} }

View File

@ -0,0 +1,34 @@
/*
* 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.client.audio;
import ru.windcorp.progressia.client.audio.backend.SoundType;
import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry;
public class AudioRegistry extends NamespacedInstanceRegistry<SoundType> {
private static final AudioRegistry INSTANCE = new AudioRegistry();
/**
* @return the instance
*/
public static AudioRegistry getInstance() {
return INSTANCE;
}
}

View File

@ -1,5 +1,25 @@
/*
* 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.client.audio; package ru.windcorp.progressia.client.audio;
import ru.windcorp.progressia.common.resource.ResourceManager;
public class AudioSystem { public class AudioSystem {
static public void initialize() { static public void initialize() {
AudioManager.initAL(); AudioManager.initAL();
@ -9,8 +29,10 @@ public class AudioSystem {
} }
static void loadAudioData() { static void loadAudioData() {
AudioManager.loadSound("assets/sounds/block_destroy_clap.ogg", AudioManager.loadSound(
ResourceManager.getResource("assets/sounds/block_destroy_clap.ogg"),
"Progressia:BlockDestroy", "Progressia:BlockDestroy",
AudioFormat.MONO); AudioFormat.MONO
);
} }
} }

View File

@ -1,70 +1,55 @@
/*
* 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.client.audio; package ru.windcorp.progressia.client.audio;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
import ru.windcorp.progressia.client.audio.backend.SoundType;
import ru.windcorp.progressia.client.audio.backend.Speaker; import ru.windcorp.progressia.client.audio.backend.Speaker;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class Music extends Namespaced { public class Music
private Vec3 position = new Vec3(); extends Sound {
private Vec3 velocity = new Vec3();
private float pitch = 1.0f;
private float gain = 1.0f;
public Music(String id)
{ public Music(SoundType soundType, int timeLength, float pitch, float gain) {
super(soundType, timeLength, new Vec3(), new Vec3(), pitch, gain);
}
public Music(SoundType soundType) {
super(soundType);
}
public Music(String id, int timeLength, float pitch, float gain) {
super(id, timeLength, new Vec3(), new Vec3(), pitch, gain);
}
public Music(String id) {
super(id); super(id);
} }
public Music(String id, @Override
Vec3 position, protected Speaker initSpeaker() {
Vec3 velocity, return AudioManager.initMusicSpeaker(soundType);
float pitch,
float gain)
{
this(id);
this.position = position;
this.velocity = velocity;
this.pitch = pitch;
this.gain = gain;
} }
public void play(boolean loop) @Override
{ public void setPosition(Vec3 position) {
Speaker speaker = AudioManager.initMusicSpeaker(this.getId()); throw new UnsupportedOperationException();
speaker.setGain(gain);
speaker.setPitch(pitch);
speaker.setPosition(position);
speaker.setVelocity(velocity);
if (loop) {
speaker.playLoop();
} else {
speaker.play();
}
}
public void setGain(float gain) {
this.gain = gain;
}
public void setPitch(float pitch) { this.pitch = pitch; }
public void setVelocity(Vec3 velocity) {
this.velocity = velocity;
}
public Vec3 getPosition() { return position; }
public float getGain() {
return gain;
}
public Vec3 getVelocity() {
return velocity;
}
public float getPitch() {
return pitch;
} }
} }

View File

@ -0,0 +1,127 @@
/*
* 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.client.audio;
import glm.vec._3.Vec3;
import ru.windcorp.progressia.client.audio.backend.SoundType;
import ru.windcorp.progressia.client.audio.backend.Speaker;
public class Sound {
protected Vec3 position = new Vec3(0f, 0f, 0f);
protected Vec3 velocity = new Vec3(0f, 0f, 0f);
protected float pitch = 1.0f;
protected float gain = 1.0f;
protected int timeLength = 0;
protected SoundType soundType;
public Sound(SoundType soundType) {
this.soundType = soundType;
}
public Sound(String id) {
this(AudioRegistry.getInstance().get(id));
}
public Sound(
String id,
int timeLength,
Vec3 position,
Vec3 velocity,
float pitch,
float gain
) {
this(id);
this.position = position;
this.velocity = velocity;
this.pitch = pitch;
this.gain = gain;
}
public Sound(
SoundType soundType,
int timeLength,
Vec3 position,
Vec3 velocity,
float pitch,
float gain
) {
this(soundType);
this.position = position;
this.velocity = velocity;
this.pitch = pitch;
this.gain = gain;
}
protected Speaker initSpeaker() {
return AudioManager.initSpeaker(soundType);
}
public void play(boolean loop) {
Speaker speaker = initSpeaker();
speaker.setGain(gain);
speaker.setPitch(pitch);
speaker.setPosition(position);
speaker.setVelocity(velocity);
if (loop) {
speaker.playLoop();
} else {
speaker.play();
}
}
public void setGain(float gain) {
this.gain = gain;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
public void setPosition(Vec3 position) {
this.position = position;
}
public void setVelocity(Vec3 velocity) {
this.velocity = velocity;
}
public Vec3 getPosition() {
return position;
}
public float getGain() {
return gain;
}
public Vec3 getVelocity() {
return velocity;
}
public float getPitch() {
return pitch;
}
public double getDuration() {
return soundType.getDuration();
}
}

View File

@ -1,78 +0,0 @@
package ru.windcorp.progressia.client.audio;
import glm.vec._3.Vec3;
import ru.windcorp.progressia.client.audio.backend.Speaker;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class SoundEffect
extends Namespaced {
private Vec3 position = new Vec3();
private Vec3 velocity = new Vec3();
private float pitch = 1.0f;
private float gain = 1.0f;
public SoundEffect(String id)
{
super(id);
}
public SoundEffect(String id,
Vec3 position,
Vec3 velocity,
float pitch,
float gain)
{
this(id);
this.position = position;
this.velocity = velocity;
this.pitch = pitch;
this.gain = gain;
}
public void play(boolean loop)
{
Speaker speaker = AudioManager.initSpeaker(this.getId());
speaker.setGain(gain);
speaker.setPitch(pitch);
speaker.setPosition(position);
speaker.setVelocity(velocity);
if (loop) {
speaker.playLoop();
} else {
speaker.play();
}
}
public void setGain(float gain) {
this.gain = gain;
}
public void setPitch(float pitch) { this.pitch = pitch; }
public void setPosition(Vec3 position) {
this.position = position;
}
public void setVelocity(Vec3 velocity) {
this.velocity = velocity;
}
public Vec3 getPosition() {
return position;
}
public float getGain() {
return gain;
}
public Vec3 getVelocity() {
return velocity;
}
public float getPitch() {
return pitch;
}
}

View File

@ -1,3 +1,21 @@
/*
* 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.client.audio.backend; package ru.windcorp.progressia.client.audio.backend;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
@ -11,27 +29,30 @@ import static org.lwjgl.openal.AL10.*;
public class AudioReader { public class AudioReader {
private AudioReader() {} private AudioReader() {
}
// TODO fix converting from mono-stereo // TODO fix converting from mono-stereo
private static SoundType readAsSpecified(String path, String id, int format) { private static SoundType readAsSpecified(Resource resource, String id, int format) {
IntBuffer channelBuffer = BufferUtils.createIntBuffer(1); IntBuffer channelBuffer = BufferUtils.createIntBuffer(1);
IntBuffer rateBuffer = BufferUtils.createIntBuffer(1); IntBuffer rateBuffer = BufferUtils.createIntBuffer(1);
Resource res = ResourceManager.getResource(path); ShortBuffer rawAudio = decodeVorbis(resource, channelBuffer, rateBuffer);
ShortBuffer rawAudio = decodeVorbis(res, channelBuffer, rateBuffer); return new SoundType(
id,
return new SoundType(id, rawAudio, format, rawAudio,
rateBuffer.get(0)); format,
rateBuffer.get(0)
);
} }
public static SoundType readAsMono(String path, String id) { public static SoundType readAsMono(Resource resource, String id) {
return readAsSpecified(path, id, AL_FORMAT_MONO16); return readAsSpecified(resource, id, AL_FORMAT_MONO16);
} }
public static SoundType readAsStereo(String path,String id) { public static SoundType readAsStereo(Resource resource, String id) {
return readAsSpecified(path, id, AL_FORMAT_STEREO16); return readAsSpecified(resource, id, AL_FORMAT_STEREO16);
} }
private static ShortBuffer decodeVorbis( private static ShortBuffer decodeVorbis(

View File

@ -1,3 +1,21 @@
/*
* 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.client.audio.backend; package ru.windcorp.progressia.client.audio.backend;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
@ -12,7 +30,8 @@ public class Listener {
private static final Listener INSTANCE = new Listener(); private static final Listener INSTANCE = new Listener();
private Listener() {} private Listener() {
}
public static Listener getInstance() { public static Listener getInstance() {
return INSTANCE; return INSTANCE;
@ -72,9 +91,17 @@ public class Listener {
private void applyParams() { private void applyParams() {
alListener3f(AL_POSITION, position.x, position.y, position.z); alListener3f(AL_POSITION, position.x, position.y, position.z);
alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z); alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z);
alListenerfv(AL_ORIENTATION, new float[] { alListenerfv(
oriAt.x, oriAt.y, oriAt.z, oriUp.x, oriUp.y, oriUp.z AL_ORIENTATION,
}); new float[] {
oriAt.x,
oriAt.y,
oriAt.z,
oriUp.x,
oriUp.y,
oriUp.z
}
);
} }
} }

View File

@ -1,8 +1,29 @@
/*
* 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.client.audio.backend; package ru.windcorp.progressia.client.audio.backend;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import org.lwjgl.openal.AL10;
import static org.lwjgl.openal.AL11.*; import static org.lwjgl.openal.AL11.*;
public class SoundType extends Namespaced { public class SoundType extends Namespaced {
@ -11,9 +32,14 @@ public class SoundType extends Namespaced {
private int sampleRate; private int sampleRate;
private int format; private int format;
private int audioBuffer; private int audioBuffer;
private double duration;
public SoundType(String id, ShortBuffer rawAudio, public SoundType(
int format, int sampleRate) { String id,
ShortBuffer rawAudio,
int format,
int sampleRate
) {
super(id); super(id);
this.rawAudio = rawAudio; this.rawAudio = rawAudio;
this.sampleRate = sampleRate; this.sampleRate = sampleRate;
@ -24,9 +50,14 @@ public class SoundType extends Namespaced {
private void createAudioBuffer() { private void createAudioBuffer() {
this.audioBuffer = alGenBuffers(); this.audioBuffer = alGenBuffers();
alBufferData(audioBuffer, format, rawAudio, sampleRate); alBufferData(audioBuffer, format, rawAudio, sampleRate);
duration = rawAudio.limit() / (double) sampleRate / (format == AL10.AL_FORMAT_STEREO16 ? 2 : 1);
} }
public void initSpeaker(Speaker speaker) { public void initSpeaker(Speaker speaker) {
speaker.setAudioData(audioBuffer); speaker.setAudioData(audioBuffer);
} }
public double getDuration() {
return duration;
}
} }

View File

@ -1,3 +1,21 @@
/*
* 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.client.audio.backend; package ru.windcorp.progressia.client.audio.backend;
import glm.vec._3.Vec3; import glm.vec._3.Vec3;
@ -85,8 +103,7 @@ public class Speaker {
final int speakerState = alGetSourcei(sourceData, AL_SOURCE_STATE); final int speakerState = alGetSourcei(sourceData, AL_SOURCE_STATE);
if (speakerState == AL_PLAYING) { if (speakerState == AL_PLAYING) {
return true; return true;
} } else {
else {
state = State.NOT_PLAYING; state = State.NOT_PLAYING;
return false; return false;
} }
@ -103,6 +120,7 @@ public class Speaker {
} }
public void setAudioData(int audioData) { public void setAudioData(int audioData) {
stop();
this.audioData = audioData; this.audioData = audioData;
alSourcei(this.sourceData, AL_BUFFER, audioData); alSourcei(this.sourceData, AL_BUFFER, audioData);
} }
@ -143,8 +161,7 @@ public class Speaker {
return gain; return gain;
} }
public State getState() public State getState() {
{
return state; return state;
} }

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms; package ru.windcorp.progressia.client.comms;
import java.io.IOException; import java.io.IOException;

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms; package ru.windcorp.progressia.client.comms;
import ru.windcorp.progressia.common.comms.CommsChannel; import ru.windcorp.progressia.common.comms.CommsChannel;

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.util.namespaces.Namespaced;

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent;

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -33,7 +51,8 @@ public class ControlTriggerLambda extends ControlTriggerInputBased {
@Override @Override
public PacketControl onInputEvent(InputEvent event) { public PacketControl onInputEvent(InputEvent event) {
if (!predicate.test(event)) return null; if (!predicate.test(event))
return null;
PacketControl packet = new PacketControl( PacketControl packet = new PacketControl(
packetId, packetId,

View File

@ -0,0 +1,53 @@
/*
* 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.client.comms.controls;
import java.util.function.Consumer;
import java.util.function.Predicate;
import ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.common.comms.controls.PacketControl;
public class ControlTriggerLocalLambda extends ControlTriggerInputBased {
private final Predicate<InputEvent> predicate;
private final Consumer<InputEvent> action;
public ControlTriggerLocalLambda(
String id,
Predicate<InputEvent> predicate,
Consumer<InputEvent> action
) {
super(id);
this.predicate = predicate;
this.action = action;
}
@Override
public PacketControl onInputEvent(InputEvent event) {
if (!predicate.test(event))
return null;
action.accept(event);
return null;
}
}

View File

@ -1,11 +1,28 @@
/*
* 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.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry;
public class ControlTriggerRegistry extends NamespacedInstanceRegistry<ControlTrigger> { public class ControlTriggerRegistry extends NamespacedInstanceRegistry<ControlTrigger> {
private static final ControlTriggerRegistry INSTANCE = private static final ControlTriggerRegistry INSTANCE = new ControlTriggerRegistry();
new ControlTriggerRegistry();
public static ControlTriggerRegistry getInstance() { public static ControlTriggerRegistry getInstance() {
return INSTANCE; return INSTANCE;

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -35,7 +53,8 @@ public class ControlTriggers {
) { ) {
return of( return of(
id, id,
(input, control) -> {}, (input, control) -> {
},
predicate predicate
); );
} }
@ -77,7 +96,8 @@ public class ControlTriggers {
) { ) {
return of( return of(
id, id,
(input, control) -> {}, (input, control) -> {
},
createCheckedCompoundPredicate(inputType, predicates) createCheckedCompoundPredicate(inputType, predicates)
); );
} }
@ -117,25 +137,117 @@ public class ControlTriggers {
return of( return of(
id, id,
InputEvent.class, InputEvent.class,
(input, control) -> {}, (input, control) -> {
},
predicates predicates
); );
} }
private static //
<I extends InputEvent> //
BiConsumer<InputEvent, ControlData> ///
createCheckedDataWriter( ///
//
//
//
//
//
//
//
//
//
public static ControlTriggerInputBased localOf(
String id,
Consumer<InputEvent> action,
Predicate<InputEvent> predicate
) {
return new ControlTriggerLocalLambda(id, predicate, action);
}
public static ControlTriggerInputBased localOf(
String id,
Runnable action,
Predicate<InputEvent> predicate
) {
return localOf(
id,
input -> action.run(),
predicate
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased localOf(
String id,
Class<I> inputType,
Consumer<I> action,
Predicate<I>... predicates
) {
return localOf(
id,
createCheckedAction(inputType, action),
createCheckedCompoundPredicate(inputType, predicates)
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased localOf(
String id,
Class<I> inputType,
Runnable action,
Predicate<I>... predicates
) {
return localOf(
id,
inputType,
input -> action.run(),
predicates
);
}
@SafeVarargs
public static ControlTriggerInputBased localOf(
String id,
Consumer<InputEvent> action,
Predicate<InputEvent>... predicates
) {
return localOf(
id,
InputEvent.class,
action,
predicates
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased localOf(
String id,
Runnable action,
Predicate<InputEvent>... predicates
) {
return of(
id,
input -> action.run(),
predicates
);
}
private static <I extends InputEvent> BiConsumer<InputEvent, ControlData> createCheckedDataWriter(
Class<I> inputType, Class<I> inputType,
BiConsumer<I, ControlData> dataWriter BiConsumer<I, ControlData> dataWriter
) { ) {
return (inputEvent, control) -> dataWriter.accept(inputType.cast(inputEvent), control); return (inputEvent, control) -> dataWriter.accept(inputType.cast(inputEvent), control);
} }
private static private static <I extends InputEvent> Consumer<InputEvent> createCheckedAction(
<I extends InputEvent> Class<I> inputType,
Predicate<InputEvent> Consumer<I> action
createCheckedCompoundPredicate( ) {
return inputEvent -> action.accept(inputType.cast(inputEvent));
}
private static <I extends InputEvent> Predicate<InputEvent> createCheckedCompoundPredicate(
Class<I> inputType, Class<I> inputType,
Predicate<I>[] predicates Predicate<I>[] predicates
) { ) {
@ -171,6 +283,7 @@ public class ControlTriggers {
} }
private ControlTriggers() {} private ControlTriggers() {
}
} }

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms.controls; package ru.windcorp.progressia.client.comms.controls;
import ru.windcorp.progressia.client.Client; import ru.windcorp.progressia.client.Client;

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms.localhost; package ru.windcorp.progressia.client.comms.localhost;
import java.io.IOException; import java.io.IOException;

View File

@ -1,3 +1,21 @@
/*
* 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.client.comms.localhost; package ru.windcorp.progressia.client.comms.localhost;
import ru.windcorp.progressia.client.comms.ServerCommsChannel; import ru.windcorp.progressia.client.comms.ServerCommsChannel;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,15 +14,15 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client.graphics; package ru.windcorp.progressia.client.graphics;
import glm.vec._4.Vec4; import glm.vec._4.Vec4;
public class Colors { public class Colors {
public static final Vec4 public static final Vec4 WHITE = toVector(0xFFFFFFFF),
WHITE = toVector(0xFFFFFFFF),
BLACK = toVector(0xFF000000), BLACK = toVector(0xFF000000),
GRAY_4 = toVector(0xFF444444), GRAY_4 = toVector(0xFF444444),
@ -45,15 +45,16 @@ public class Colors {
} }
public static Vec4 multiplyRGB(Vec4 color, float multiplier, Vec4 output) { public static Vec4 multiplyRGB(Vec4 color, float multiplier, Vec4 output) {
if (output == null) output = new Vec4(); if (output == null)
output = new Vec4();
return color.mul(multiplier, multiplier, multiplier, 1, output); return color.mul(multiplier, multiplier, multiplier, 1, output);
} }
public static Vec4 toVector(int argb, Vec4 output) { public static Vec4 toVector(int argb, Vec4 output) {
output.w = ((argb & 0xFF000000) >>> 24) / 256f; // Alpha output.w = ((argb & 0xFF000000) >>> 24) / (float) 0xFF; // Alpha
output.x = ((argb & 0x00FF0000) >>> 16) / 256f; // Red output.x = ((argb & 0x00FF0000) >>> 16) / (float) 0xFF; // Red
output.y = ((argb & 0x0000FF00) >>> 8) / 256f; // Green output.y = ((argb & 0x0000FF00) >>> 8) / (float) 0xFF; // Green
output.z = ((argb & 0x000000FF) ) / 256f; // Blue output.z = ((argb & 0x000000FF)) / (float) 0xFF; // Blue
return output; return output;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,10 +14,12 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client.graphics; package ru.windcorp.progressia.client.graphics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
@ -31,7 +33,16 @@ import ru.windcorp.progressia.client.graphics.input.bus.Input;
public class GUI { public class GUI {
private static final List<Layer> LAYERS = new ArrayList<>(); private static final List<Layer> LAYERS = Collections.synchronizedList(new ArrayList<>());
private static final List<Layer> UNMODIFIABLE_LAYERS = Collections.unmodifiableList(LAYERS);
@FunctionalInterface
private interface LayerStackModification {
void affect(List<Layer> layers);
}
private static final List<LayerStackModification> MODIFICATION_QUEUE = Collections
.synchronizedList(new ArrayList<>());
private static class ModifiableInput extends Input { private static class ModifiableInput extends Input {
@Override @Override
@ -42,25 +53,39 @@ public class GUI {
private static final ModifiableInput THE_INPUT = new ModifiableInput(); private static final ModifiableInput THE_INPUT = new ModifiableInput();
private GUI() {} private GUI() {
public synchronized static void addBottomLayer(Layer layer) {
LAYERS.add(layer);
} }
public synchronized static void addTopLayer(Layer layer) { public static void addBottomLayer(Layer layer) {
LAYERS.add(0, layer); modify(layers -> layers.add(layer));
} }
public synchronized static void removeLayer(Layer layer) { public static void addTopLayer(Layer layer) {
LAYERS.remove(layer); modify(layers -> layers.add(0, layer));
} }
public synchronized static void render() { public static void removeLayer(Layer layer) {
modify(layers -> layers.remove(layer));
}
private static void modify(LayerStackModification mod) {
MODIFICATION_QUEUE.add(mod);
}
public static List<Layer> getLayers() {
return UNMODIFIABLE_LAYERS;
}
public static void render() {
synchronized (LAYERS) {
MODIFICATION_QUEUE.forEach(action -> action.affect(LAYERS));
MODIFICATION_QUEUE.clear();
for (int i = LAYERS.size() - 1; i >= 0; --i) { for (int i = LAYERS.size() - 1; i >= 0; --i) {
LAYERS.get(i).render(); LAYERS.get(i).render();
} }
} }
}
public static void invalidateEverything() { public static void invalidateEverything() {
LAYERS.forEach(Layer::invalidate); LAYERS.forEach(Layer::invalidate);

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client.graphics; package ru.windcorp.progressia.client.graphics;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;

View File

@ -1,3 +1,21 @@
/*
* 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.client.graphics.backend; package ru.windcorp.progressia.client.graphics.backend;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -22,6 +40,7 @@ public class FaceCulling {
} }
} }
private FaceCulling() {} private FaceCulling() {
}
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,14 +14,15 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client.graphics.backend; package ru.windcorp.progressia.client.graphics.backend;
import static org.lwjgl.opengl.GL11.*;
import glm.vec._2.i.Vec2i; import glm.vec._2.i.Vec2i;
import org.lwjgl.glfw.GLFWVidMode;
import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
public class GraphicsBackend { public class GraphicsBackend {
@ -37,7 +38,29 @@ public class GraphicsBackend {
private static boolean faceCullingEnabled = false; private static boolean faceCullingEnabled = false;
private GraphicsBackend() {} private static boolean isFullscreen = false;
private static boolean vSyncEnabled = false;
private static boolean isGLFWInitialized = false;
private static boolean isOpenGLInitialized = false;
private GraphicsBackend() {
}
public static boolean isGLFWInitialized() {
return isGLFWInitialized;
}
static void setGLFWInitialized(boolean isGLFWInitialized) {
GraphicsBackend.isGLFWInitialized = isGLFWInitialized;
}
public static boolean isOpenGLInitialized() {
return isOpenGLInitialized;
}
static void setOpenGLInitialized(boolean isOpenGLInitialized) {
GraphicsBackend.isOpenGLInitialized = isOpenGLInitialized;
}
public static void initialize() { public static void initialize() {
startRenderThread(); startRenderThread();
@ -73,7 +96,8 @@ public class GraphicsBackend {
} }
static void onFrameResized(long window, int newWidth, int newHeight) { static void onFrameResized(long window, int newWidth, int newHeight) {
if (window != windowHandle) return; if (window != windowHandle)
return;
InputHandler.handleFrameResize(newWidth, newHeight); InputHandler.handleFrameResize(newWidth, newHeight);
FRAME_SIZE.set(newWidth, newHeight); FRAME_SIZE.set(newWidth, newHeight);
@ -113,7 +137,8 @@ public class GraphicsBackend {
} }
public static void setFaceCulling(boolean useFaceCulling) { public static void setFaceCulling(boolean useFaceCulling) {
if (useFaceCulling == faceCullingEnabled) return; if (useFaceCulling == faceCullingEnabled)
return;
if (useFaceCulling) { if (useFaceCulling) {
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@ -124,4 +149,47 @@ public class GraphicsBackend {
faceCullingEnabled = useFaceCulling; faceCullingEnabled = useFaceCulling;
} }
public static boolean isFullscreen() {
return isFullscreen;
}
public static boolean isVSyncEnabled() {
return vSyncEnabled;
}
public static void setFullscreen() {
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowMonitor(
getWindowHandle(),
glfwGetPrimaryMonitor(),
0,
0,
vidmode.width(),
vidmode.height(),
0);
isFullscreen = true;
}
public static void setWindowed() {
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowMonitor(
getWindowHandle(),
0,
(vidmode.width() - getFrameWidth()) / 2,
(vidmode.height() - getFrameHeight()) / 2,
getFrameWidth(),
getFrameHeight(),
0);
isFullscreen = false;
}
public static void setVSyncEnabled(boolean enable) {
glfwSwapInterval(enable ? 1 : 0);
vSyncEnabled = enable;
}
public static int getRefreshRate() {
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
return vidmode.refreshRate();
}
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,14 +14,16 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client.graphics.backend; package ru.windcorp.progressia.client.graphics.backend;
import glm.vec._2.i.Vec2i; import glm.vec._2.i.Vec2i;
public class GraphicsInterface { public class GraphicsInterface {
private GraphicsInterface() {} private GraphicsInterface() {
}
public static Thread getRenderThread() { public static Thread getRenderThread() {
return GraphicsBackend.getRenderThread(); return GraphicsBackend.getRenderThread();
@ -71,4 +73,13 @@ public class GraphicsInterface {
GraphicsBackend.startNextLayer(); GraphicsBackend.startNextLayer();
} }
public static void makeFullscreen(boolean state) {
if (state) {
GraphicsBackend.setFullscreen();
} else {
GraphicsBackend.setWindowed();
}
GraphicsBackend.setVSyncEnabled(GraphicsBackend.isVSyncEnabled());
}
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client.graphics.backend; package ru.windcorp.progressia.client.graphics.backend;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@ -46,8 +47,7 @@ public class InputHandler {
} }
private static final ModifiableKeyEvent THE_KEY_EVENT = private static final ModifiableKeyEvent THE_KEY_EVENT = new ModifiableKeyEvent();
new ModifiableKeyEvent();
static void handleKeyInput( static void handleKeyInput(
long window, long window,
@ -56,7 +56,8 @@ public class InputHandler {
int action, int action,
int mods int mods
) { ) {
if (GraphicsBackend.getWindowHandle() != window) return; if (GraphicsBackend.getWindowHandle() != window)
return;
THE_KEY_EVENT.initialize(key, scancode, action, mods); THE_KEY_EVENT.initialize(key, scancode, action, mods);
dispatch(THE_KEY_EVENT); dispatch(THE_KEY_EVENT);
@ -94,14 +95,15 @@ public class InputHandler {
} }
private static final ModifiableCursorMoveEvent THE_CURSOR_MOVE_EVENT = private static final ModifiableCursorMoveEvent THE_CURSOR_MOVE_EVENT = new ModifiableCursorMoveEvent();
new ModifiableCursorMoveEvent();
static void handleMouseMoveInput( static void handleMouseMoveInput(
long window, long window,
double x, double y double x,
double y
) { ) {
if (GraphicsBackend.getWindowHandle() != window) return; if (GraphicsBackend.getWindowHandle() != window)
return;
y = GraphicsInterface.getFrameHeight() - y; // Flip y axis y = GraphicsInterface.getFrameHeight() - y; // Flip y axis
InputTracker.initializeCursorPosition(x, y); InputTracker.initializeCursorPosition(x, y);
@ -127,15 +129,15 @@ public class InputHandler {
} }
private static final ModifiableWheelScrollEvent THE_WHEEL_SCROLL_EVENT = private static final ModifiableWheelScrollEvent THE_WHEEL_SCROLL_EVENT = new ModifiableWheelScrollEvent();
new ModifiableWheelScrollEvent();
static void handleWheelScroll( static void handleWheelScroll(
long window, long window,
double xoffset, double xoffset,
double yoffset double yoffset
) { ) {
if (GraphicsBackend.getWindowHandle() != window) return; if (GraphicsBackend.getWindowHandle() != window)
return;
THE_WHEEL_SCROLL_EVENT.initialize(xoffset, yoffset); THE_WHEEL_SCROLL_EVENT.initialize(xoffset, yoffset);
dispatch(THE_WHEEL_SCROLL_EVENT); dispatch(THE_WHEEL_SCROLL_EVENT);
} }
@ -155,8 +157,7 @@ public class InputHandler {
} }
private static final ModifiableFrameResizeEvent THE_FRAME_RESIZE_EVENT = private static final ModifiableFrameResizeEvent THE_FRAME_RESIZE_EVENT = new ModifiableFrameResizeEvent();
new ModifiableFrameResizeEvent();
/* /*
* NB: this is NOT a GLFW callback, the raw callback is in GraphicsBackend * NB: this is NOT a GLFW callback, the raw callback is in GraphicsBackend

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*
* Progressia * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020-2021 Wind Corporation and contributors
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -14,7 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*******************************************************************************/ */
package ru.windcorp.progressia.client.graphics.backend; package ru.windcorp.progressia.client.graphics.backend;
import glm.vec._2.d.Vec2d; import glm.vec._2.d.Vec2d;
@ -24,12 +25,14 @@ import gnu.trove.set.hash.TIntHashSet;
public class InputTracker { public class InputTracker {
private static final Vec2d CURSOR_POSITION = new Vec2d( private static final Vec2d CURSOR_POSITION = new Vec2d(
Double.NaN, Double.NaN Double.NaN,
Double.NaN
); );
private static final TIntSet PRESSED_KEYS = new TIntHashSet(256); private static final TIntSet PRESSED_KEYS = new TIntHashSet(256);
private InputTracker() {} private InputTracker() {
}
public static double getCursorX() { public static double getCursorX() {
return CURSOR_POSITION.x; return CURSOR_POSITION.x;

Some files were not shown because too many files have changed in this diff Show More