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,24 +1,47 @@
#!/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() {
# 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!
directory="build_packages/DEB/progressia-$version" version='1.0_all'
# .deb control file that must be present # This directory will be copied into $tmpDir
configurationFile="$directory/DEBIAN/control" templateDirectory="build_packages/DEB/template"
outputFile="build_packages/DEB/progressia-$version.deb" # Files that must be present
requiredFiles="$templateDirectory/DEBIAN/control"
nameAndVersion="$name-$version"
tmpDir="build_packages/DEB/$nameAndVersion"
outputFile="build_packages/DEB/$nameAndVersion.deb"
echo "Checking environment to build Debian package" echo "Checking environment to build Debian package"
for item in $requiredCommands; do for item in $requiredCommands; do
if command -v "$item" &> /dev/null; then if command -v "$item" &> /dev/null; then
echo "- $item found" echo "- $item found"
@ -27,43 +50,46 @@ buildDebianPackage() {
exit 100 exit 100
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
exit 101 echoerr "$file is missing or not readable, cannot package"
else exit 101
echo "- $configurationFile is present and readable" else
fi echo "- $file is present and readable"
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 "$tmpDir" &&
mkdir -p "$homeDir" && mkdir -p "$shareDir" &&
cp -r 'build/libs/lib' "$homeDir/lib" && cp -r "$templateDirectory"/* "$tmpDir" &&
cp 'build/libs/Progressia.jar' "$homeDir/Progressia.jar" && cp -r 'build/libs/lib' "$shareDir/lib" &&
echo "------ DPKG-DEB ------" && cp 'build/libs/Progressia.jar' "$shareDir/Progressia.jar" &&
fakeroot dpkg-deb --build "$directory" && echo "------ DPKG-DEB ------" &&
echo "---- DPKG-DEB END ----" && fakeroot dpkg-deb --build "$tmpDir" &&
echo "---- DPKG-DEB END ----" &&
mv "$outputFile" build_packages mv "$outputFile" build_packages
} || { } || {
echoerr "Could not create Debian package" echoerr "Could not create Debian package"
exitCode=1 exitCode=1
} }
{ {
if [ -d "$homeDir" ]; then if [ -d "$tmpDir" ]; then
rm -r "$homeDir" rm -r "$tmpDir"
fi fi
echo "Cleaned up" echo "Cleaned up"
} || { } || {
echoerr "Could not clean up after packaging Debian package" echoerr "Could not clean up after packaging Debian package"
exitCode=2 exitCode=2
} }
exit "$exitCode" exit "$exitCode"
} }
@ -71,15 +97,15 @@ buildWindowsInstaller() {
# Commands that must be available to execute this action # Commands that must be available to execute this action
requiredCommands='makensis' requiredCommands='makensis'
# NSIS configuration file that must be present # NSIS configuration file that must be present
configurationFile='build_packages/NSIS/ProgressiaInstaller.nsi' configurationFile='build_packages/NSIS/ProgressiaInstaller.nsi'
# File that will be output # File that will be output
outputFile='build_packages/NSIS/ProgressiaInstaller.exe' outputFile='build_packages/NSIS/ProgressiaInstaller.exe'
echo "Checking environment to build Windows installer" echo "Checking environment to build Windows installer"
for item in $requiredCommands; do for item in $requiredCommands; do
if command -v "$item" &> /dev/null; then if command -v "$item" &> /dev/null; then
echo "- $item found" echo "- $item found"
@ -88,20 +114,21 @@ buildWindowsInstaller() {
exit 100 exit 100
fi fi
done done
if ! [ -r "$configurationFile" ]; then if ! [ -r "$configurationFile" ]; then
echoerr "$configurationFile is missing or not readable, cannot build" echoerr "$configurationFile is missing or not readable, cannot build"
exit 101 exit 101
else else
echo "- $configurationFile is present and readable" echo "- $configurationFile is present and readable"
fi fi
echo "Environment OK; building Windows installer" echo "Environment OK; building Windows installer"
exitCode=0 exitCode=0
{ {
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 ----" &&
@ -110,7 +137,7 @@ buildWindowsInstaller() {
echoerr "Could not build Windows installer" echoerr "Could not build Windows installer"
exitCode=1 exitCode=1
} }
{ {
if [ -d 'build_packages/NSIS/lib' ]; then if [ -d 'build_packages/NSIS/lib' ]; then
rm -r 'build_packages/NSIS/lib' rm -r 'build_packages/NSIS/lib'
@ -118,12 +145,15 @@ 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"
exitCode=2 exitCode=2
} }
exit "$exitCode" exit "$exitCode"
} }

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,35 +72,40 @@
;-------------------------------- ;--------------------------------
;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
WriteRegStr HKLM SOFTWARE\Progressia "Install_Dir" "$INSTDIR" WriteRegStr HKLM SOFTWARE\Progressia "Install_Dir" "$INSTDIR"
;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 {
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,21 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
@ -22,53 +23,53 @@ import java.io.PrintWriter;
import java.io.Writer; import java.io.Writer;
public class CSVWriter { public class CSVWriter {
private String columnSeparator = ";"; private String columnSeparator = ";";
private String rowSeparator = "\n"; private String rowSeparator = "\n";
private boolean shouldAddSeparator = false; private boolean shouldAddSeparator = false;
private final PrintWriter parent; private final PrintWriter parent;
public CSVWriter(PrintWriter output) { public CSVWriter(PrintWriter output) {
this.parent = output; this.parent = output;
} }
public CSVWriter(Writer output) { public CSVWriter(Writer output) {
this(new PrintWriter(output)); this(new PrintWriter(output));
} }
public CSVWriter(OutputStream output) { public CSVWriter(OutputStream output) {
this(new PrintWriter(output)); this(new PrintWriter(output));
} }
public PrintWriter getParent() { public PrintWriter getParent() {
return parent; return parent;
} }
public String getColumnSeparator() { public String getColumnSeparator() {
return columnSeparator; return columnSeparator;
} }
public CSVWriter setColumnSeparator(String columnSeparator) { public CSVWriter setColumnSeparator(String columnSeparator) {
this.columnSeparator = columnSeparator; this.columnSeparator = columnSeparator;
return this; return this;
} }
public String getRowSeparator() { public String getRowSeparator() {
return rowSeparator; return rowSeparator;
} }
public CSVWriter setRowSeparator(String rowSeparator) { public CSVWriter setRowSeparator(String rowSeparator) {
this.rowSeparator = rowSeparator; this.rowSeparator = rowSeparator;
return this; return this;
} }
public void print(Object object) { public void print(Object object) {
skip(); skip();
getParent().print(String.valueOf(object)); getParent().print(String.valueOf(object));
} }
public void skip() { public void skip() {
if (shouldAddSeparator) { if (shouldAddSeparator) {
getParent().print(getColumnSeparator()); getParent().print(getColumnSeparator());
@ -76,27 +77,27 @@ public class CSVWriter {
shouldAddSeparator = true; shouldAddSeparator = true;
} }
} }
public void skip(int amount) { public void skip(int amount) {
for (int i = 0; i < amount; ++i) { for (int i = 0; i < amount; ++i) {
skip(); skip();
} }
} }
public void endRow() { public void endRow() {
getParent().print(getRowSeparator()); getParent().print(getRowSeparator());
shouldAddSeparator = false; shouldAddSeparator = false;
} }
public void endRow(Object object) { public void endRow(Object object) {
print(object); print(object);
endRow(); endRow();
} }
public void flush() { public void flush() {
getParent().flush(); getParent().flush();
} }
public void close() { public void close() {
getParent().close(); getParent().close();
} }

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,47 +14,57 @@
* *
* 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;
import java.util.Map; 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) {
e.printStackTrace(); e.printStackTrace();
} }
} }
PRIMITIVE_TO_NULL.put(Boolean.TYPE, Boolean.FALSE); PRIMITIVE_TO_NULL.put(Boolean.TYPE, Boolean.FALSE);
PRIMITIVE_TO_NULL.put(Byte.TYPE, Byte.valueOf((byte) 0)); PRIMITIVE_TO_NULL.put(Byte.TYPE, Byte.valueOf((byte) 0));
PRIMITIVE_TO_NULL.put(Short.TYPE, Short.valueOf((short) 0)); PRIMITIVE_TO_NULL.put(Short.TYPE, Short.valueOf((short) 0));
PRIMITIVE_TO_NULL.put(Integer.TYPE, Integer.valueOf(0)); PRIMITIVE_TO_NULL.put(Integer.TYPE, Integer.valueOf(0));
PRIMITIVE_TO_NULL.put(Long.TYPE, Long.valueOf(0)); PRIMITIVE_TO_NULL.put(Long.TYPE, Long.valueOf(0));
PRIMITIVE_TO_NULL.put(Float.TYPE, Float.valueOf(Float.NaN)); PRIMITIVE_TO_NULL.put(Float.TYPE, Float.valueOf(Float.NaN));
PRIMITIVE_TO_NULL.put(Double.TYPE, Double.valueOf(Double.NaN)); PRIMITIVE_TO_NULL.put(Double.TYPE, Double.valueOf(Double.NaN));
PRIMITIVE_TO_NULL.put(Character.TYPE, Character.valueOf('\u0000')); PRIMITIVE_TO_NULL.put(Character.TYPE, Character.valueOf('\u0000'));
} }
public static Class<?> getBoxedClass(Class<?> primitiveClass) { public static Class<?> getBoxedClass(Class<?> primitiveClass) {
return PRIMITIVE_TO_BOXED.getOrDefault(primitiveClass, primitiveClass); return PRIMITIVE_TO_BOXED.getOrDefault(primitiveClass, primitiveClass);
} }
public static Object getPrimitiveNull(Class<?> primitiveClass) { public static Object getPrimitiveNull(Class<?> primitiveClass) {
return PRIMITIVE_TO_NULL.get(primitiveClass); return PRIMITIVE_TO_NULL.get(primitiveClass);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,45 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
private static final long serialVersionUID = -4052144233640072750L;
private static final long serialVersionUID = -4052144233640072750L;
public SyntaxException() {
public SyntaxException() {
}
}
public SyntaxException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace); public SyntaxException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
} super(message, cause, enableSuppression, writableStackTrace);
}
public SyntaxException(String message, Throwable cause) {
super(message, cause); public SyntaxException(String message, Throwable cause) {
} super(message, cause);
}
public SyntaxException(String message) {
super(message); public SyntaxException(String message) {
} super(message);
}
public SyntaxException(Throwable cause) {
super(cause); public SyntaxException(Throwable cause) {
} super(cause);
}
}
}

View File

@ -1,128 +1,132 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
public class CharArrayIterator implements CharacterIterator {
public class CharArrayIterator implements CharacterIterator {
private final char[] array;
private int pos; private final char[] array;
private int pos;
public CharArrayIterator(char[] array) {
this.array = array; public CharArrayIterator(char[] array) {
} this.array = array;
}
public CharArrayIterator(String src) {
this(src.toCharArray()); public CharArrayIterator(String src) {
} this(src.toCharArray());
}
@Override
public char first() { @Override
pos = 0; public char first() {
if (array.length != 0) { pos = 0;
return array[pos]; if (array.length != 0) {
} return array[pos];
return DONE; }
} return DONE;
}
@Override
public char last() { @Override
pos = array.length; public char last() {
if (array.length != 0) { pos = array.length;
pos -= 1; if (array.length != 0) {
return array[pos]; pos -= 1;
} return array[pos];
return DONE; }
} return DONE;
}
@Override
public char current() { @Override
if (array.length != 0 && pos < array.length) { public char current() {
return array[pos]; if (array.length != 0 && pos < array.length) {
} return array[pos];
return DONE; }
} return DONE;
}
@Override
public char next() { @Override
pos += 1; public char next() {
if (pos >= array.length) { pos += 1;
pos = array.length; if (pos >= array.length) {
return DONE; pos = array.length;
} return DONE;
return current(); }
} return current();
}
@Override
public char previous() { @Override
if (pos == 0) { public char previous() {
return DONE; if (pos == 0) {
} return DONE;
pos -= 1; }
return current(); pos -= 1;
} return current();
}
@Override
public char setIndex(int position) { @Override
if (position < 0 || position > array.length) { public char setIndex(int position) {
throw new IllegalArgumentException("bad position: " + position); if (position < 0 || position > array.length) {
} throw new IllegalArgumentException("bad position: " + position);
}
pos = position;
pos = position;
if (pos != array.length && array.length != 0) {
return array[pos]; if (pos != array.length && array.length != 0) {
} return array[pos];
return DONE; }
} return DONE;
}
@Override
public int getBeginIndex() { @Override
return 0; public int getBeginIndex() {
} return 0;
}
@Override
public int getEndIndex() { @Override
return array.length; public int getEndIndex() {
} return array.length;
}
@Override
public int getIndex() { @Override
return pos; public int getIndex() {
} return pos;
}
// @SuppressWarnings("all") Just STFU, this _is_ terrific
// @SuppressWarnings("all") Just STFU, this _is_ terrific
// SonarLint: "clone" should not be overridden (java:S2975)
// And I wouldn't have done that if only CharacterIterator had not required exception safety. // SonarLint: "clone" should not be overridden (java:S2975)
// SonarLint: "toString()" and "clone()" methods should not return null (java:S2225) // And I wouldn't have done that if only CharacterIterator had not required
// The clause is unreachable: CharacterArrayIterator implements Cloneable and superclass is Object. // exception safety.
@SuppressWarnings({"squid:S2975", "squid:S2225"}) // SonarLint: "toString()" and "clone()" methods should not return null
// (java:S2225)
@Override // The clause is unreachable: CharacterArrayIterator implements Cloneable
public CharArrayIterator clone() { // and superclass is Object.
try { @SuppressWarnings({ "squid:S2975", "squid:S2225" })
return (CharArrayIterator) super.clone();
} catch (CloneNotSupportedException cnse) { @Override
// Impossible public CharArrayIterator clone() {
return null; try {
} return (CharArrayIterator) super.clone();
} } catch (CloneNotSupportedException cnse) {
// Impossible
} return null;
}
}
}

View File

@ -1,42 +1,43 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
@FunctionalInterface
public interface CharConsumer { @FunctionalInterface
public interface CharConsumer {
void accept(char c);
void accept(char c);
public static CharConsumer andThen(CharConsumer first, CharConsumer second) {
return c -> { public static CharConsumer andThen(CharConsumer first, CharConsumer second) {
first.accept(c); return c -> {
second.accept(c); first.accept(c);
}; second.accept(c);
} };
}
public static IntConsumer toInt(CharConsumer consumer) {
return i -> consumer.accept((char) i); public static IntConsumer toInt(CharConsumer consumer) {
} return i -> consumer.accept((char) i);
}
public static CharConsumer toChar(IntConsumer consumer) {
return consumer::accept; public static CharConsumer toChar(IntConsumer consumer) {
} return consumer::accept;
}
}
}

View File

@ -1,69 +1,70 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
import ru.windcorp.jputil.ArrayUtil;
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) {
return new ArrayFiller(array, offset, length); public static CharConsumer fillArray(char[] array, int offset, int length) {
} return new ArrayFiller(array, offset, length);
}
public static CharConsumer fillArray(char[] array) {
return fillArray(array, 0, -1); public static CharConsumer fillArray(char[] array) {
} return fillArray(array, 0, -1);
}
private static class ArrayFiller implements CharConsumer {
private static class ArrayFiller implements CharConsumer {
final char[] array;
int i; final char[] array;
final int end; int i;
final int end;
/**
* @param array /**
* @param offset * @param array
* @param length * @param offset
*/ * @param length
ArrayFiller(char[] array, int offset, int length) { */
this.array = Objects.requireNonNull(array, "array"); ArrayFiller(char[] array, int offset, int length) {
this.end = ArrayUtil.checkArrayStartEnd(array, offset, offset + length); this.array = Objects.requireNonNull(array, "array");
this.i = offset; this.end = ArrayUtil.checkArrayStartEnd(array, offset, offset + length);
} this.i = offset;
}
/**
* @see ru.windcorp.jputil.chars.CharConsumer#accept(char) /**
*/ * @see ru.windcorp.jputil.chars.CharConsumer#accept(char)
@Override */
public void accept(char c) { @Override
if (i == end) public void accept(char c) {
throw new ArrayIndexOutOfBoundsException(end); if (i == end)
array[i++] = c; throw new ArrayIndexOutOfBoundsException(end);
} array[i++] = c;
}
}
}
}
}

View File

@ -1,84 +1,85 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.IntPredicate; import java.util.Arrays;
import java.util.function.IntPredicate;
import ru.windcorp.jputil.ArrayUtil;
import ru.windcorp.jputil.ArrayUtil;
@FunctionalInterface
public interface CharPredicate { @FunctionalInterface
public interface CharPredicate {
boolean test(char c);
boolean test(char c);
public static CharPredicate and(CharPredicate first, CharPredicate second) {
return c -> first.test(c) && second.test(c); public static CharPredicate and(CharPredicate first, CharPredicate second) {
} return c -> first.test(c) && second.test(c);
}
public static CharPredicate or(CharPredicate first, CharPredicate second) {
return c -> first.test(c) || second.test(c); public static CharPredicate or(CharPredicate first, CharPredicate second) {
} return c -> first.test(c) || second.test(c);
}
public static CharPredicate negate(CharPredicate predicate) {
return c -> !predicate.test(c); public static CharPredicate negate(CharPredicate predicate) {
} return c -> !predicate.test(c);
}
public static IntPredicate toInt(CharPredicate predicate) {
return i -> predicate.test((char) i); public static IntPredicate toInt(CharPredicate predicate) {
} return i -> predicate.test((char) i);
}
public static CharPredicate toChar(IntPredicate predicate) {
return predicate::test; public static CharPredicate toChar(IntPredicate predicate) {
} return predicate::test;
}
public static CharPredicate forArray(char... chars) {
if (chars.length == 0) { public static CharPredicate forArray(char... chars) {
return c -> false; if (chars.length == 0) {
} return c -> false;
}
if (chars.length == 1) {
return forChar(chars[0]); if (chars.length == 1) {
} return forChar(chars[0]);
}
if (chars.length < 16) {
return c -> ArrayUtil.firstIndexOf(chars, c) >= 0; if (chars.length < 16) {
} else { return c -> ArrayUtil.firstIndexOf(chars, c) >= 0;
final char[] sorted = Arrays.copyOf(chars, chars.length); } else {
Arrays.sort(sorted); final char[] sorted = Arrays.copyOf(chars, chars.length);
return c -> Arrays.binarySearch(chars, c) >= 0; Arrays.sort(sorted);
} return c -> Arrays.binarySearch(chars, c) >= 0;
} }
}
public static CharPredicate forChar(final char c) {
return given -> given == c; public static CharPredicate forChar(final char c) {
} return given -> given == c;
}
public static CharPredicate forRange(final char minInclusive, final char maxExclusive) {
if (minInclusive > maxExclusive) { public static CharPredicate forRange(final char minInclusive, final char maxExclusive) {
throw new IllegalArgumentException("min > max: " + minInclusive + " > " + maxExclusive); if (minInclusive > maxExclusive) {
} throw new IllegalArgumentException("min > max: " + minInclusive + " > " + maxExclusive);
}
if (minInclusive == maxExclusive) {
return c -> false; if (minInclusive == maxExclusive) {
} return c -> false;
}
return c -> c >= minInclusive && c < maxExclusive;
} return c -> c >= minInclusive && c < maxExclusive;
}
}
}

View File

@ -1,35 +1,36 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
@FunctionalInterface
public interface CharSupplier { @FunctionalInterface
public interface CharSupplier {
char getAsChar();
char getAsChar();
public static IntSupplier toInt(CharSupplier consumer) {
return consumer::getAsChar; public static IntSupplier toInt(CharSupplier consumer) {
} return consumer::getAsChar;
}
public static CharSupplier toChar(IntSupplier consumer) {
return () -> (char) consumer.getAsInt(); public static CharSupplier toChar(IntSupplier consumer) {
} return () -> (char) consumer.getAsInt();
}
}
}

View File

@ -1,44 +1,45 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
private static final long serialVersionUID = -3647188859290365053L;
private static final long serialVersionUID = -3647188859290365053L;
public EscapeException() {
super(); public EscapeException() {
} super();
}
public EscapeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace); public EscapeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
} super(message, cause, enableSuppression, writableStackTrace);
}
public EscapeException(String message, Throwable cause) {
super(message, cause); public EscapeException(String message, Throwable cause) {
} super(message, cause);
}
public EscapeException(String message) {
super(message); public EscapeException(String message) {
} super(message);
}
public EscapeException(Throwable cause) {
super(cause); public EscapeException(Throwable cause) {
} super(cause);
}
}
}

View File

@ -1,474 +1,514 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
import ru.windcorp.jputil.ArrayUtil;
import ru.windcorp.jputil.chars.reader.CharReader; import ru.windcorp.jputil.ArrayUtil;
import ru.windcorp.jputil.chars.reader.CharReaders; import ru.windcorp.jputil.chars.reader.CharReader;
import ru.windcorp.jputil.chars.reader.CharReaders;
public class Escaper {
public class Escaper {
public static class EscaperBuilder {
private char escapeChar = '\\'; public static class EscaperBuilder {
private char unicodeEscapeChar = 'u'; private char escapeChar = '\\';
private char[] safes = null; private char unicodeEscapeChar = 'u';
private char[] unsafes = null; private char[] safes = null;
private char[] unsafes = null;
private boolean preferUnicode = false;
private boolean strict = true; private boolean preferUnicode = false;
private boolean strict = true;
public EscaperBuilder withEscapeChar(char escapeChar) {
this.escapeChar = escapeChar; public EscaperBuilder withEscapeChar(char escapeChar) {
return this; this.escapeChar = escapeChar;
} return this;
}
public EscaperBuilder withUnicodeEscapeChar(char unicodeEscapeChar) {
this.unicodeEscapeChar = unicodeEscapeChar; public EscaperBuilder withUnicodeEscapeChar(char unicodeEscapeChar) {
return this; this.unicodeEscapeChar = unicodeEscapeChar;
} return this;
}
public EscaperBuilder withChars(char[] safes, char[] unsafes) {
this.safes = safes; public EscaperBuilder withChars(char[] safes, char[] unsafes) {
this.unsafes = unsafes; this.safes = safes;
return this; this.unsafes = unsafes;
} return this;
}
public EscaperBuilder withChars(String safes, String unsafes) {
this.safes = safes.toCharArray(); public EscaperBuilder withChars(String safes, String unsafes) {
this.unsafes = unsafes.toCharArray(); this.safes = safes.toCharArray();
return this; this.unsafes = unsafes.toCharArray();
} return this;
}
public EscaperBuilder withChars(char[] chars) {
this.safes = this.unsafes = chars; public EscaperBuilder withChars(char[] chars) {
return this; this.safes = this.unsafes = chars;
} return this;
}
public EscaperBuilder withChars(String chars) {
this.safes = this.unsafes = chars.toCharArray(); public EscaperBuilder withChars(String chars) {
return this; this.safes = this.unsafes = chars.toCharArray();
} return this;
}
public EscaperBuilder withSafes(char[] safes) {
this.safes = safes; public EscaperBuilder withSafes(char[] safes) {
return this; this.safes = safes;
} return this;
}
public EscaperBuilder withSafes(String safes) {
this.safes = safes.toCharArray(); public EscaperBuilder withSafes(String safes) {
return this; this.safes = safes.toCharArray();
} return this;
}
public EscaperBuilder withUnsafes(char[] unsafes) {
this.unsafes = unsafes; public EscaperBuilder withUnsafes(char[] unsafes) {
return this; this.unsafes = unsafes;
} return this;
}
public EscaperBuilder withUnsafes(String unsafes) {
this.unsafes = unsafes.toCharArray(); public EscaperBuilder withUnsafes(String unsafes) {
return this; this.unsafes = unsafes.toCharArray();
} return this;
}
public EscaperBuilder preferUnicode(boolean preferUnicode) {
this.preferUnicode = preferUnicode; public EscaperBuilder preferUnicode(boolean preferUnicode) {
return this; this.preferUnicode = preferUnicode;
} return this;
}
public EscaperBuilder strict(boolean strict) {
this.strict = strict; public EscaperBuilder strict(boolean strict) {
return this; this.strict = strict;
} return this;
}
public Escaper build() {
return new Escaper(escapeChar, unicodeEscapeChar, safes, unsafes, preferUnicode, strict); public Escaper build() {
} return new Escaper(escapeChar, unicodeEscapeChar, safes, unsafes, preferUnicode, strict);
}
}
}
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(
private final char escapeChar; '\\',
private final char unicodeEscapeChar; 'u',
private final char[] safes; "tbnrf'\"".toCharArray(),
private final char[] unsafes; "\t\b\n\r\f\'\"".toCharArray(),
true,
private final boolean preferUnicode; true
private final boolean strict; );
protected Escaper( private final char escapeChar;
char escapeChar, char unicodeEscapeChar, private final char unicodeEscapeChar;
char[] safes, char[] unsafes, private final char[] safes;
boolean preferUnicode, boolean strict) { private final char[] unsafes;
this.escapeChar = escapeChar;
this.unicodeEscapeChar = unicodeEscapeChar; private final boolean preferUnicode;
this.safes = safes; private final boolean strict;
this.unsafes = unsafes;
this.preferUnicode = preferUnicode; protected Escaper(
this.strict = strict; char escapeChar,
char unicodeEscapeChar,
int duplicate; char[] safes,
if ((duplicate = ArrayUtil.hasDuplicates(safes)) != -1) char[] unsafes,
throw new IllegalArgumentException("Duplicate safe character '" + safes[duplicate] + "'"); boolean preferUnicode,
boolean strict
if ((duplicate = ArrayUtil.hasDuplicates(unsafes)) != -1) ) {
throw new IllegalArgumentException("Duplicate unsafe character '" + unsafes[duplicate] + "'"); this.escapeChar = escapeChar;
this.unicodeEscapeChar = unicodeEscapeChar;
for (char c : safes) { this.safes = safes;
if (c == escapeChar) throw new IllegalArgumentException("Safe characters contain escape chatacter"); this.unsafes = unsafes;
if (c == unicodeEscapeChar) throw new IllegalArgumentException("Safe characters contain Unicode escape chatacter"); this.preferUnicode = preferUnicode;
} this.strict = strict;
for (char c : unsafes) { int duplicate;
if (c == escapeChar) throw new IllegalArgumentException("Unsafe characters contain escape chatacter (escape character is escaped automatically)"); if ((duplicate = ArrayUtil.hasDuplicates(safes)) != -1)
if (c == unicodeEscapeChar) throw new IllegalArgumentException("Unsafe characters contain Unicode escape chatacter"); throw new IllegalArgumentException("Duplicate safe character '" + safes[duplicate] + "'");
}
} if ((duplicate = ArrayUtil.hasDuplicates(unsafes)) != -1)
throw new IllegalArgumentException("Duplicate unsafe character '" + unsafes[duplicate] + "'");
public static EscaperBuilder create() {
return new EscaperBuilder(); for (char c : safes) {
} if (c == escapeChar)
throw new IllegalArgumentException("Safe characters contain escape chatacter");
/* if (c == unicodeEscapeChar)
* Logic - escape throw new IllegalArgumentException("Safe characters contain Unicode escape chatacter");
*/ }
public void escape(CharReader src, int length, CharPredicate until, CharConsumer output) { for (char c : unsafes) {
int end; if (c == escapeChar)
if (length < 0) end = Integer.MAX_VALUE; throw new IllegalArgumentException(
else end = src.getPosition() + length; "Unsafe characters contain escape chatacter (escape character is escaped automatically)"
while (src.has() && );
src.getPosition() < end && if (c == unicodeEscapeChar)
(until == null || !until.test(src.current()))) throw new IllegalArgumentException("Unsafe characters contain Unicode escape chatacter");
escape(src.consume(), output); }
} }
public void escape(char c, CharConsumer output) { public static EscaperBuilder create() {
if (c == escapeChar) { return new EscaperBuilder();
output.accept(escapeChar); }
output.accept(escapeChar);
return; /*
} * Logic - escape
*/
int index = ArrayUtil.firstIndexOf(unsafes, c);
public void escape(CharReader src, int length, CharPredicate until, CharConsumer output) {
if (index >= 0) { int end;
output.accept(escapeChar); if (length < 0)
output.accept(safes[index]); end = Integer.MAX_VALUE;
} else { else
if (preferUnicode && !isRegular(c)) { end = src.getPosition() + length;
escapeAsHex(c, output); while (
} else { src.has() &&
output.accept(c); src.getPosition() < end &&
} (until == null || !until.test(src.current()))
} )
} escape(src.consume(), output);
}
// SonarLint: Assignments should not be made from within sub-expressions (java:S1121)
// Seems self-evident enough public void escape(char c, CharConsumer output) {
@SuppressWarnings("squid:S1121") if (c == escapeChar) {
output.accept(escapeChar);
private void escapeAsHex(char c, CharConsumer output) { output.accept(escapeChar);
output.accept(escapeChar); return;
output.accept(unicodeEscapeChar); }
output.accept(StringUtil.hexDigit(c >>= (4 * 3)));
output.accept(StringUtil.hexDigit(c >>= (4 * 2))); int index = ArrayUtil.firstIndexOf(unsafes, c);
output.accept(StringUtil.hexDigit(c >>= (4 * 1)));
output.accept(StringUtil.hexDigit(c >> (4 * 0))); if (index >= 0) {
} output.accept(escapeChar);
output.accept(safes[index]);
public int getEscapedLength(CharReader src, int length, CharPredicate until) { } else {
int end; if (preferUnicode && !isRegular(c)) {
if (length < 0) end = Integer.MAX_VALUE; escapeAsHex(c, output);
else end = src.getPosition() + length; } else {
output.accept(c);
int result = 0; }
}
while (src.has() && }
src.getPosition() < end &&
(until == null || !until.test(src.current()))) { // SonarLint: Assignments should not be made from within sub-expressions
result += getEscapedLength(src.consume()); // (java:S1121)
} // Seems self-evident enough
@SuppressWarnings("squid:S1121")
return result;
} private void escapeAsHex(char c, CharConsumer output) {
output.accept(escapeChar);
public int getEscapedLength(char c) { output.accept(unicodeEscapeChar);
if (c == escapeChar || ArrayUtil.firstIndexOf(unsafes, c) >= 0) output.accept(StringUtil.hexDigit(c >>= (4 * 3)));
return 2; output.accept(StringUtil.hexDigit(c >>= (4 * 2)));
else { output.accept(StringUtil.hexDigit(c >>= (4 * 1)));
if (preferUnicode && !isRegular(c)) output.accept(StringUtil.hexDigit(c >> (4 * 0)));
return 6; }
else
return 1; public int getEscapedLength(CharReader src, int length, CharPredicate until) {
} int end;
} if (length < 0)
end = Integer.MAX_VALUE;
/* else
* Logic - unescape end = src.getPosition() + length;
*/
int result = 0;
public void unescape(CharReader src, int length, CharPredicate until, CharConsumer output) throws EscapeException {
int end; while (
if (length < 0) end = Integer.MAX_VALUE; src.has() &&
else end = src.getPosition() + length; src.getPosition() < end &&
while (src.has() && (until == null || !until.test(src.current()))
src.getPosition() < end && ) {
(until == null || !until.test(src.current()))) { result += getEscapedLength(src.consume());
output.accept(unescapeOneSequence(src)); }
}
} return result;
}
public char unescapeOneSequence(CharReader src) throws EscapeException {
int resetPos = src.getPosition(); public int getEscapedLength(char c) {
try { if (c == escapeChar || ArrayUtil.firstIndexOf(unsafes, c) >= 0)
if (src.current() == escapeChar) { return 2;
src.next(); else {
if (preferUnicode && !isRegular(c))
if (src.isEnd()) return 6;
throw new EscapeException("Incomplete escape sequence at the end"); else
return 1;
if (src.current() == escapeChar) { }
src.next(); }
return escapeChar;
} /*
* Logic - unescape
if (src.current() == unicodeEscapeChar) { */
src.next();
return (char) ( public void unescape(CharReader src, int length, CharPredicate until, CharConsumer output) throws EscapeException {
hexValue(src.consume()) << (4 * 3) | int end;
hexValue(src.consume()) << (4 * 2) | if (length < 0)
hexValue(src.consume()) << (4 * 1) | end = Integer.MAX_VALUE;
hexValue(src.consume()) << (4 * 0) else
); end = src.getPosition() + length;
} while (
src.has() &&
int index = ArrayUtil.firstIndexOf(safes, src.current()); src.getPosition() < end &&
if (index >= 0) { (until == null || !until.test(src.current()))
src.next(); ) {
return unsafes[index]; output.accept(unescapeOneSequence(src));
} }
}
if (strict)
throw new EscapeException("Unknown escape sequence \"" + escapeChar + src.current() + "\""); public char unescapeOneSequence(CharReader src) throws EscapeException {
else int resetPos = src.getPosition();
return src.consume(); try {
} else if (src.current() == escapeChar) {
return src.consume(); src.next();
} catch (EscapeException | RuntimeException e) {
src.setPosition(resetPos); if (src.isEnd())
throw e; throw new EscapeException("Incomplete escape sequence at the end");
}
} if (src.current() == escapeChar) {
src.next();
public int getUnescapedLength(CharReader src, int length, CharPredicate until) { return escapeChar;
int end; }
if (length < 0) end = Integer.MAX_VALUE;
else end = src.getPosition() + length; if (src.current() == unicodeEscapeChar) {
src.next();
int result = 0; return (char) (hexValue(src.consume()) << (4 * 3) |
hexValue(src.consume()) << (4 * 2) |
while (src.has() && hexValue(src.consume()) << (4 * 1) |
src.getPosition() < end && hexValue(src.consume()) << (4 * 0));
(until == null || !until.test(src.current()))) { }
skipOneSequence(src);
result++; int index = ArrayUtil.firstIndexOf(safes, src.current());
} if (index >= 0) {
src.next();
return result; return unsafes[index];
} }
public void skipOneSequence(CharReader src) { if (strict)
if ( throw new EscapeException("Unknown escape sequence \"" + escapeChar + src.current() + "\"");
src.current() == escapeChar else
&& return src.consume();
src.next() == unicodeEscapeChar } else
) { return src.consume();
src.advance(4); } catch (EscapeException | RuntimeException e) {
} src.setPosition(resetPos);
src.next(); throw e;
} }
}
/*
* Utility public int getUnescapedLength(CharReader src, int length, CharPredicate until) {
*/ int end;
if (length < 0)
public void escape(CharReader src, int length, CharConsumer output) { end = Integer.MAX_VALUE;
escape(src, length, null, output); else
} end = src.getPosition() + length;
public void escape(CharReader src, CharPredicate until, CharConsumer output) { int result = 0;
escape(src, -1, until, output);
} while (
src.has() &&
public void escape(CharReader src, CharConsumer output) { src.getPosition() < end &&
escape(src, -1, null, output); (until == null || !until.test(src.current()))
} ) {
skipOneSequence(src);
public int getEscapedLength(CharReader src, int length) { result++;
return getEscapedLength(src, length, null); }
}
return result;
public int getEscapedLength(CharReader src, CharPredicate until) { }
return getEscapedLength(src, -1, until);
} public void skipOneSequence(CharReader src) {
if (
public int getEscapedLength(CharReader src) { src.current() == escapeChar
return getEscapedLength(src, -1, null); &&
} src.next() == unicodeEscapeChar
) {
public char[] escape(CharReader src, int length, CharPredicate until) { src.advance(4);
src.mark(); }
char[] result = new char[getEscapedLength(src, length, until)]; src.next();
src.reset(); }
escape(src, length, until, CharConsumers.fillArray(result));
return result; /*
} * Utility
*/
public char[] escape(CharReader src, int length) {
return escape(src, length, (CharPredicate) null); public void escape(CharReader src, int length, CharConsumer output) {
} escape(src, length, null, output);
}
public char[] escape(CharReader src, CharPredicate until) {
return escape(src, -1, until); public void escape(CharReader src, CharPredicate until, CharConsumer output) {
} escape(src, -1, until, output);
}
public char[] escape(CharReader src) {
return escape(src, -1, (CharPredicate) null); public void escape(CharReader src, CharConsumer output) {
} escape(src, -1, null, output);
}
public void unescape(CharReader src, int length, CharConsumer output) throws EscapeException {
unescape(src, length, null, output); public int getEscapedLength(CharReader src, int length) {
} return getEscapedLength(src, length, null);
}
public void unescape(CharReader src, CharPredicate until, CharConsumer output) throws EscapeException {
unescape(src, -1, until, output); public int getEscapedLength(CharReader src, CharPredicate until) {
} return getEscapedLength(src, -1, until);
}
public void unescape(CharReader src, CharConsumer output) throws EscapeException {
unescape(src, -1, null, output); public int getEscapedLength(CharReader src) {
} return getEscapedLength(src, -1, null);
}
public int getUnescapedLength(CharReader src, int length) {
return getUnescapedLength(src, length, null); public char[] escape(CharReader src, int length, CharPredicate until) {
} src.mark();
char[] result = new char[getEscapedLength(src, length, until)];
public int getUnescapedLength(CharReader src, CharPredicate until) { src.reset();
return getUnescapedLength(src, -1, until); escape(src, length, until, CharConsumers.fillArray(result));
} return result;
}
public int getUnescapedLength(CharReader src) {
return getUnescapedLength(src, -1, null); public char[] escape(CharReader src, int length) {
} return escape(src, length, (CharPredicate) null);
}
public char[] unescape(CharReader src, int length, CharPredicate until) throws EscapeException {
src.mark(); public char[] escape(CharReader src, CharPredicate until) {
char[] result = new char[getUnescapedLength(src, length, until)]; return escape(src, -1, until);
src.reset(); }
unescape(src, length, until, CharConsumers.fillArray(result));
return result; public char[] escape(CharReader src) {
} return escape(src, -1, (CharPredicate) null);
}
public char[] unescape(CharReader src, int length) throws EscapeException {
return unescape(src, length, (CharPredicate) null); public void unescape(CharReader src, int length, CharConsumer output) throws EscapeException {
} unescape(src, length, null, output);
}
public char[] unescape(CharReader src, CharPredicate until) throws EscapeException {
return unescape(src, -1, until); public void unescape(CharReader src, CharPredicate until, CharConsumer output) throws EscapeException {
} unescape(src, -1, until, output);
}
public char[] unescape(CharReader src) throws EscapeException {
return unescape(src, -1, (CharPredicate) null); public void unescape(CharReader src, CharConsumer output) throws EscapeException {
} unescape(src, -1, null, output);
}
@Deprecated()
public char[] unescape(CharacterIterator src, char until) throws EscapeException { public int getUnescapedLength(CharReader src, int length) {
int index = src.getIndex(); return getUnescapedLength(src, length, null);
CharReader reader = CharReaders.wrap(src); }
char[] result = unescape(reader, -1, CharPredicate.forChar(until)); public int getUnescapedLength(CharReader src, CharPredicate until) {
return getUnescapedLength(src, -1, until);
src.setIndex(index + reader.getPosition()); }
return result;
} public int getUnescapedLength(CharReader src) {
return getUnescapedLength(src, -1, null);
public String escape(String src) { }
StringBuilder result = new StringBuilder(src.length());
escape(CharReaders.wrap(src), (CharConsumer) result::append); public char[] unescape(CharReader src, int length, CharPredicate until) throws EscapeException {
return result.toString(); src.mark();
} char[] result = new char[getUnescapedLength(src, length, until)];
src.reset();
public String unescape(String src) throws EscapeException { unescape(src, length, until, CharConsumers.fillArray(result));
StringBuilder result = new StringBuilder(src.length()); return result;
unescape(CharReaders.wrap(src), (CharConsumer) result::append); }
return result.toString();
} public char[] unescape(CharReader src, int length) throws EscapeException {
return unescape(src, length, (CharPredicate) null);
/* }
* Misc
*/ public char[] unescape(CharReader src, CharPredicate until) throws EscapeException {
return unescape(src, -1, until);
private static int hexValue(char c) throws EscapeException { }
if (c < '0') throw thisIsNotAHexDigit(c);
if (c <= '9') return c - '0'; public char[] unescape(CharReader src) throws EscapeException {
if (c < 'A') throw thisIsNotAHexDigit(c); return unescape(src, -1, (CharPredicate) null);
if (c <= 'F') return c - 'A'; }
if (c < 'a') throw thisIsNotAHexDigit(c);
if (c <= 'f') return c - 'a'; @Deprecated()
if (c == CharReader.DONE) throw new EscapeException("Incomplete Unicode escape sequence at the end"); public char[] unescape(CharacterIterator src, char until) throws EscapeException {
throw thisIsNotAHexDigit(c); int index = src.getIndex();
} CharReader reader = CharReaders.wrap(src);
private static EscapeException thisIsNotAHexDigit(char c) { char[] result = unescape(reader, -1, CharPredicate.forChar(until));
return new EscapeException("Invalid hex digit '" + c + "', expected [0-9A-Fa-f]");
} src.setIndex(index + reader.getPosition());
return result;
protected static boolean isRegular(char c) { }
return c >= ' ' && c <= '~';
} public String escape(String src) {
StringBuilder result = new StringBuilder(src.length());
/* escape(CharReaders.wrap(src), (CharConsumer) result::append);
* Getters / setters return result.toString();
*/ }
public char getEscapeChar() { public String unescape(String src) throws EscapeException {
return escapeChar; StringBuilder result = new StringBuilder(src.length());
} unescape(CharReaders.wrap(src), (CharConsumer) result::append);
return result.toString();
public char getUnicodeEscapeChar() { }
return unicodeEscapeChar;
} /*
* Misc
public char[] getSafes() { */
return safes;
} private static int hexValue(char c) throws EscapeException {
if (c < '0')
public char[] getUnsafes() { throw thisIsNotAHexDigit(c);
return unsafes; if (c <= '9')
} return c - '0';
if (c < 'A')
public boolean isPreferUnicode() { throw thisIsNotAHexDigit(c);
return preferUnicode; if (c <= 'F')
} return c - 'A';
if (c < 'a')
public boolean isStrict() { throw thisIsNotAHexDigit(c);
return strict; if (c <= 'f')
} return c - 'a';
if (c == CharReader.DONE)
} throw new EscapeException("Incomplete Unicode escape sequence at the end");
throw thisIsNotAHexDigit(c);
}
private static EscapeException thisIsNotAHexDigit(char c) {
return new EscapeException("Invalid hex digit '" + c + "', expected [0-9A-Fa-f]");
}
protected static boolean isRegular(char c) {
return c >= ' ' && c <= '~';
}
/*
* Getters / setters
*/
public char getEscapeChar() {
return escapeChar;
}
public char getUnicodeEscapeChar() {
return unicodeEscapeChar;
}
public char[] getSafes() {
return safes;
}
public char[] getUnsafes() {
return unsafes;
}
public boolean isPreferUnicode() {
return preferUnicode;
}
public boolean isStrict() {
return strict;
}
}

View File

@ -1,17 +1,21 @@
/* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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;
@ -26,77 +30,81 @@ public class FancyCharacterIterator implements CharacterIterator {
this.data = data; this.data = data;
} }
@Override @Override
public char first() { public char first() {
return obj.first(); return obj.first();
} }
@Override @Override
public char last() { public char last() {
return obj.last(); return obj.last();
} }
@Override @Override
public char setIndex(int p) { public char setIndex(int p) {
return obj.setIndex(p); return obj.setIndex(p);
} }
@Override @Override
public char current() { public char current() {
return obj.current(); return obj.current();
} }
@Override @Override
public char next() { public char next() {
return obj.next(); return obj.next();
} }
@Override @Override
public char previous() { public char previous() {
return obj.previous(); return obj.previous();
} }
@Override @Override
public int getBeginIndex() { public int getBeginIndex() {
return obj.getBeginIndex(); return obj.getBeginIndex();
} }
@Override @Override
public int getEndIndex() { public int getEndIndex() {
return obj.getEndIndex(); return obj.getEndIndex();
} }
@Override @Override
public int getIndex() { public int getIndex() {
return obj.getIndex(); return obj.getIndex();
} }
@Override @Override
public String toString() { public String toString() {
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();
} }
// @SuppressWarnings("all") Just STFU, this _is_ terrific
// SonarLint: "clone" should not be overridden (java:S2975)
// And I wouldn't have done that if only CharacterIterator had not required exception safety.
// 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"})
@Override
public FancyCharacterIterator clone() {
try {
return (FancyCharacterIterator) super.clone();
} catch (CloneNotSupportedException cnse) {
// Impossible
return null;
}
}
} // @SuppressWarnings("all") Just STFU, this _is_ terrific
// SonarLint: "clone" should not be overridden (java:S2975)
// And I wouldn't have done that if only CharacterIterator had not required
// exception safety.
// 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" })
@Override
public FancyCharacterIterator clone() {
try {
return (FancyCharacterIterator) super.clone();
} catch (CloneNotSupportedException cnse) {
// Impossible
return null;
}
}
}

View File

@ -1,135 +1,138 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
private final StringBuilder sb = new StringBuilder();
private final StringBuilder sb = new StringBuilder();
private int indentLevel = 0;
private boolean indentApplied = false; private int indentLevel = 0;
private boolean indentApplied = false;
private String[] indentCache = new String[16];
private String indent = ""; private String[] indentCache = new String[16];
private final char[] indentFill; private String indent = "";
private final char[] indentFill;
public IndentedStringBuilder(char[] indentFill) {
this.indentFill = indentFill; public IndentedStringBuilder(char[] indentFill) {
} this.indentFill = indentFill;
}
public IndentedStringBuilder(String indentFill) {
this(indentFill.toCharArray()); public IndentedStringBuilder(String indentFill) {
} this(indentFill.toCharArray());
}
public IndentedStringBuilder(char indentChar, int length) {
this(StringUtil.sequence(indentChar, length)); public IndentedStringBuilder(char indentChar, int length) {
} this(StringUtil.sequence(indentChar, length));
}
public IndentedStringBuilder() {
this(new char[] {' '}); public IndentedStringBuilder() {
} this(new char[] { ' ' });
}
@Override
public String toString() { @Override
return sb.toString(); public String toString() {
} return sb.toString();
}
public int getIndentLevel() {
return indentLevel; public int getIndentLevel() {
} return indentLevel;
}
public void setIndentLevel(int level) {
this.indentLevel = level; public void setIndentLevel(int level) {
updateIndent(); this.indentLevel = level;
} updateIndent();
}
public char[] getIndentFill() {
return indentFill; public char[] getIndentFill() {
} return indentFill;
}
protected void updateIndent() {
if (indentLevel < indentCache.length) { protected void updateIndent() {
indent = indentCache[indentLevel]; if (indentLevel < indentCache.length) {
if (indent != null) return; indent = indentCache[indentLevel];
} if (indent != null)
return;
char[] fill = getIndentFill(); }
char[] array = new char[fill.length * getIndentLevel()];
for (int i = 0; i < array.length; i += fill.length) char[] fill = getIndentFill();
System.arraycopy(fill, 0, array, i, fill.length); char[] array = new char[fill.length * getIndentLevel()];
indent = new String(array); for (int i = 0; i < array.length; i += fill.length)
System.arraycopy(fill, 0, array, i, fill.length);
if (indentLevel < indentCache.length) { indent = new String(array);
indentCache[indentLevel] = indent;
} if (indentLevel < indentCache.length) {
} indentCache[indentLevel] = indent;
}
public IndentedStringBuilder indent() { }
setIndentLevel(getIndentLevel() + 1);
return this; public IndentedStringBuilder indent() {
} setIndentLevel(getIndentLevel() + 1);
return this;
public IndentedStringBuilder unindent() { }
setIndentLevel(getIndentLevel() - 1);
return this; public IndentedStringBuilder unindent() {
} setIndentLevel(getIndentLevel() - 1);
return this;
public IndentedStringBuilder append(Object x) { }
if (x == null) {
appendRaw("null"); public IndentedStringBuilder append(Object x) {
return this; if (x == null) {
} appendRaw("null");
return this;
String str = x.toString(); }
int newLines = StringUtil.count(str, '\n');
String str = x.toString();
if (newLines == 0) { int newLines = StringUtil.count(str, '\n');
appendRaw(str);
return this; if (newLines == 0) {
} appendRaw(str);
return this;
String[] lines = StringUtil.split(str, '\n', newLines + 1); }
appendRaw(lines[0]);
String[] lines = StringUtil.split(str, '\n', newLines + 1);
for (int i = 1; i < lines.length; ++i) { appendRaw(lines[0]);
newLine();
appendRaw(lines[i]); for (int i = 1; i < lines.length; ++i) {
} newLine();
appendRaw(lines[i]);
return this; }
}
return this;
public IndentedStringBuilder appendRaw(String str) { }
if (str.isEmpty()) return this; // Do not append indent
public IndentedStringBuilder appendRaw(String str) {
if (!indentApplied) { if (str.isEmpty())
sb.append(indent); return this; // Do not append indent
indentApplied = true;
} if (!indentApplied) {
sb.append(indent);
sb.append(str); indentApplied = true;
return this; }
}
sb.append(str);
public IndentedStringBuilder newLine() { return this;
sb.append('\n'); }
indentApplied = false;
return this; public IndentedStringBuilder newLine() {
} sb.append('\n');
indentApplied = false;
} return this;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,38 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
private static final long serialVersionUID = 5392628641744570926L;
private static final long serialVersionUID = 5392628641744570926L;
public UncheckedEscapeException(String message, EscapeException cause) {
super(message, cause); public UncheckedEscapeException(String message, EscapeException cause) {
} super(message, cause);
}
public UncheckedEscapeException(EscapeException cause) {
super(cause); public UncheckedEscapeException(EscapeException cause) {
} super(cause);
}
@Override
public synchronized EscapeException getCause() { @Override
return (EscapeException) super.getCause(); public synchronized EscapeException getCause() {
} return (EscapeException) super.getCause();
}
}
}

View File

@ -1,139 +1,143 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.Reader; import java.io.IOException;
import java.nio.CharBuffer; import java.io.Reader;
import java.util.Arrays; import java.nio.CharBuffer;
import java.util.Iterator; import java.util.Arrays;
import java.util.NoSuchElementException; import java.util.Iterator;
import java.util.NoSuchElementException;
public class WordReader implements Iterator<String> {
public class WordReader implements Iterator<String> {
private final Reader reader;
private final Reader reader;
private char[] wordBuffer = new char[1024];
private final CharBuffer inputBuffer; private char[] wordBuffer = new char[1024];
private final CharBuffer inputBuffer;
private String next = null;
private boolean isExhausted = false; private String next = null;
private boolean isExhausted = false;
private IOException lastException = null;
private IOException lastException = null;
public WordReader(Reader src, int bufferSize) {
this.reader = src; public WordReader(Reader src, int bufferSize) {
this.inputBuffer = CharBuffer.allocate(bufferSize); this.reader = src;
} this.inputBuffer = CharBuffer.allocate(bufferSize);
}
public WordReader(Reader src) {
this(src, 2048); public WordReader(Reader src) {
} this(src, 2048);
}
public WordReader(char[] array, int offset, int length) {
this.reader = null; public WordReader(char[] array, int offset, int length) {
this.inputBuffer = CharBuffer.wrap(Arrays.copyOfRange(array, offset, length + offset)); this.reader = null;
} this.inputBuffer = CharBuffer.wrap(Arrays.copyOfRange(array, offset, length + offset));
}
public WordReader(char[] array) {
this.reader = null; public WordReader(char[] array) {
this.inputBuffer = CharBuffer.wrap(array); this.reader = null;
} this.inputBuffer = CharBuffer.wrap(array);
}
public WordReader(String str) {
this(str.toCharArray()); public WordReader(String str) {
} this(str.toCharArray());
}
@Override
public String next() { @Override
if (!hasNext()) { public String next() {
throw new NoSuchElementException(); if (!hasNext()) {
} throw new NoSuchElementException();
}
String result = next;
next = null; String result = next;
return result; next = null;
} return result;
}
@Override
public boolean hasNext() { @Override
if (next != null) { public boolean hasNext() {
return true; if (next != null) {
} return true;
}
if (isExhausted) {
return false; if (isExhausted) {
} return false;
}
int length = 0;
char c; int length = 0;
while (true) { char c;
c = nextChar(); while (true) {
c = nextChar();
if (isExhausted) break;
if (isExhausted)
if (Character.isWhitespace(c)) { break;
if (length == 0) continue;
else break; if (Character.isWhitespace(c)) {
} if (length == 0)
continue;
if (wordBuffer.length == length) { else
char[] newBuf = new char[wordBuffer.length * 2]; break;
System.arraycopy(wordBuffer, 0, newBuf, 0, wordBuffer.length); }
wordBuffer = newBuf;
} if (wordBuffer.length == length) {
char[] newBuf = new char[wordBuffer.length * 2];
wordBuffer[length++] = c; System.arraycopy(wordBuffer, 0, newBuf, 0, wordBuffer.length);
} wordBuffer = newBuf;
}
if (length == 0) {
return false; wordBuffer[length++] = c;
} }
next = new String(wordBuffer, 0, length); if (length == 0) {
return true; return false;
} }
private char nextChar() { next = new String(wordBuffer, 0, length);
if (!inputBuffer.hasRemaining()) { return true;
if (reader == null) { }
isExhausted = true;
return 0; private char nextChar() {
} if (!inputBuffer.hasRemaining()) {
if (reader == null) {
inputBuffer.rewind(); isExhausted = true;
try { return 0;
if (reader.read(inputBuffer) == -1) { }
isExhausted = true;
} inputBuffer.rewind();
} catch (IOException e) { try {
lastException = e; if (reader.read(inputBuffer) == -1) {
isExhausted = true; isExhausted = true;
return 0; }
} } catch (IOException e) {
lastException = e;
} isExhausted = true;
return 0;
return inputBuffer.get(); }
}
}
public IOException getLastException() {
return lastException; return inputBuffer.get();
} }
} public IOException getLastException() {
return lastException;
}
}

View File

@ -1,104 +1,108 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.
* will throw an exception if position is invalid. * Positions that are negative or lower than 0 are invalid.
*/ * {@link #current()}
protected int position = 0; * will throw an exception if position is invalid.
*/
private int[] marks = new int[DEFAULT_MARK_STACK_SIZE]; protected int position = 0;
private int nextMark = 0;
private int[] marks = new int[DEFAULT_MARK_STACK_SIZE];
protected static int closestGreaterPowerOf2(int x) { private int nextMark = 0;
x |= x >> 1;
x |= x >> 2; protected static int closestGreaterPowerOf2(int x) {
x |= x >> 4; x |= x >> 1;
x |= x >> 8; x |= x >> 2;
x |= x >> 16; x |= x >> 4;
return x + 1; x |= x >> 8;
} x |= x >> 16;
return x + 1;
/** }
* @see ru.windcorp.jputil.chars.reader.CharReader#getPosition()
*/ /**
@Override * @see ru.windcorp.jputil.chars.reader.CharReader#getPosition()
public int getPosition() { */
return position; @Override
} public int getPosition() {
return position;
/** }
* @see ru.windcorp.jputil.chars.reader.CharReader#setPosition(int)
*/ /**
@Override * @see ru.windcorp.jputil.chars.reader.CharReader#setPosition(int)
public int setPosition(int position) { */
this.position = position; @Override
return position; public int setPosition(int position) {
} this.position = position;
return position;
/** }
* @see ru.windcorp.jputil.chars.reader.CharReader#mark()
*/ /**
@Override * @see ru.windcorp.jputil.chars.reader.CharReader#mark()
public int mark() { */
ensureMarksCapacity(); @Override
marks[nextMark++] = position; public int mark() {
return position; ensureMarksCapacity();
} marks[nextMark++] = position;
return position;
/** }
* @see ru.windcorp.jputil.chars.reader.CharReader#forget()
*/ /**
@Override * @see ru.windcorp.jputil.chars.reader.CharReader#forget()
public int forget() { */
return marks[--nextMark]; @Override
} public int forget() {
return marks[--nextMark];
private void ensureMarksCapacity() { }
if (nextMark < marks.length) return;
int[] newMarks = new int[closestGreaterPowerOf2(nextMark)]; private void ensureMarksCapacity() {
System.arraycopy(marks, 0, newMarks, 0, nextMark); if (nextMark < marks.length)
marks = newMarks; return;
} int[] newMarks = new int[closestGreaterPowerOf2(nextMark)];
System.arraycopy(marks, 0, newMarks, 0, nextMark);
@Override marks = newMarks;
public String toString() { }
StringBuilder sb = new StringBuilder("\"");
@Override
mark(); public String toString() {
position = 0; StringBuilder sb = new StringBuilder("\"");
sb.append(getChars());
reset(); mark();
position = 0;
sb.append("\"\n "); sb.append(getChars());
for (int i = 0; i < position; ++i) sb.append(' '); reset();
sb.append("^ (pos " + position + ")");
return sb.toString(); sb.append("\"\n ");
} for (int i = 0; i < position; ++i)
sb.append(' ');
} sb.append("^ (pos " + position + ")");
return sb.toString();
}
}

View File

@ -1,59 +1,60 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
import ru.windcorp.jputil.ArrayUtil;
import ru.windcorp.jputil.ArrayUtil;
/**
* @author Javapony /**
* * @author Javapony
*/ */
public class ArrayCharReader extends AbstractCharReader { public class ArrayCharReader extends AbstractCharReader {
private final char[] array; private final char[] array;
private final int offset; private final int offset;
private final int length; private final int length;
public ArrayCharReader(char[] array, int offset, int length) { public ArrayCharReader(char[] array, int offset, int length) {
this.array = Objects.requireNonNull(array, "array"); this.array = Objects.requireNonNull(array, "array");
this.length = ArrayUtil.checkArrayOffsetLength(array, offset, length); this.length = ArrayUtil.checkArrayOffsetLength(array, offset, length);
this.offset = offset; this.offset = offset;
} }
/** /**
* @see ru.windcorp.jputil.chars.reader.CharReader#current() * @see ru.windcorp.jputil.chars.reader.CharReader#current()
*/ */
@Override @Override
public char current() { public char current() {
if (position >= length) return DONE; if (position >= length)
if (position < 0) return DONE;
throw new IllegalStateException("Position " + position + " is invalid"); if (position < 0)
return array[position + offset]; throw new IllegalStateException("Position " + position + " is invalid");
} return array[position + offset];
}
/**
* @see ru.windcorp.jputil.chars.reader.CharReader#remaining() /**
*/ * @see ru.windcorp.jputil.chars.reader.CharReader#remaining()
@Override */
public int remaining() { @Override
return length - position; public int remaining() {
} return length - position;
}
}
}

View File

@ -1,122 +1,128 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
protected static final int DEFAULT_BUFFER_SIZE = 256; protected static final int DEFAULT_BUFFER_SIZE = 256;
/** /**
* Buffer to store data acquired with {@link #pullChars(char[], int, int)}. * Buffer to store data acquired with {@link #pullChars(char[], int, int)}.
* Contains characters for positions <code>[0; bufferNextIndex)</code>. * Contains characters for positions <code>[0; bufferNextIndex)</code>.
*/ */
private char[] buffer = new char[DEFAULT_BUFFER_SIZE]; private char[] buffer = new char[DEFAULT_BUFFER_SIZE];
/** /**
* The index of the next character. * The index of the next character.
*/ */
private int bufferNextIndex = 0; private int bufferNextIndex = 0;
/** /**
* Whether this reader has been buffered completely. * Whether this reader has been buffered completely.
*/ */
private boolean exhausted = false; private boolean exhausted = false;
/** /**
* 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
protected abstract char pullChar(); * reached
*/
/** protected abstract char pullChar();
* Acquires next characters and stores them in the array.
* /**
* @param buffer the output array * Acquires next characters and stores them in the array.
* @param offset index of the first character *
* @param length maximum amount of characters to be pulled * @param buffer the output array
* @return the amount of characters actually pulled * @param offset index of the first character
*/ * @param length maximum amount of characters to be pulled
protected int pullChars(char[] buffer, int offset, int length) { * @return the amount of characters actually pulled
for (int i = 0; i < length; ++i) { */
if ((buffer[offset + i] = pullChar()) == DONE) { protected int pullChars(char[] buffer, int offset, int length) {
return i; for (int i = 0; i < length; ++i) {
} if ((buffer[offset + i] = pullChar()) == DONE) {
} return i;
}
return length; }
}
return length;
private int pullChars(int offset, int length) { }
if (exhausted || length == 0) return 0;
private int pullChars(int offset, int length) {
int pulled = pullChars(buffer, offset, length); if (exhausted || length == 0)
if (pulled != length) { return 0;
exhausted = true;
} int pulled = pullChars(buffer, offset, length);
if (pulled != length) {
return pulled; exhausted = true;
} }
@Override return pulled;
public char current() { }
if (getPosition() < 0) {
throw new IllegalStateException("Position " + getPosition() + " is invalid"); @Override
} public char current() {
if (getPosition() < 0) {
if (getPosition() >= bufferNextIndex) { throw new IllegalStateException("Position " + getPosition() + " is invalid");
if (exhausted) return DONE; }
ensureBufferCapacity(); if (getPosition() >= bufferNextIndex) {
if (exhausted)
int needToPull = getPosition() - bufferNextIndex + 1; return DONE;
assert needToPull <= buffer.length : "buffer size not ensured!";
ensureBufferCapacity();
int pulled = pullChars(bufferNextIndex, needToPull);
bufferNextIndex += pulled; int needToPull = getPosition() - bufferNextIndex + 1;
assert needToPull <= buffer.length : "buffer size not ensured!";
if (exhausted) return DONE;
} int pulled = pullChars(bufferNextIndex, needToPull);
bufferNextIndex += pulled;
// TODO test the shit out of current()
if (exhausted)
return buffer[getPosition()]; return DONE;
} }
private void ensureBufferCapacity() { // TODO test the shit out of current()
if (getPosition() < buffer.length) return;
char[] newBuffer = new char[closestGreaterPowerOf2(getPosition())]; return buffer[getPosition()];
System.arraycopy(buffer, 0, newBuffer, 0, bufferNextIndex); }
buffer = newBuffer;
} private void ensureBufferCapacity() {
if (getPosition() < buffer.length)
/** return;
* @see ru.windcorp.jputil.chars.reader.CharReader#remaining() char[] newBuffer = new char[closestGreaterPowerOf2(getPosition())];
*/ System.arraycopy(buffer, 0, newBuffer, 0, bufferNextIndex);
@Override buffer = newBuffer;
public int remaining() { }
if (exhausted) {
return Math.max(bufferNextIndex - getPosition(), 0); /**
} * @see ru.windcorp.jputil.chars.reader.CharReader#remaining()
*/
return super.remaining(); @Override
} public int remaining() {
if (exhausted) {
} return Math.max(bufferNextIndex - getPosition(), 0);
}
return super.remaining();
}
}

View File

@ -1,270 +1,284 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.util.Arrays; import java.io.IOException;
import java.util.Arrays;
import ru.windcorp.jputil.chars.CharPredicate;
import ru.windcorp.jputil.chars.EscapeException; import ru.windcorp.jputil.chars.CharPredicate;
import ru.windcorp.jputil.chars.Escaper; import ru.windcorp.jputil.chars.EscapeException;
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)
// DONE is an essential part of the interface // DONE is an essential part of the interface
@SuppressWarnings("squid:S1214") @SuppressWarnings("squid:S1214")
public interface CharReader { public interface CharReader {
char DONE = '\uFFFF'; char DONE = '\uFFFF';
char current(); char current();
int getPosition();
int setPosition(int position); int getPosition();
default char next() { int setPosition(int position);
return advance(1);
} default char next() {
return advance(1);
default char previous() { }
return rollBack(1);
} default char previous() {
return rollBack(1);
default char consume() { }
char c = current();
advance(1); default char consume() {
return c; char c = current();
} advance(1);
return c;
default char advance(int forward) { }
setPosition(getPosition() + forward);
return current(); default char advance(int forward) {
} setPosition(getPosition() + forward);
return current();
default char rollBack(int backward) { }
return advance(-backward);
} default char rollBack(int backward) {
return advance(-backward);
default boolean isEnd() { }
return current() == DONE;
} default boolean isEnd() {
return current() == DONE;
default boolean has() { }
return current() != DONE;
} default boolean has() {
return current() != DONE;
default boolean is(char c) { }
return current() == c;
} default boolean is(char c) {
return current() == c;
default int getChars(char[] output, int offset, int length) { }
for (int i = 0; i < length; ++i) {
if ((output[offset + i] = current()) == DONE) { default int getChars(char[] output, int offset, int length) {
return i; for (int i = 0; i < length; ++i) {
} if ((output[offset + i] = current()) == DONE) {
next(); return i;
} }
next();
return length; }
}
return length;
default int getChars(char[] output) { }
return getChars(output, 0, output.length);
} default int getChars(char[] output) {
return getChars(output, 0, output.length);
default char[] getChars(int length) { }
char[] result = new char[length];
int from = getChars(result); default char[] getChars(int length) {
if (from != length) Arrays.fill(result, from, length, DONE); char[] result = new char[length];
return result; int from = getChars(result);
} if (from != length)
Arrays.fill(result, from, length, DONE);
default char[] getChars() { return result;
return getChars(remaining()); }
}
default char[] getChars() {
default String getString(int length) { return getChars(remaining());
StringBuilder sb = new StringBuilder(); }
for (int i = 0; i < length && !isEnd(); ++i) sb.append(consume());
return sb.toString(); default String getString(int length) {
} StringBuilder sb = new StringBuilder();
for (int i = 0; i < length && !isEnd(); ++i)
default String getString() { sb.append(consume());
return getString(Integer.MAX_VALUE); return sb.toString();
} }
default boolean match(CharSequence seq) { default String getString() {
for (int i = 0; i < seq.length(); ++i) { return getString(Integer.MAX_VALUE);
if (isEnd()) return false; }
if (current() != seq.charAt(i)) return false;
next(); default boolean match(CharSequence seq) {
} for (int i = 0; i < seq.length(); ++i) {
if (isEnd())
return true; return false;
} if (current() != seq.charAt(i))
return false;
default boolean matchOrReset(CharSequence seq) { next();
mark(); }
if (match(seq)) {
forget(); return true;
return true; }
} else {
reset(); default boolean matchOrReset(CharSequence seq) {
return false; mark();
} if (match(seq)) {
} forget();
return true;
default boolean match(char[] array) { } else {
for (int i = 0; i < array.length; ++i) { reset();
if (isEnd()) return false; return false;
if (current() != array[i]) return false; }
next(); }
}
default boolean match(char[] array) {
return true; for (int i = 0; i < array.length; ++i) {
} if (isEnd())
return false;
default boolean matchOrReset(char[] array) { if (current() != array[i])
mark(); return false;
if (match(array)) { next();
forget(); }
return true;
} else { return true;
reset(); }
return false;
} default boolean matchOrReset(char[] array) {
} mark();
if (match(array)) {
default int skip(CharPredicate condition) { forget();
int i = 0; return true;
} else {
while (has() && condition.test(current())) { reset();
i++; return false;
next(); }
} }
return i; default int skip(CharPredicate condition) {
} int i = 0;
default int skipWhitespace() { while (has() && condition.test(current())) {
return skip(Character::isWhitespace); i++;
} next();
}
/**
* Skips to the end of the current line. Both <code>"\n"</code>, <code>"\r"</code> return i;
* and <code>"\r\n"</code> are considered line separators. }
* @return the amount of characters in the skipped line
*/ default int skipWhitespace() {
default int skipLine() { return skip(Character::isWhitespace);
int i = 0; }
while (!isEnd()) { /**
if (current() == '\r') { * Skips to the end of the current line. Both <code>"\n"</code>,
if (next() == '\n') { * <code>"\r"</code>
next(); * and <code>"\r\n"</code> are considered line separators.
} *
break; * @return the amount of characters in the skipped line
} else if (current() == '\n') { */
next(); default int skipLine() {
break; int i = 0;
}
while (!isEnd()) {
i++; if (current() == '\r') {
next(); if (next() == '\n') {
} next();
}
return i; break;
} } else if (current() == '\n') {
next();
default char[] readWhile(CharPredicate condition) { break;
return readUntil(CharPredicate.negate(condition)); }
}
i++;
default char[] readUntil(CharPredicate condition) { next();
mark(); }
int length = 0;
while (!isEnd() && !condition.test(current())) { return i;
length++; }
next();
} default char[] readWhile(CharPredicate condition) {
reset(); return readUntil(CharPredicate.negate(condition));
}
char[] result = new char[length];
for (int i = 0; i < length; ++i) result[i] = consume(); default char[] readUntil(CharPredicate condition) {
return result; mark();
} int length = 0;
while (!isEnd() && !condition.test(current())) {
default char[] readWord() { length++;
skipWhitespace(); next();
return readUntil(Character::isWhitespace); }
} reset();
default char[] readWord(Escaper escaper, char quotes) throws EscapeException { char[] result = new char[length];
skipWhitespace(); for (int i = 0; i < length; ++i)
result[i] = consume();
if (current() == quotes) { return result;
return escaper.unescape(this, quotes); }
} else {
return readWord(); default char[] readWord() {
} skipWhitespace();
} return readUntil(Character::isWhitespace);
}
default char[] readLine() {
mark(); default char[] readWord(Escaper escaper, char quotes) throws EscapeException {
int length = skipLine(); skipWhitespace();
reset();
if (current() == quotes) {
char[] result = new char[length]; return escaper.unescape(this, quotes);
for (int i = 0; i < result.length; ++i) result[i] = consume(); } else {
return result; return readWord();
} }
}
default int remaining() {
mark(); default char[] readLine() {
int result = 0; mark();
int length = skipLine();
while (consume() != DONE) result++; reset();
reset(); char[] result = new char[length];
return result; for (int i = 0; i < result.length; ++i)
} result[i] = consume();
return result;
int mark(); }
int forget();
default int remaining() {
default int reset() { mark();
return setPosition(forget()); int result = 0;
}
while (consume() != DONE)
default IOException getLastException() { result++;
return null;
} reset();
return result;
default void resetLastException() { }
// Do nothing
} int mark();
default boolean hasErrored() { int forget();
return getLastException() != null;
} default int reset() {
return setPosition(forget());
} }
default IOException getLastException() {
return null;
}
default void resetLastException() {
// Do nothing
}
default boolean hasErrored() {
return getLastException() != null;
}
}

View File

@ -1,112 +1,113 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.InputStreamReader; import java.io.InputStream;
import java.io.Reader; import java.io.InputStreamReader;
import java.nio.charset.Charset; import java.io.Reader;
import java.nio.charset.StandardCharsets; import java.nio.charset.Charset;
import java.text.CharacterIterator; import java.nio.charset.StandardCharsets;
import java.util.function.IntSupplier; import java.text.CharacterIterator;
import java.util.function.IntSupplier;
import ru.windcorp.jputil.chars.CharSupplier;
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) {
return new ArrayCharReader(array, offset, length); public static CharReader wrap(char[] array, int offset, int length) {
} return new ArrayCharReader(array, offset, length);
}
public static CharReader wrap(char[] array) {
return wrap(array, 0, array.length); public static CharReader wrap(char[] array) {
} return wrap(array, 0, array.length);
}
public static CharReader wrap(String str, int offset, int length) {
return new StringCharReader(str, offset, length); public static CharReader wrap(String str, int offset, int length) {
} return new StringCharReader(str, offset, length);
}
public static CharReader wrap(String str) {
return wrap(str, 0, str.length()); public static CharReader wrap(String str) {
} return wrap(str, 0, str.length());
}
public static CharReader wrap(CharSupplier supplier) {
return new BufferedCharReader() { public static CharReader wrap(CharSupplier supplier) {
@Override return new BufferedCharReader() {
protected char pullChar() { @Override
try { protected char pullChar() {
return supplier.getAsChar(); try {
} catch (Exception e) { return supplier.getAsChar();
return DONE; } catch (Exception e) {
} return DONE;
} }
}; }
} };
}
public static CharReader wrap(IntSupplier supplier) {
return new BufferedCharReader() { public static CharReader wrap(IntSupplier supplier) {
@Override return new BufferedCharReader() {
protected char pullChar() { @Override
try { protected char pullChar() {
int i = supplier.getAsInt(); try {
if (i < 0 || i > Character.MAX_VALUE) { int i = supplier.getAsInt();
return DONE; if (i < 0 || i > Character.MAX_VALUE) {
} else { return DONE;
return (char) i; } else {
} return (char) i;
} catch (Exception e) { }
return DONE; } catch (Exception e) {
} return DONE;
} }
}; }
} };
}
public static CharReader wrap(CharacterIterator it) {
return new BufferedCharReader() { public static CharReader wrap(CharacterIterator it) {
@Override return new BufferedCharReader() {
protected char pullChar() { @Override
char result = it.current(); protected char pullChar() {
it.next(); char result = it.current();
return result; it.next();
} return result;
}; }
} };
}
public static CharReader wrap(Reader reader) {
return new ReaderCharReader(reader); public static CharReader wrap(Reader reader) {
} return new ReaderCharReader(reader);
}
public static CharReader wrap(InputStream is, Charset charset) {
return wrap(new InputStreamReader(is, charset)); public static CharReader wrap(InputStream is, Charset charset) {
} return wrap(new InputStreamReader(is, charset));
}
public static CharReader wrapDefaultCS(InputStream is) {
return wrap(new InputStreamReader(is)); public static CharReader wrapDefaultCS(InputStream is) {
} return wrap(new InputStreamReader(is));
}
public static CharReader wrapUTF8(InputStream is) {
return wrap(new InputStreamReader(is, StandardCharsets.UTF_8)); public static CharReader wrapUTF8(InputStream is) {
} return wrap(new InputStreamReader(is, StandardCharsets.UTF_8));
}
}
}

View File

@ -1,70 +1,71 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.Reader; import java.io.IOException;
import java.io.Reader;
/**
* @author Javapony /**
* * @author Javapony
*/ */
public class ReaderCharReader extends BufferedCharReader { public class ReaderCharReader extends BufferedCharReader {
private final Reader src; private final Reader src;
private IOException lastException = null; private IOException lastException = null;
public ReaderCharReader(Reader src) { public ReaderCharReader(Reader src) {
this.src = src; this.src = src;
} }
/** /**
* @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChar() * @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChar()
*/ */
@Override @Override
protected char pullChar() { protected char pullChar() {
try { try {
return (char) src.read(); // Handles DONE correctly return (char) src.read(); // Handles DONE correctly
} catch (IOException e) { } catch (IOException e) {
lastException = e; lastException = e;
return DONE; return DONE;
} }
} }
/** /**
* @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChars(char[], int, int) * @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChars(char[],
*/ * int, int)
@Override */
protected int pullChars(char[] buffer, int offset, int length) { @Override
try { protected int pullChars(char[] buffer, int offset, int length) {
return src.read(buffer, offset, length); try {
} catch (IOException e) { return src.read(buffer, offset, length);
lastException = e; } catch (IOException e) {
return 0; lastException = e;
} return 0;
} }
}
/**
* @return the exception /**
*/ * @return the exception
@Override */
public IOException getLastException() { @Override
return lastException; public IOException getLastException() {
} return lastException;
}
}
}

View File

@ -1,65 +1,68 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
private final String str; private final String str;
private final int offset; private final int offset;
private final int length; private final int length;
public StringCharReader(String str, int offset, int length) { public StringCharReader(String str, int offset, int length) {
this.str = Objects.requireNonNull(str, "str"); this.str = Objects.requireNonNull(str, "str");
if (length < 0) if (length < 0)
length = str.length(); length = str.length();
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.length = length;
} this.offset = offset;
this.length = length;
/** }
* @see ru.windcorp.jputil.chars.reader.CharReader#current()
*/ /**
@Override * @see ru.windcorp.jputil.chars.reader.CharReader#current()
public char current() { */
if (position >= length) return DONE; @Override
if (position < 0) public char current() {
throw new IllegalStateException("Position " + position + " is invalid"); if (position >= length)
return str.charAt(position + offset); return DONE;
} if (position < 0)
throw new IllegalStateException("Position " + position + " is invalid");
/** return str.charAt(position + offset);
* @see ru.windcorp.jputil.chars.reader.CharReader#remaining() }
*/
@Override /**
public int remaining() { * @see ru.windcorp.jputil.chars.reader.CharReader#remaining()
return length - position; */
} @Override
public int remaining() {
} return length - position;
}
}

View File

@ -1,8 +1,26 @@
package ru.windcorp.jputil.functions; /*
* JPUtil
@FunctionalInterface * Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
public interface FloatSupplier { *
* This program is free software: you can redistribute it and/or modify
float getAsFloat(); * 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;
@FunctionalInterface
public interface FloatSupplier {
float getAsFloat();
}

View File

@ -1,72 +1,76 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
@FunctionalInterface
public interface ThrowingBiConsumer<T, U, E extends Exception> { @FunctionalInterface
public interface ThrowingBiConsumer<T, U, E extends Exception> {
@FunctionalInterface
public static interface BiConsumerHandler<T, U, E extends Exception> { @FunctionalInterface
void handle(T t, U u, E e); public static interface BiConsumerHandler<T, U, E extends Exception> {
} void handle(T t, U u, E e);
}
void accept(T t, U u) throws E;
void accept(T t, U u) throws E;
@SuppressWarnings("unchecked")
default BiConsumer<T, U> withHandler(BiConsumerHandler<? super T, ? super U, ? super E> handler) { @SuppressWarnings("unchecked")
return (t, u) -> { default BiConsumer<T, U> withHandler(BiConsumerHandler<? super T, ? super U, ? super E> handler) {
try { return (t, u) -> {
accept(t, u); try {
} catch (RuntimeException e) { accept(t, u);
throw e; } catch (RuntimeException e) {
} catch (Exception e) { throw e;
handler.handle(t, u, (E) e); } catch (Exception e) {
} handler.handle(t, u, (E) e);
}; }
} };
}
public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat(
ThrowingBiConsumer<? super T, ? super U, ? extends E> first, public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat(
ThrowingBiConsumer<? super T, ? super U, ? extends E> second) { ThrowingBiConsumer<? super T, ? super U, ? extends E> first,
return (t, u) -> { ThrowingBiConsumer<? super T, ? super U, ? extends E> second
first.accept(t, u); ) {
second.accept(t, u); return (t, u) -> {
}; first.accept(t, u);
} second.accept(t, u);
};
public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat( }
BiConsumer<? super T, ? super U> first,
ThrowingBiConsumer<? super T, ? super U, E> second) { public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat(
return (t, u) -> { BiConsumer<? super T, ? super U> first,
first.accept(t, u); ThrowingBiConsumer<? super T, ? super U, E> second
second.accept(t, u); ) {
}; return (t, u) -> {
} first.accept(t, u);
second.accept(t, u);
public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat( };
ThrowingBiConsumer<? super T, ? super U, E> first, }
BiConsumer<? super T, ? super U> second) {
return (t, u) -> { public static <T, U, E extends Exception> ThrowingBiConsumer<T, U, E> concat(
first.accept(t, u); ThrowingBiConsumer<? super T, ? super U, E> first,
second.accept(t, u); BiConsumer<? super T, ? super U> second
}; ) {
} return (t, u) -> {
first.accept(t, u);
} second.accept(t, u);
};
}
}

View File

@ -1,62 +1,72 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.Consumer; import java.util.function.BiConsumer;
import java.util.function.Consumer;
@FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> { @FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
void accept(T t) throws E;
void accept(T t) throws E;
@SuppressWarnings("unchecked")
default Consumer<T> withHandler(BiConsumer<? super T, ? super E> handler) { @SuppressWarnings("unchecked")
return t -> { default Consumer<T> withHandler(BiConsumer<? super T, ? super E> handler) {
try { return t -> {
accept(t); try {
} catch (RuntimeException e) { accept(t);
throw e; } catch (RuntimeException e) {
} catch (Exception e) { throw e;
handler.accept(t, (E) e); } catch (Exception e) {
} handler.accept(t, (E) e);
}; }
} };
}
public static <T, E extends Exception> ThrowingConsumer<T, E> concat(ThrowingConsumer<? super T, ? extends E> first, ThrowingConsumer<? super T, ? extends E> second) {
return t -> { public static <T, E extends Exception> ThrowingConsumer<T, E> concat(
first.accept(t); ThrowingConsumer<? super T, ? extends E> first,
second.accept(t); ThrowingConsumer<? super T, ? extends E> second
}; ) {
} return t -> {
first.accept(t);
public static <T, E extends Exception> ThrowingConsumer<T, E> concat(Consumer<? super T> first, ThrowingConsumer<? super T, ? extends E> second) { second.accept(t);
return t -> { };
first.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(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);
}; };
} }
} public static <T, E extends Exception> ThrowingConsumer<T, E> concat(
ThrowingConsumer<? super T, ? extends E> first,
Consumer<? super T> second
) {
return t -> {
first.accept(t);
second.accept(t);
};
}
}

View File

@ -1,73 +1,81 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.Function; import java.util.function.BiConsumer;
import java.util.function.Supplier; import java.util.function.Function;
import java.util.function.Supplier;
@FunctionalInterface
public interface ThrowingFunction<T, R, E extends Exception> { @FunctionalInterface
public interface ThrowingFunction<T, R, E extends Exception> {
R apply(T t) throws E;
R apply(T t) throws E;
@SuppressWarnings("unchecked")
default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler, Function<? super T, ? extends R> value) { @SuppressWarnings("unchecked")
return t -> { default Function<T, R> withHandler(
try { BiConsumer<? super T, ? super E> handler,
return apply(t); Function<? super T, ? extends R> value
} catch (RuntimeException e) { ) {
throw e; return t -> {
} catch (Exception e) { try {
if (handler != null) handler.accept(t, (E) e); return apply(t);
return value == null ? null : value.apply(t); } catch (RuntimeException e) {
} throw e;
}; } catch (Exception e) {
} if (handler != null)
handler.accept(t, (E) e);
default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler, Supplier<? extends R> value) { return value == null ? null : value.apply(t);
return withHandler(handler, t -> value.get()); }
} };
}
default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler, R value) {
return withHandler(handler, t -> value); default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler, Supplier<? extends R> value) {
} return withHandler(handler, t -> value.get());
}
default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler) {
return withHandler(handler, (Function<T, R>) null); default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler, R value) {
} return withHandler(handler, t -> value);
}
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
ThrowingFunction<? super T, I, ? extends E> first, default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler) {
ThrowingFunction<? super I, ? extends R, ? extends E> second) { return withHandler(handler, (Function<T, R>) null);
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, ? extends E> first,
Function<? super T, I> first, ThrowingFunction<? super I, ? extends R, ? extends 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, Function<? super T, I> first,
Function<? super I, ? extends R> 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(
ThrowingFunction<? super T, I, E> first,
Function<? super I, ? extends R> second
) {
return t -> second.apply(first.apply(t));
}
}

View File

@ -1,64 +1,65 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
@FunctionalInterface
public interface ThrowingRunnable<E extends Exception> { @FunctionalInterface
public interface ThrowingRunnable<E extends Exception> {
void run() throws E;
void run() throws E;
@SuppressWarnings("unchecked")
default Runnable withHandler(Consumer<? super E> handler) { @SuppressWarnings("unchecked")
return () -> { default Runnable withHandler(Consumer<? super E> handler) {
try { return () -> {
run(); try {
} catch (RuntimeException e) { run();
throw e; } catch (RuntimeException e) {
} catch (Exception e) { throw e;
handler.accept((E) e); } catch (Exception e) {
} handler.accept((E) e);
}; }
} };
}
public static <E extends Exception> ThrowingRunnable<E> concat(
ThrowingRunnable<? extends E> first, public static <E extends Exception> ThrowingRunnable<E> concat(
ThrowingRunnable<? extends E> second ThrowingRunnable<? extends E> first,
) { ThrowingRunnable<? extends E> second
return () -> { ) {
first.run(); return () -> {
second.run(); first.run();
}; second.run();
} };
}
public static <E extends Exception> ThrowingRunnable<E> concat(Runnable first, ThrowingRunnable<E> second) {
return () -> { public static <E extends Exception> ThrowingRunnable<E> concat(Runnable first, ThrowingRunnable<E> second) {
first.run(); return () -> {
second.run(); first.run();
}; second.run();
} };
}
public static <E extends Exception> ThrowingRunnable<E> concat(ThrowingRunnable<E> first, Runnable second) {
return () -> { public static <E extends Exception> ThrowingRunnable<E> concat(ThrowingRunnable<E> first, Runnable second) {
first.run(); return () -> {
second.run(); first.run();
}; second.run();
} };
}
}
}

View File

@ -1,50 +1,52 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.Supplier; import java.util.function.Consumer;
import java.util.function.Supplier;
@FunctionalInterface
public interface ThrowingSupplier<T, E extends Exception> { @FunctionalInterface
public interface ThrowingSupplier<T, E extends Exception> {
T get() throws E;
T get() throws E;
@SuppressWarnings("unchecked")
default Supplier<T> withHandler(Consumer<? super E> handler, Supplier<? extends T> value) { @SuppressWarnings("unchecked")
return () -> { default Supplier<T> withHandler(Consumer<? super E> handler, Supplier<? extends T> value) {
try { return () -> {
return get(); try {
} catch (RuntimeException e) { return get();
throw e; } catch (RuntimeException e) {
} catch (Exception e) { throw e;
if (handler != null) handler.accept((E) e); } catch (Exception e) {
return value == null ? null : value.get(); if (handler != null)
} handler.accept((E) e);
}; return value == null ? null : value.get();
} }
};
default Supplier<T> withHandler(Consumer<? super E> handler, T value) { }
return withHandler(handler, () -> value);
} default Supplier<T> withHandler(Consumer<? super E> handler, T value) {
return withHandler(handler, () -> value);
default Supplier<T> withHandler(Consumer<? super E> handler) { }
return withHandler(handler, (Supplier<T>) null);
} default Supplier<T> withHandler(Consumer<? super E> handler) {
return withHandler(handler, (Supplier<T>) null);
} }
}

View File

@ -1,47 +1,48 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.NoSuchElementException; import java.util.Iterator;
import java.util.NoSuchElementException;
public class ArrayIterator<E> implements Iterator<E> {
public class ArrayIterator<E> implements Iterator<E> {
private final E[] array;
private int next; private final E[] array;
private int next;
@SafeVarargs
public ArrayIterator(E... array) { @SafeVarargs
this.array = array; public ArrayIterator(E... array) {
} this.array = array;
}
@Override
public boolean hasNext() { @Override
return next < array.length; public boolean hasNext() {
} return next < array.length;
}
@Override
public E next() { @Override
try { public E next() {
return array[next++]; try {
} catch (ArrayIndexOutOfBoundsException e) { return array[next++];
throw new NoSuchElementException(); } catch (ArrayIndexOutOfBoundsException e) {
} throw new NoSuchElementException();
} }
}
}
}

View File

@ -1,61 +1,61 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.Function; import java.util.Iterator;
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> {
private final Iterator<T> parent; private final Iterator<T> parent;
private final Function<T, E> function; private final Function<T, E> function;
public FunctionIterator(Iterator<T> parent, Function<T, E> function) { public FunctionIterator(Iterator<T> parent, Function<T, E> function) {
this.parent = parent; this.parent = parent;
this.function = function; this.function = function;
} }
/** /**
* @see java.util.Iterator#hasNext() * @see java.util.Iterator#hasNext()
*/ */
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return parent.hasNext(); return parent.hasNext();
} }
/** /**
* @see java.util.Iterator#next() * @see java.util.Iterator#next()
*/ */
@Override @Override
public E next() { public E next() {
return function.apply(parent.next()); return function.apply(parent.next());
} }
/** /**
* @see java.util.Iterator#remove() * @see java.util.Iterator#remove()
*/ */
@Override @Override
public void remove() { public void remove() {
parent.remove(); parent.remove();
} }
} }

View File

@ -1,60 +1,62 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.NoSuchElementException; import java.util.Iterator;
import java.util.NoSuchElementException;
public class PeekingIterator<E> implements Iterator<E> {
public class PeekingIterator<E> implements Iterator<E> {
private final Iterator<? extends E> source;
private E next = null; private final Iterator<? extends E> source;
private E next = null;
public PeekingIterator(Iterator<? extends E> source) {
this.source = source; public PeekingIterator(Iterator<? extends E> source) {
} this.source = source;
}
@Override
public boolean hasNext() { @Override
return next != null || source.hasNext(); public boolean hasNext() {
} return next != null || source.hasNext();
}
public E peek() {
if (next == null) { public E peek() {
if (source.hasNext()) { if (next == null) {
next = source.next(); if (source.hasNext()) {
} else { next = source.next();
throw new NoSuchElementException(); } else {
} throw new NoSuchElementException();
} }
}
return next;
} return next;
}
// SonarLint: "Iterator.next()" methods should throw "NoSuchElementException" (java:S2272)
// peek() throws NoSuchElementException as expected // SonarLint: "Iterator.next()" methods should throw
@SuppressWarnings("squid:S2272") // "NoSuchElementException" (java:S2272)
// peek() throws NoSuchElementException as expected
@Override @SuppressWarnings("squid:S2272")
public E next() {
E element = peek(); @Override
next = null; public E next() {
return element; E element = peek();
} next = null;
return element;
} }
}

View File

@ -1,67 +1,70 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.NoSuchElementException; import java.util.Iterator;
import java.util.NoSuchElementException;
public class RangeIterator<E> implements Iterator<E> {
public class RangeIterator<E> implements Iterator<E> {
private final Iterator<E> parent;
private final int from; private final Iterator<E> parent;
private final int amount; private final int from;
private final int amount;
private int nextIndex = 0;
private int nextIndex = 0;
public RangeIterator(Iterator<E> iterator, int from, int amount) {
this.parent = iterator; public RangeIterator(Iterator<E> iterator, int from, int amount) {
this.from = from; this.parent = iterator;
this.amount = amount < 0 ? Integer.MAX_VALUE : amount; this.from = from;
} this.amount = amount < 0 ? Integer.MAX_VALUE : amount;
}
public RangeIterator(Iterator<E> iterator, int from) {
this(iterator, from, -1); public RangeIterator(Iterator<E> iterator, int from) {
} this(iterator, from, -1);
}
@Override
public boolean hasNext() { @Override
update(); public boolean hasNext() {
return nextIndex < from + amount && parent.hasNext(); update();
} return nextIndex < from + amount && parent.hasNext();
}
@Override
public E next() { @Override
update(); public E next() {
if (nextIndex >= from + amount) { update();
throw new NoSuchElementException("RangeIterator about to retrieve element " + nextIndex if (nextIndex >= from + amount) {
+ " which exceeds upper boundary " + (from + amount)); throw new NoSuchElementException(
} "RangeIterator about to retrieve element " + nextIndex
+ " which exceeds upper boundary " + (from + amount)
E result = parent.next(); );
nextIndex++; }
return result;
} E result = parent.next();
nextIndex++;
protected void update() { return result;
while (nextIndex < from && parent.hasNext()) { }
parent.next();
nextIndex++; protected void update() {
} while (nextIndex < from && parent.hasNext()) {
} parent.next();
nextIndex++;
} }
}
}

View File

@ -1,70 +1,72 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.Iterator; import java.util.ArrayList;
import java.util.NoSuchElementException; import java.util.Iterator;
import java.util.NoSuchElementException;
public class Reiterator<E> implements Iterable<E> {
public class Reiterator<E> implements Iterable<E> {
private class ReiteratorIterator implements Iterator<E> {
private class ReiteratorIterator implements Iterator<E> {
int index = 0;
int index = 0;
@Override
public boolean hasNext() { @Override
synchronized (source) { public boolean hasNext() {
if (index >= data.size()) { synchronized (source) {
if (!source.hasNext()) { if (index >= data.size()) {
return false; if (!source.hasNext()) {
} else { return false;
data.add(source.next()); } else {
} data.add(source.next());
} }
}
return true;
} return true;
} }
}
@Override
public E next() { @Override
E result; public E next() {
synchronized (source) { E result;
if (!hasNext()) throw new NoSuchElementException(); synchronized (source) {
result = data.get(index); if (!hasNext())
} throw new NoSuchElementException();
index++; result = data.get(index);
return result; }
} index++;
return result;
} }
private final Iterator<E> source; }
private final ArrayList<E> data = new ArrayList<>();
private final Iterator<E> source;
public Reiterator(Iterator<E> source) { private final ArrayList<E> data = new ArrayList<>();
this.source = source;
} public Reiterator(Iterator<E> source) {
this.source = source;
@Override }
public Iterator<E> iterator() {
return new ReiteratorIterator(); @Override
} public Iterator<E> iterator() {
return new ReiteratorIterator();
} }
}

View File

@ -1,39 +1,40 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
private final String[] names;
private final String[] names;
public AbstractSelectorOperator(String[] names) {
this.names = names; public AbstractSelectorOperator(String[] names) {
} this.names = names;
}
@Override
public boolean matchesName(String name) { @Override
for (String n : names) { public boolean matchesName(String name) {
if (n.equals(name)) { for (String n : names) {
return true; if (n.equals(name)) {
} return true;
} }
}
return false;
} return false;
}
}
}

View File

@ -1,57 +1,58 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.chars.StringUtil; import ru.windcorp.jputil.SyntaxException;
import ru.windcorp.jputil.chars.StringUtil;
public abstract class NamedParameterizedSelector<T> extends NamedSelector<T> {
public abstract class NamedParameterizedSelector<T> extends NamedSelector<T> {
private final char separator;
private String givenName; private final char separator;
private String givenName;
public NamedParameterizedSelector(char separator, String... names) {
super(names); public NamedParameterizedSelector(char separator, String... names) {
this.separator = separator; super(names);
} this.separator = separator;
}
@Override
public Selector<T> derive(String name) throws SyntaxException { @Override
String[] parts = StringUtil.split(name, separator, 2); public Selector<T> derive(String name) throws SyntaxException {
String[] parts = StringUtil.split(name, separator, 2);
if (parts[1] == null) {
return null; if (parts[1] == null) {
} return null;
}
if (!matchesName(parts[0])) {
return null; if (!matchesName(parts[0])) {
} return null;
}
NamedParameterizedSelector<T> selector = deriveImpl(parts[1]);
selector.givenName = name; NamedParameterizedSelector<T> selector = deriveImpl(parts[1]);
return selector; selector.givenName = name;
} return selector;
}
protected abstract NamedParameterizedSelector<T> deriveImpl(String param) throws SyntaxException;
protected abstract NamedParameterizedSelector<T> deriveImpl(String param) throws SyntaxException;
@Override
public String toString() { @Override
return givenName; public String toString() {
} return givenName;
}
}
}

View File

@ -1,50 +1,51 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
public abstract class NamedSelector<T> implements Selector<T> {
public abstract class NamedSelector<T> implements Selector<T> {
private final String[] names;
private final String[] names;
public NamedSelector(String... names) {
this.names = names; public NamedSelector(String... names) {
} this.names = names;
}
public boolean matchesName(String name) {
for (String n : names) { public boolean matchesName(String name) {
if (n.equalsIgnoreCase(name)) { for (String n : names) {
return true; if (n.equalsIgnoreCase(name)) {
} return true;
} }
}
return false;
} return false;
}
@Override
public Selector<T> derive(String name) throws SyntaxException { @Override
return matchesName(name) ? this : null; public Selector<T> derive(String name) throws SyntaxException {
} return matchesName(name) ? this : null;
}
@Override
public String toString() { @Override
return names[0]; public String toString() {
} return names[0];
}
}
}

View File

@ -1,36 +1,37 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.Predicate; import java.util.Deque;
import java.util.function.Predicate;
public class OperatorAnd extends AbstractSelectorOperator {
public class OperatorAnd extends AbstractSelectorOperator {
public OperatorAnd(String... names) {
super(names); public OperatorAnd(String... names) {
} super(names);
}
@Override
public <T> void process(Deque<Predicate<T>> stack) { @Override
Predicate<T> arg2 = stack.pop(); public <T> void process(Deque<Predicate<T>> stack) {
Predicate<T> arg1 = stack.pop(); Predicate<T> arg2 = stack.pop();
stack.push(obj -> arg1.test(obj) && arg2.test(obj)); Predicate<T> arg1 = stack.pop();
} stack.push(obj -> arg1.test(obj) && arg2.test(obj));
}
}
}

View File

@ -1,36 +1,37 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.Predicate; import java.util.Deque;
import java.util.function.Predicate;
public class OperatorExclude extends AbstractSelectorOperator {
public class OperatorExclude extends AbstractSelectorOperator {
public OperatorExclude(String... names) {
super(names); public OperatorExclude(String... names) {
} super(names);
}
@Override
public <T> void process(Deque<Predicate<T>> stack) { @Override
Predicate<T> arg2 = stack.pop(); public <T> void process(Deque<Predicate<T>> stack) {
Predicate<T> arg1 = stack.pop(); Predicate<T> arg2 = stack.pop();
stack.push(obj -> arg1.test(obj) && !arg2.test(obj)); Predicate<T> arg1 = stack.pop();
} stack.push(obj -> arg1.test(obj) && !arg2.test(obj));
}
}
}

View File

@ -1,34 +1,35 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.Predicate; import java.util.Deque;
import java.util.function.Predicate;
public class OperatorNot extends AbstractSelectorOperator {
public class OperatorNot extends AbstractSelectorOperator {
public OperatorNot(String... names) {
super(names); public OperatorNot(String... names) {
} super(names);
}
@Override
public <T> void process(Deque<Predicate<T>> stack) { @Override
stack.push(stack.pop().negate()); public <T> void process(Deque<Predicate<T>> stack) {
} stack.push(stack.pop().negate());
}
}
}

View File

@ -1,36 +1,37 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.Predicate; import java.util.Deque;
import java.util.function.Predicate;
public class OperatorOr extends AbstractSelectorOperator {
public class OperatorOr extends AbstractSelectorOperator {
public OperatorOr(String... names) {
super(names); public OperatorOr(String... names) {
} super(names);
}
@Override
public <T> void process(Deque<Predicate<T>> stack) { @Override
Predicate<T> arg2 = stack.pop(); public <T> void process(Deque<Predicate<T>> stack) {
Predicate<T> arg1 = stack.pop(); Predicate<T> arg2 = stack.pop();
stack.push(obj -> arg1.test(obj) || arg2.test(obj)); Predicate<T> arg1 = stack.pop();
} stack.push(obj -> arg1.test(obj) || arg2.test(obj));
}
}
}

View File

@ -1,36 +1,37 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.Predicate; import java.util.Deque;
import java.util.function.Predicate;
public class OperatorXor extends AbstractSelectorOperator {
public class OperatorXor extends AbstractSelectorOperator {
public OperatorXor(String... names) {
super(names); public OperatorXor(String... names) {
} super(names);
}
@Override
public <T> void process(Deque<Predicate<T>> stack) { @Override
Predicate<T> arg2 = stack.pop(); public <T> void process(Deque<Predicate<T>> stack) {
Predicate<T> arg1 = stack.pop(); Predicate<T> arg2 = stack.pop();
stack.push(obj -> arg1.test(obj) != arg2.test(obj)); Predicate<T> arg1 = stack.pop();
} stack.push(obj -> arg1.test(obj) != arg2.test(obj));
}
}
}

View File

@ -1,36 +1,37 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
public class PredicateWrapper<T> extends NamedSelector<T> {
public class PredicateWrapper<T> extends NamedSelector<T> {
private final Predicate<? super T> predicate;
private final Predicate<? super T> predicate;
public PredicateWrapper(String name, Predicate<? super T> predicate) {
super(name); public PredicateWrapper(String name, Predicate<? super T> predicate) {
this.predicate = predicate; super(name);
} this.predicate = predicate;
}
@Override
public boolean test(T obj) { @Override
return predicate.test(obj); public boolean test(T obj) {
} return predicate.test(obj);
}
}
}

View File

@ -1,28 +1,29 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
import ru.windcorp.jputil.SyntaxException;
import ru.windcorp.jputil.SyntaxException;
public interface Selector<T> extends Predicate<T> {
public interface Selector<T> extends Predicate<T> {
public Selector<T> derive(String name) throws SyntaxException;
public Selector<T> derive(String name) throws SyntaxException;
}
}

View File

@ -1,29 +1,30 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.function.Predicate; import java.util.Deque;
import java.util.function.Predicate;
public interface SelectorOperator {
public interface SelectorOperator {
public <T> void process(Deque<Predicate<T>> stack);
public <T> void process(Deque<Predicate<T>> stack);
public boolean matchesName(String name);
public boolean matchesName(String name);
}
}

View File

@ -1,176 +1,175 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.Collection; import java.util.ArrayList;
import java.util.Collections; import java.util.Collection;
import java.util.Deque; import java.util.Collections;
import java.util.Iterator; import java.util.Deque;
import java.util.LinkedList; import java.util.Iterator;
import java.util.function.Predicate; import java.util.LinkedList;
import java.util.function.Predicate;
import ru.windcorp.jputil.SyntaxException;
import ru.windcorp.jputil.iterators.PeekingIterator; import ru.windcorp.jputil.SyntaxException;
import ru.windcorp.jputil.iterators.PeekingIterator;
public class SelectorSystem<T> {
public class SelectorSystem<T> {
public static final char EXPRESSION_OPEN = '(';
public static final char EXPRESSION_CLOSE = ')'; public static final char EXPRESSION_OPEN = '(';
public static final char EXPRESSION_CLOSE = ')';
private final Collection<Selector<T>> selectors =
Collections.synchronizedCollection(new ArrayList<Selector<T>>()); private final Collection<Selector<T>> selectors = 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;
public Collection<Selector<T>> getSelectors() { public Collection<Selector<T>> getSelectors() {
return this.selectors; return this.selectors;
} }
public Collection<SelectorOperator> getSelectorOperators() { public Collection<SelectorOperator> getSelectorOperators() {
return this.operators; return this.operators;
} }
public String getStackPrefix() { public String getStackPrefix() {
return stackPrefix; return stackPrefix;
} }
public SelectorSystem<T> setStackPrefix(String stackPrefix) { public SelectorSystem<T> setStackPrefix(String stackPrefix) {
this.stackPrefix = stackPrefix; this.stackPrefix = stackPrefix;
return this; return this;
} }
public SelectorSystem<T> add(Selector<T> selector) { public SelectorSystem<T> add(Selector<T> selector) {
getSelectors().add(selector); getSelectors().add(selector);
return this; return this;
} }
public SelectorSystem<T> add(SelectorOperator operator) { public SelectorSystem<T> add(SelectorOperator operator) {
getSelectorOperators().add(operator); getSelectorOperators().add(operator);
return this; return this;
} }
public Predicate<T> parse(Iterator<String> tokens) throws SyntaxException { public Predicate<T> parse(Iterator<String> tokens) throws SyntaxException {
PeekingIterator<String> peeker = new PeekingIterator<>(tokens); PeekingIterator<String> peeker = new PeekingIterator<>(tokens);
if (getStackPrefix() != null && peeker.hasNext() && getStackPrefix().equals(peeker.peek())) { if (getStackPrefix() != null && peeker.hasNext() && getStackPrefix().equals(peeker.peek())) {
peeker.next(); peeker.next();
return parseStack(peeker); return parseStack(peeker);
} }
Deque<Predicate<T>> stack = new LinkedList<>(); Deque<Predicate<T>> stack = new LinkedList<>();
synchronized (getSelectorOperators()) { synchronized (getSelectorOperators()) {
synchronized (getSelectors()) { synchronized (getSelectors()) {
while (peeker.hasNext()) { while (peeker.hasNext()) {
parseToken(stack, peeker); parseToken(stack, peeker);
} }
} }
} }
return compress(stack); return compress(stack);
} }
private void parseToken(Deque<Predicate<T>> stack, Iterator<String> tokens) throws SyntaxException { private void parseToken(Deque<Predicate<T>> stack, Iterator<String> tokens) throws SyntaxException {
if (!tokens.hasNext()) { if (!tokens.hasNext()) {
throw new SyntaxException("Not enough tokens"); throw new SyntaxException("Not enough tokens");
} }
String token = tokens.next(); String token = tokens.next();
for (SelectorOperator operator : getSelectorOperators()) { for (SelectorOperator operator : getSelectorOperators()) {
if (operator.matchesName(token.toLowerCase())) { if (operator.matchesName(token.toLowerCase())) {
parseToken(stack, tokens); parseToken(stack, tokens);
operator.process(stack); operator.process(stack);
return; return;
} }
} }
Selector<T> tmp; Selector<T> tmp;
for (Selector<T> selector : getSelectors()) { for (Selector<T> selector : getSelectors()) {
if ((tmp = selector.derive(token)) != null) { if ((tmp = selector.derive(token)) != null) {
stack.push(tmp); stack.push(tmp);
return; return;
} }
} }
throw new SyntaxException("Unknown token \"" + token + "\""); throw new SyntaxException("Unknown token \"" + token + "\"");
} }
public Predicate<T> parseStack(Iterator<String> tokens) throws SyntaxException { public Predicate<T> parseStack(Iterator<String> tokens) throws SyntaxException {
Deque<Predicate<T>> stack = new LinkedList<>(); Deque<Predicate<T>> stack = new LinkedList<>();
String token; String token;
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()) { if (operator.matchesName(token.toLowerCase())) {
if (operator.matchesName(token.toLowerCase())) { operator.process(stack);
operator.process(stack); continue tokenCycle;
continue tokenCycle; }
} }
}
for (Selector<T> selector : getSelectors()) {
for (Selector<T> selector : getSelectors()) { Selector<T> tmp;
Selector<T> tmp; if ((tmp = selector.derive(token)) != null) {
if ((tmp = selector.derive(token)) != null) { stack.push(tmp);
stack.push(tmp); continue tokenCycle;
continue tokenCycle; }
} }
}
throw new SyntaxException("Unknown token \"" + token + "\"");
throw new SyntaxException("Unknown token \"" + token + "\"");
}
} }
} }
}
return compress(stack);
return compress(stack); }
}
private Predicate<T> compress(Deque<Predicate<T>> stack) throws SyntaxException {
private Predicate<T> compress(Deque<Predicate<T>> stack) throws SyntaxException { if (stack.isEmpty()) {
if (stack.isEmpty()) { throw new SyntaxException("Stack is empty");
throw new SyntaxException("Stack is empty"); }
}
if (stack.size() == 1) {
if (stack.size() == 1) { return stack.pop();
return stack.pop(); }
}
return obj -> {
return obj -> { for (Predicate<? super T> predicate : stack) {
for (Predicate<? super T> predicate : stack) { if (predicate.test(obj)) {
if (predicate.test(obj)) { return true;
return true; }
} }
}
return false;
return false; };
}; }
}
}
}

View File

@ -1,22 +1,23 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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,51 +1,52 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.analyzers.OutOfMemoryAnalyzer; import ru.windcorp.progressia.common.util.crash.CrashReports;
import ru.windcorp.progressia.common.util.crash.providers.*; import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer;
import ru.windcorp.progressia.common.util.crash.providers.*;
public class ProgressiaLauncher {
public class ProgressiaLauncher {
public static String[] arguments;
public static String[] arguments;
public static void launch(String[] args, Proxy proxy) {
arguments = args.clone(); public static void launch(String[] args, Proxy proxy) {
setupCrashReports(); arguments = args.clone();
proxy.initialize(); setupCrashReports();
} proxy.initialize();
}
private static void setupCrashReports() {
// Context providers private static void setupCrashReports() {
CrashReports.registerProvider(new OSContextProvider()); // Context providers
CrashReports.registerProvider(new RAMContextProvider()); CrashReports.registerProvider(new OSContextProvider());
CrashReports.registerProvider(new JavaVersionContextProvider()); CrashReports.registerProvider(new RAMContextProvider());
CrashReports.registerProvider(new OpenALContextProvider()); CrashReports.registerProvider(new JavaVersionContextProvider());
CrashReports.registerProvider(new ArgsContextProvider()); CrashReports.registerProvider(new OpenALContextProvider());
CrashReports.registerProvider(new LanguageContextProvider()); CrashReports.registerProvider(new ArgsContextProvider());
CrashReports.registerProvider(new StackTraceProvider()); CrashReports.registerProvider(new LanguageContextProvider());
// Analyzers CrashReports.registerProvider(new ScreenContextProvider());
CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer()); // Analyzers
CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer());
Thread.setDefaultUncaughtExceptionHandler((Thread thread, Throwable t)-> {
CrashReports.crash(t, "Uncaught exception in thread %s", thread.getName()); Thread.setDefaultUncaughtExceptionHandler((Thread thread, Throwable t) -> {
}); CrashReports.crash(t, "Uncaught exception in thread %s", thread.getName());
} });
}
}
}

View File

@ -1,24 +1,25 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
void initialize();
void initialize();
}
}

View File

@ -1,59 +1,79 @@
package ru.windcorp.progressia.client; /*
* Progressia
import ru.windcorp.progressia.client.comms.DefaultClientCommsListener; * Copyright (C) 2020-2021 Wind Corporation and contributors
import ru.windcorp.progressia.client.comms.ServerCommsChannel; *
import ru.windcorp.progressia.client.graphics.world.Camera; * This program is free software: you can redistribute it and/or modify
import ru.windcorp.progressia.client.graphics.world.EntityAnchor; * it under the terms of the GNU General Public License as published by
import ru.windcorp.progressia.client.graphics.world.LocalPlayer; * the Free Software Foundation, either version 3 of the License, or
import ru.windcorp.progressia.client.world.WorldRender; * (at your option) any later version.
import ru.windcorp.progressia.common.world.WorldData; *
import ru.windcorp.progressia.common.world.entity.EntityData; * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
public class Client { * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
private final WorldRender world; *
private final LocalPlayer localPlayer = new LocalPlayer(this); * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
private final Camera camera = new Camera((float) Math.toRadians(70)); */
private final ServerCommsChannel comms; package ru.windcorp.progressia.client;
public Client(WorldData world, ServerCommsChannel comms) { import ru.windcorp.progressia.client.comms.DefaultClientCommsListener;
this.world = new WorldRender(world, this); import ru.windcorp.progressia.client.comms.ServerCommsChannel;
this.comms = comms; import ru.windcorp.progressia.client.graphics.world.Camera;
import ru.windcorp.progressia.client.graphics.world.EntityAnchor;
comms.addListener(new DefaultClientCommsListener(this)); import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
} import ru.windcorp.progressia.client.world.WorldRender;
import ru.windcorp.progressia.common.world.WorldData;
public WorldRender getWorld() { import ru.windcorp.progressia.common.world.entity.EntityData;
return world;
} public class Client {
public LocalPlayer getLocalPlayer() { private final WorldRender world;
return localPlayer; private final LocalPlayer localPlayer = new LocalPlayer(this);
}
private final Camera camera = new Camera((float) Math.toRadians(70));
public boolean isReady() {
return localPlayer.hasEntity(); private final ServerCommsChannel comms;
}
public Client(WorldData world, ServerCommsChannel comms) {
public Camera getCamera() { this.world = new WorldRender(world, this);
return camera; this.comms = comms;
}
comms.addListener(new DefaultClientCommsListener(this));
public ServerCommsChannel getComms() { }
return comms;
} public WorldRender getWorld() {
return world;
public void onLocalPlayerEntityChanged(EntityData entity, EntityData lastKnownEntity) { }
if (entity == null) {
getCamera().setAnchor(null); public LocalPlayer getLocalPlayer() {
return; return localPlayer;
} }
getCamera().setAnchor(new EntityAnchor( public boolean isReady() {
getWorld().getEntityRenderable(entity) return localPlayer.hasEntity();
)); }
}
public Camera getCamera() {
} return camera;
}
public ServerCommsChannel getComms() {
return comms;
}
public void onLocalPlayerEntityChanged(EntityData entity, EntityData lastKnownEntity) {
if (entity == null) {
getCamera().setAnchor(null);
return;
}
getCamera().setAnchor(
new EntityAnchor(
getWorld().getEntityRenderable(entity)
)
);
}
}

View File

@ -1,54 +1,67 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.client.graphics.backend.GraphicsBackend; import ru.windcorp.progressia.Proxy;
import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue; import ru.windcorp.progressia.client.audio.AudioSystem;
import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram; import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend;
import ru.windcorp.progressia.client.graphics.font.GNUUnifontLoader; import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue;
import ru.windcorp.progressia.client.graphics.font.Typefaces; import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram;
import ru.windcorp.progressia.client.graphics.texture.Atlases; import ru.windcorp.progressia.client.graphics.font.GNUUnifontLoader;
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram; import ru.windcorp.progressia.client.graphics.font.Typefaces;
import ru.windcorp.progressia.common.resource.ResourceManager; import ru.windcorp.progressia.client.graphics.texture.Atlases;
import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
import ru.windcorp.progressia.server.ServerState; import ru.windcorp.progressia.client.localization.Localizer;
import ru.windcorp.progressia.test.TestContent; import ru.windcorp.progressia.common.resource.ResourceManager;
import ru.windcorp.progressia.common.util.crash.CrashReports;
public class ClientProxy implements Proxy { import ru.windcorp.progressia.server.ServerState;
import ru.windcorp.progressia.test.TestContent;
@Override import ru.windcorp.progressia.test.TestMusicPlayer;
public void initialize() {
GraphicsBackend.initialize(); public class ClientProxy implements Proxy {
try {
RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init); @Override
RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); public void initialize() {
RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz")))); GraphicsBackend.initialize();
} catch (InterruptedException e) { try {
throw CrashReports.report(e, "ClientProxy failed"); RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init);
} RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init);
RenderTaskQueue.waitAndInvoke(
TestContent.registerContent(); () -> Typefaces
.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz")))
Atlases.loadAllAtlases(); );
} catch (InterruptedException e) {
ServerState.startServer(); throw CrashReports.report(e, "ClientProxy failed");
ClientState.connectToLocalServer(); }
}
Localizer.getInstance().setLanguage("en-US");
}
TestContent.registerContent();
Atlases.loadAllAtlases();
AudioSystem.initialize();
ServerState.startServer();
ClientState.connectToLocalServer();
TestMusicPlayer.start();
}
}

View File

@ -1,46 +1,65 @@
package ru.windcorp.progressia.client; /*
* Progressia
import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; * Copyright (C) 2020-2021 Wind Corporation and contributors
import ru.windcorp.progressia.client.graphics.GUI; *
import ru.windcorp.progressia.client.graphics.world.LayerWorld; * This program is free software: you can redistribute it and/or modify
import ru.windcorp.progressia.common.world.WorldData; * it under the terms of the GNU General Public License as published by
import ru.windcorp.progressia.server.ServerState; * the Free Software Foundation, either version 3 of the License, or
import ru.windcorp.progressia.test.LayerTestGUI; * (at your option) any later version.
import ru.windcorp.progressia.test.LayerTestUI; *
import ru.windcorp.progressia.test.TestContent; * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
public class ClientState { * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
private static Client instance; *
* You should have received a copy of the GNU General Public License
public static Client getInstance() { * along with this program. If not, see <https://www.gnu.org/licenses/>.
return instance; */
}
package ru.windcorp.progressia.client;
public static void setInstance(Client instance) {
ClientState.instance = instance; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel;
} import ru.windcorp.progressia.client.graphics.GUI;
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
public static void connectToLocalServer() { import ru.windcorp.progressia.common.world.WorldData;
import ru.windcorp.progressia.server.ServerState;
WorldData world = new WorldData(); import ru.windcorp.progressia.test.LayerAbout;
import ru.windcorp.progressia.test.LayerTestUI;
LocalServerCommsChannel channel = new LocalServerCommsChannel( import ru.windcorp.progressia.test.TestContent;
ServerState.getInstance()
); public class ClientState {
Client client = new Client(world, channel); private static Client instance;
channel.connect(TestContent.PLAYER_LOGIN); public static Client getInstance() {
return instance;
setInstance(client); }
GUI.addBottomLayer(new LayerWorld(client)); public static void setInstance(Client instance) {
GUI.addTopLayer(new LayerTestUI()); ClientState.instance = instance;
GUI.addTopLayer(new LayerTestGUI()); }
} public static void connectToLocalServer() {
private ClientState() {} WorldData world = new WorldData();
} LocalServerCommsChannel channel = new LocalServerCommsChannel(
ServerState.getInstance()
);
Client client = new Client(world, channel);
channel.connect(TestContent.PLAYER_LOGIN);
setInstance(client);
GUI.addBottomLayer(new LayerWorld(client));
GUI.addTopLayer(new LayerTestUI());
GUI.addTopLayer(new LayerAbout());
}
private ClientState() {
}
}

View File

@ -1,28 +1,29 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
public class ProgressiaClientMain {
public class ProgressiaClientMain {
public static void main(String[] args) {
ProgressiaLauncher.launch(args, new ClientProxy()); public static void main(String[] args) {
} ProgressiaLauncher.launch(args, new ClientProxy());
}
}
}

View File

@ -1,5 +1,23 @@
/*
* 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 {
MONO, STEREO MONO, STEREO
} }

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,12 +41,11 @@ 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(
0, 0,
ALC_DEFAULT_DEVICE_SPECIFIER ALC_DEFAULT_DEVICE_SPECIFIER
); );
device = alcOpenDevice(defaultDeviceName); device = alcOpenDevice(defaultDeviceName);
@ -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());
} }
@ -141,4 +147,4 @@ public class AudioManager {
return alGetString(AL11.AL_VERSION); return alGetString(AL11.AL_VERSION);
} }
} }

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(
"Progressia:BlockDestroy", ResourceManager.getResource("assets/sounds/block_destroy_clap.ogg"),
AudioFormat.MONO); "Progressia:BlockDestroy",
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(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) public Music(String id, int timeLength, float pitch, float gain) {
{ super(id, timeLength, new Vec3(), new Vec3(), pitch, gain);
super(id); }
}
public Music(String id, public Music(String id) {
Vec3 position, super(id);
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) @Override
{ protected Speaker initSpeaker() {
Speaker speaker = AudioManager.initMusicSpeaker(this.getId()); return AudioManager.initMusicSpeaker(soundType);
speaker.setGain(gain); }
speaker.setPitch(pitch);
speaker.setPosition(position); @Override
speaker.setVelocity(velocity); public void setPosition(Vec3 position) {
throw new UnsupportedOperationException();
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,38 +29,41 @@ 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(
Resource dataToDecode, Resource dataToDecode,
IntBuffer channelsBuffer, IntBuffer channelsBuffer,
IntBuffer rateBuffer IntBuffer rateBuffer
) { ) {
return stb_vorbis_decode_memory( return stb_vorbis_decode_memory(
dataToDecode.readAsBytes(), dataToDecode.readAsBytes(),
channelsBuffer, channelsBuffer,
rateBuffer rateBuffer
); );
} }
} }

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;
@ -37,7 +56,7 @@ public class Listener {
if (wasInWorld) { if (wasInWorld) {
velocity.set(camera.getLastAnchorPosition()).sub(position).div( velocity.set(camera.getLastAnchorPosition()).sub(position).div(
(float) GraphicsInterface.getFrameLength() (float) GraphicsInterface.getFrameLength()
); );
} else { } else {
// If !wasInWorld, previous position is nonsence. Assume 0. // If !wasInWorld, previous position is nonsence. Assume 0.
@ -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;
@ -5,147 +23,146 @@ import static org.lwjgl.openal.AL11.*;
public class Speaker { public class Speaker {
public enum State { public enum State {
NOT_PLAYING, NOT_PLAYING,
PLAYING, PLAYING,
PLAYING_LOOP PLAYING_LOOP
} }
// Buffers // Buffers
private int audioData; private int audioData;
private int sourceData; private int sourceData;
// Characteristics // Characteristics
private Vec3 position = new Vec3(); private Vec3 position = new Vec3();
private Vec3 velocity = new Vec3(); private Vec3 velocity = new Vec3();
private float pitch = 1.0f; private float pitch = 1.0f;
private float gain = 1.0f; private float gain = 1.0f;
private State state = State.NOT_PLAYING; private State state = State.NOT_PLAYING;
public Speaker() { public Speaker() {
sourceData = alGenSources(); sourceData = alGenSources();
} }
public Speaker(int audioData) { public Speaker(int audioData) {
this(); this();
setAudioData(audioData); setAudioData(audioData);
} }
public Speaker( public Speaker(
int audioData, int audioData,
Vec3 position, Vec3 position,
Vec3 velocity, Vec3 velocity,
float pitch, float pitch,
float gain float gain
) { ) {
setAudioData(audioData); setAudioData(audioData);
setPosition(position); setPosition(position);
setVelocity(velocity); setVelocity(velocity);
setPitch(pitch); setPitch(pitch);
setGain(gain); setGain(gain);
} }
public Speaker( public Speaker(
Vec3 position, Vec3 position,
Vec3 velocity, Vec3 velocity,
float pitch, float pitch,
float gain float gain
) { ) {
setPosition(position); setPosition(position);
setVelocity(velocity); setVelocity(velocity);
setPitch(pitch); setPitch(pitch);
setGain(gain); setGain(gain);
} }
public void play() { public void play() {
alSourcePlay(sourceData); alSourcePlay(sourceData);
state = State.PLAYING; state = State.PLAYING;
} }
public void playLoop() { public void playLoop() {
alSourcei(sourceData, AL_LOOPING, AL_TRUE); alSourcei(sourceData, AL_LOOPING, AL_TRUE);
alSourcePlay(sourceData); alSourcePlay(sourceData);
state = State.PLAYING_LOOP; state = State.PLAYING_LOOP;
} }
public void stop() { public void stop() {
alSourceStop(sourceData); alSourceStop(sourceData);
if (state == State.PLAYING_LOOP) { if (state == State.PLAYING_LOOP) {
alSourcei(sourceData, AL_LOOPING, AL_FALSE); alSourcei(sourceData, AL_LOOPING, AL_FALSE);
} }
state = State.NOT_PLAYING; state = State.NOT_PLAYING;
} }
public void pause() { public void pause() {
alSourcePause(sourceData); alSourcePause(sourceData);
state = State.NOT_PLAYING; state = State.NOT_PLAYING;
} }
public boolean isPlaying() { public boolean isPlaying() {
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; }
} }
}
// GETTERS & SETTERS // GETTERS & SETTERS
public int getAudioData() { public int getAudioData() {
return audioData; return audioData;
} }
public int getSourceData() { public int getSourceData() {
return sourceData; return sourceData;
} }
public void setAudioData(int audioData) { public void setAudioData(int audioData) {
this.audioData = audioData; stop();
alSourcei(this.sourceData, AL_BUFFER, audioData); this.audioData = audioData;
} alSourcei(this.sourceData, AL_BUFFER, audioData);
}
public void setPosition(Vec3 position) { public void setPosition(Vec3 position) {
this.position = position; this.position = position;
alSource3f(sourceData, AL_POSITION, position.x, position.y, position.z); alSource3f(sourceData, AL_POSITION, position.x, position.y, position.z);
} }
public Vec3 getPosition() { public Vec3 getPosition() {
return position; return position;
} }
public void setVelocity(Vec3 velocity) { public void setVelocity(Vec3 velocity) {
alSource3f(sourceData, AL_VELOCITY, velocity.x, velocity.y, velocity.z); alSource3f(sourceData, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
this.velocity = velocity; this.velocity = velocity;
} }
public Vec3 getVelocity() { public Vec3 getVelocity() {
return velocity; return velocity;
} }
public void setPitch(float pitch) { public void setPitch(float pitch) {
alSourcef(sourceData, AL_PITCH, pitch); alSourcef(sourceData, AL_PITCH, pitch);
this.pitch = pitch; this.pitch = pitch;
} }
public float getPitch() { public float getPitch() {
return pitch; return pitch;
} }
public void setGain(float gain) { public void setGain(float gain) {
alSourcef(sourceData, AL_GAIN, gain); alSourcef(sourceData, AL_GAIN, gain);
this.gain = gain; this.gain = gain;
} }
public float getGain() { public float getGain() {
return gain; return gain;
} }
public State getState() public State getState() {
{ return state;
return state; }
}
} }

View File

@ -1,46 +1,64 @@
package ru.windcorp.progressia.client.comms; /*
* Progressia
import java.io.IOException; * Copyright (C) 2020-2021 Wind Corporation and contributors
*
import ru.windcorp.progressia.client.Client; * This program is free software: you can redistribute it and/or modify
import ru.windcorp.progressia.common.comms.CommsListener; * it under the terms of the GNU General Public License as published by
import ru.windcorp.progressia.common.comms.packets.Packet; * the Free Software Foundation, either version 3 of the License, or
import ru.windcorp.progressia.common.util.crash.CrashReports; * (at your option) any later version.
import ru.windcorp.progressia.common.world.PacketSetLocalPlayer; *
import ru.windcorp.progressia.common.world.PacketAffectWorld; * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
// TODO refactor with no mercy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
public class DefaultClientCommsListener implements CommsListener { * GNU General Public License for more details.
*
private final Client client; * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
public DefaultClientCommsListener(Client client) { */
this.client = client;
} package ru.windcorp.progressia.client.comms;
@Override import java.io.IOException;
public void onPacketReceived(Packet packet) {
if (packet instanceof PacketAffectWorld) { import ru.windcorp.progressia.client.Client;
((PacketAffectWorld) packet).apply( import ru.windcorp.progressia.common.comms.CommsListener;
getClient().getWorld().getData() import ru.windcorp.progressia.common.comms.packets.Packet;
); import ru.windcorp.progressia.common.util.crash.CrashReports;
} else if (packet instanceof PacketSetLocalPlayer) { import ru.windcorp.progressia.common.world.PacketSetLocalPlayer;
setLocalPlayer((PacketSetLocalPlayer) packet); import ru.windcorp.progressia.common.world.PacketAffectWorld;
}
} // TODO refactor with no mercy
public class DefaultClientCommsListener implements CommsListener {
private void setLocalPlayer(PacketSetLocalPlayer packet) {
getClient().getLocalPlayer().setEntityId(packet.getEntityId()); private final Client client;
}
public DefaultClientCommsListener(Client client) {
@Override this.client = client;
public void onIOError(IOException reason) { }
throw CrashReports.report(reason, "An IOException has occurred in communications");
// TODO implement @Override
} public void onPacketReceived(Packet packet) {
if (packet instanceof PacketAffectWorld) {
public Client getClient() { ((PacketAffectWorld) packet).apply(
return client; getClient().getWorld().getData()
} );
} else if (packet instanceof PacketSetLocalPlayer) {
} setLocalPlayer((PacketSetLocalPlayer) packet);
}
}
private void setLocalPlayer(PacketSetLocalPlayer packet) {
getClient().getLocalPlayer().setEntityId(packet.getEntityId());
}
@Override
public void onIOError(IOException reason) {
throw CrashReports.report(reason, "An IOException has occurred in communications");
// TODO implement
}
public Client getClient() {
return client;
}
}

View File

@ -1,7 +1,25 @@
package ru.windcorp.progressia.client.comms; /*
* Progressia
import ru.windcorp.progressia.common.comms.CommsChannel; * Copyright (C) 2020-2021 Wind Corporation and contributors
*
public abstract class ServerCommsChannel extends CommsChannel { * 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;
import ru.windcorp.progressia.common.comms.CommsChannel;
public abstract class ServerCommsChannel extends CommsChannel {
}

View File

@ -1,11 +1,29 @@
package ru.windcorp.progressia.client.comms.controls; /*
* Progressia
import ru.windcorp.progressia.common.util.namespaces.Namespaced; * Copyright (C) 2020-2021 Wind Corporation and contributors
*
public abstract class ControlTrigger extends Namespaced { * 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
public ControlTrigger(String id) { * the Free Software Foundation, either version 3 of the License, or
super(id); * (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 ru.windcorp.progressia.common.util.namespaces.Namespaced;
public abstract class ControlTrigger extends Namespaced {
public ControlTrigger(String id) {
super(id);
}
}

View File

@ -1,14 +1,32 @@
package ru.windcorp.progressia.client.comms.controls; /*
* Progressia
import ru.windcorp.progressia.client.graphics.input.InputEvent; * Copyright (C) 2020-2021 Wind Corporation and contributors
import ru.windcorp.progressia.common.comms.controls.PacketControl; *
* This program is free software: you can redistribute it and/or modify
public abstract class ControlTriggerInputBased extends ControlTrigger { * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
public ControlTriggerInputBased(String id) { * (at your option) any later version.
super(id); *
} * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
public abstract PacketControl onInputEvent(InputEvent event); * 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 ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.common.comms.controls.PacketControl;
public abstract class ControlTriggerInputBased extends ControlTrigger {
public ControlTriggerInputBased(String id) {
super(id);
}
public abstract PacketControl onInputEvent(InputEvent event);
}

View File

@ -1,48 +1,67 @@
package ru.windcorp.progressia.client.comms.controls; /*
* Progressia
import java.util.function.BiConsumer; * Copyright (C) 2020-2021 Wind Corporation and contributors
import java.util.function.Predicate; *
* This program is free software: you can redistribute it and/or modify
import ru.windcorp.progressia.client.graphics.input.InputEvent; * it under the terms of the GNU General Public License as published by
import ru.windcorp.progressia.common.comms.controls.ControlData; * the Free Software Foundation, either version 3 of the License, or
import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry; * (at your option) any later version.
import ru.windcorp.progressia.common.comms.controls.PacketControl; *
import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil; * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
public class ControlTriggerLambda extends ControlTriggerInputBased { * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
private final String packetId; *
private final Predicate<InputEvent> predicate; * You should have received a copy of the GNU General Public License
private final BiConsumer<InputEvent, ControlData> dataWriter; * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
public ControlTriggerLambda(
String id, package ru.windcorp.progressia.client.comms.controls;
Predicate<InputEvent> predicate,
BiConsumer<InputEvent, ControlData> dataWriter import java.util.function.BiConsumer;
) { import java.util.function.Predicate;
super(id);
import ru.windcorp.progressia.client.graphics.input.InputEvent;
this.packetId = NamespacedUtil.getId( import ru.windcorp.progressia.common.comms.controls.ControlData;
NamespacedUtil.getNamespace(id), import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry;
"ControlKeyPress" + NamespacedUtil.getName(id) import ru.windcorp.progressia.common.comms.controls.PacketControl;
); import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil;
this.predicate = predicate; public class ControlTriggerLambda extends ControlTriggerInputBased {
this.dataWriter = dataWriter;
} private final String packetId;
private final Predicate<InputEvent> predicate;
@Override private final BiConsumer<InputEvent, ControlData> dataWriter;
public PacketControl onInputEvent(InputEvent event) {
if (!predicate.test(event)) return null; public ControlTriggerLambda(
String id,
PacketControl packet = new PacketControl( Predicate<InputEvent> predicate,
packetId, BiConsumer<InputEvent, ControlData> dataWriter
ControlDataRegistry.getInstance().create(getId()) ) {
); super(id);
dataWriter.accept(event, packet.getControl()); this.packetId = NamespacedUtil.getId(
NamespacedUtil.getNamespace(id),
return packet; "ControlKeyPress" + NamespacedUtil.getName(id)
} );
} this.predicate = predicate;
this.dataWriter = dataWriter;
}
@Override
public PacketControl onInputEvent(InputEvent event) {
if (!predicate.test(event))
return null;
PacketControl packet = new PacketControl(
packetId,
ControlDataRegistry.getInstance().create(getId())
);
dataWriter.accept(event, packet.getControl());
return packet;
}
}

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,14 +1,31 @@
package ru.windcorp.progressia.client.comms.controls; /*
* Progressia
import ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry; * Copyright (C) 2020-2021 Wind Corporation and contributors
*
public class ControlTriggerRegistry extends NamespacedInstanceRegistry<ControlTrigger> { * 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
private static final ControlTriggerRegistry INSTANCE = * the Free Software Foundation, either version 3 of the License, or
new ControlTriggerRegistry(); * (at your option) any later version.
*
public static ControlTriggerRegistry getInstance() { * This program is distributed in the hope that it will be useful,
return INSTANCE; * 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 ru.windcorp.progressia.common.util.namespaces.NamespacedInstanceRegistry;
public class ControlTriggerRegistry extends NamespacedInstanceRegistry<ControlTrigger> {
private static final ControlTriggerRegistry INSTANCE = new ControlTriggerRegistry();
public static ControlTriggerRegistry getInstance() {
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;
@ -8,145 +26,239 @@ import ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.common.comms.controls.ControlData; import ru.windcorp.progressia.common.comms.controls.ControlData;
public class ControlTriggers { public class ControlTriggers {
public static ControlTriggerInputBased of( public static ControlTriggerInputBased of(
String id, String id,
BiConsumer<InputEvent, ControlData> dataWriter, BiConsumer<InputEvent, ControlData> dataWriter,
Predicate<InputEvent> predicate Predicate<InputEvent> predicate
) { ) {
return new ControlTriggerLambda(id, predicate, dataWriter); return new ControlTriggerLambda(id, predicate, dataWriter);
} }
public static ControlTriggerInputBased of( public static ControlTriggerInputBased of(
String id, String id,
Consumer<ControlData> dataWriter, Consumer<ControlData> dataWriter,
Predicate<InputEvent> predicate Predicate<InputEvent> predicate
) { ) {
return of( return of(
id, id,
(input, control) -> dataWriter.accept(control), (input, control) -> dataWriter.accept(control),
predicate predicate
);
}
public static ControlTriggerInputBased of(
String id,
Predicate<InputEvent> predicate
) {
return of(
id,
(input, control) -> {},
predicate
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Class<I> inputType,
BiConsumer<I, ControlData> dataWriter,
Predicate<I>... predicates
) {
return of(
id,
createCheckedDataWriter(inputType, dataWriter),
createCheckedCompoundPredicate(inputType, predicates)
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Class<I> inputType,
Consumer<ControlData> dataWriter,
Predicate<I>... predicates
) {
return of(
id,
inputType,
(input, control) -> dataWriter.accept(control),
predicates
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Class<I> inputType,
Predicate<I>... predicates
) {
return of(
id,
(input, control) -> {},
createCheckedCompoundPredicate(inputType, predicates)
);
}
@SafeVarargs
public static ControlTriggerInputBased of(
String id,
BiConsumer<InputEvent, ControlData> dataWriter,
Predicate<InputEvent>... predicates
) {
return of(
id,
InputEvent.class,
dataWriter,
predicates
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Consumer<ControlData> dataWriter,
Predicate<InputEvent>... predicates
) {
return of(
id,
(input, control) -> dataWriter.accept(control),
predicates
);
}
@SafeVarargs
public static ControlTriggerInputBased of(
String id,
Predicate<InputEvent>... predicates
) {
return of(
id,
InputEvent.class,
(input, control) -> {},
predicates
); );
} }
private static public static ControlTriggerInputBased of(
<I extends InputEvent> String id,
BiConsumer<InputEvent, ControlData> Predicate<InputEvent> predicate
createCheckedDataWriter( ) {
Class<I> inputType, return of(
BiConsumer<I, ControlData> dataWriter id,
(input, control) -> {
},
predicate
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Class<I> inputType,
BiConsumer<I, ControlData> dataWriter,
Predicate<I>... predicates
) {
return of(
id,
createCheckedDataWriter(inputType, dataWriter),
createCheckedCompoundPredicate(inputType, predicates)
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Class<I> inputType,
Consumer<ControlData> dataWriter,
Predicate<I>... predicates
) {
return of(
id,
inputType,
(input, control) -> dataWriter.accept(control),
predicates
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Class<I> inputType,
Predicate<I>... predicates
) {
return of(
id,
(input, control) -> {
},
createCheckedCompoundPredicate(inputType, predicates)
);
}
@SafeVarargs
public static ControlTriggerInputBased of(
String id,
BiConsumer<InputEvent, ControlData> dataWriter,
Predicate<InputEvent>... predicates
) {
return of(
id,
InputEvent.class,
dataWriter,
predicates
);
}
@SafeVarargs
public static <I extends InputEvent> ControlTriggerInputBased of(
String id,
Consumer<ControlData> dataWriter,
Predicate<InputEvent>... predicates
) {
return of(
id,
(input, control) -> dataWriter.accept(control),
predicates
);
}
@SafeVarargs
public static ControlTriggerInputBased of(
String id,
Predicate<InputEvent>... predicates
) {
return of(
id,
InputEvent.class,
(input, control) -> {
},
predicates
);
}
//
//
///
///
//
//
//
//
//
//
//
//
//
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,
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( ) {
Class<I> inputType, return inputEvent -> action.accept(inputType.cast(inputEvent));
Predicate<I>[] predicates }
private static <I extends InputEvent> Predicate<InputEvent> createCheckedCompoundPredicate(
Class<I> inputType,
Predicate<I>[] predicates
) { ) {
return new CompoundCastPredicate<>(inputType, predicates); return new CompoundCastPredicate<>(inputType, predicates);
} }
private static class CompoundCastPredicate<I extends InputEvent> implements Predicate<InputEvent> { private static class CompoundCastPredicate<I extends InputEvent> implements Predicate<InputEvent> {
private final Class<I> inputType; private final Class<I> inputType;
private final Predicate<I>[] predicates; private final Predicate<I>[] predicates;
public CompoundCastPredicate(Class<I> inputType, Predicate<I>[] predicates) { public CompoundCastPredicate(Class<I> inputType, Predicate<I>[] predicates) {
this.inputType = inputType; this.inputType = inputType;
this.predicates = predicates; this.predicates = predicates;
@ -157,20 +269,21 @@ public class ControlTriggers {
if (!inputType.isInstance(inputEvent)) { if (!inputType.isInstance(inputEvent)) {
return false; return false;
} }
I castEvent = inputType.cast(inputEvent); I castEvent = inputType.cast(inputEvent);
for (Predicate<I> predicate : predicates) { for (Predicate<I> predicate : predicates) {
if (!predicate.test(castEvent)) { if (!predicate.test(castEvent)) {
return false; return false;
} }
} }
return true; return true;
} }
} }
private ControlTriggers() {} private ControlTriggers() {
}
} }

View File

@ -1,33 +1,51 @@
package ru.windcorp.progressia.client.comms.controls; /*
* Progressia
import ru.windcorp.progressia.client.Client; * Copyright (C) 2020-2021 Wind Corporation and contributors
import ru.windcorp.progressia.client.graphics.input.bus.Input; *
import ru.windcorp.progressia.common.comms.packets.Packet; * 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
public class InputBasedControls { * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
private final Client client; *
* This program is distributed in the hope that it will be useful,
private final ControlTriggerInputBased[] controls; * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
public InputBasedControls(Client client) { * GNU General Public License for more details.
this.client = client; *
* You should have received a copy of the GNU General Public License
this.controls = ControlTriggerRegistry.getInstance().values().stream() * along with this program. If not, see <https://www.gnu.org/licenses/>.
.filter(ControlTriggerInputBased.class::isInstance) */
.toArray(ControlTriggerInputBased[]::new);
} package ru.windcorp.progressia.client.comms.controls;
public void handleInput(Input input) { import ru.windcorp.progressia.client.Client;
for (ControlTriggerInputBased c : controls) { import ru.windcorp.progressia.client.graphics.input.bus.Input;
Packet packet = c.onInputEvent(input.getEvent()); import ru.windcorp.progressia.common.comms.packets.Packet;
if (packet != null) { public class InputBasedControls {
input.consume();
client.getComms().sendPacket(packet); private final Client client;
break;
} private final ControlTriggerInputBased[] controls;
}
} public InputBasedControls(Client client) {
this.client = client;
}
this.controls = ControlTriggerRegistry.getInstance().values().stream()
.filter(ControlTriggerInputBased.class::isInstance)
.toArray(ControlTriggerInputBased[]::new);
}
public void handleInput(Input input) {
for (ControlTriggerInputBased c : controls) {
Packet packet = c.onInputEvent(input.getEvent());
if (packet != null) {
input.consume();
client.getComms().sendPacket(packet);
break;
}
}
}
}

View File

@ -1,41 +1,59 @@
package ru.windcorp.progressia.client.comms.localhost; /*
* Progressia
import java.io.IOException; * Copyright (C) 2020-2021 Wind Corporation and contributors
*
import ru.windcorp.progressia.common.comms.packets.Packet; * This program is free software: you can redistribute it and/or modify
import ru.windcorp.progressia.server.comms.ClientPlayer; * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
public class LocalClient extends ClientPlayer { * (at your option) any later version.
*
private final LocalServerCommsChannel serverComms; * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
private final String login; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
public LocalClient(int id, String login, LocalServerCommsChannel serverComms) { *
super(id); * You should have received a copy of the GNU General Public License
setState(State.CONNECTED); * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
this.serverComms = serverComms;
this.login = login; package ru.windcorp.progressia.client.comms.localhost;
}
import java.io.IOException;
@Override
public String getLogin() { import ru.windcorp.progressia.common.comms.packets.Packet;
return this.login; import ru.windcorp.progressia.server.comms.ClientPlayer;
}
public class LocalClient extends ClientPlayer {
@Override
protected void doSendPacket(Packet packet) throws IOException { private final LocalServerCommsChannel serverComms;
this.serverComms.relayPacketToClient(packet);
} private final String login;
public void relayPacketToServer(Packet packet) { public LocalClient(int id, String login, LocalServerCommsChannel serverComms) {
onPacketReceived(packet); super(id);
} setState(State.CONNECTED);
@Override this.serverComms = serverComms;
public void disconnect() { this.login = login;
// Do nothing }
}
@Override
} public String getLogin() {
return this.login;
}
@Override
protected void doSendPacket(Packet packet) throws IOException {
this.serverComms.relayPacketToClient(packet);
}
public void relayPacketToServer(Packet packet) {
onPacketReceived(packet);
}
@Override
public void disconnect() {
// Do nothing
}
}

View File

@ -1,42 +1,60 @@
package ru.windcorp.progressia.client.comms.localhost; /*
* Progressia
import ru.windcorp.progressia.client.comms.ServerCommsChannel; * Copyright (C) 2020-2021 Wind Corporation and contributors
import ru.windcorp.progressia.common.comms.packets.Packet; *
import ru.windcorp.progressia.server.Server; * 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
public class LocalServerCommsChannel extends ServerCommsChannel { * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
private LocalClient localClient; *
private final Server server; * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
public LocalServerCommsChannel(Server server) { * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
this.server = server; * GNU General Public License for more details.
} *
* You should have received a copy of the GNU General Public License
public void connect(String login) { * along with this program. If not, see <https://www.gnu.org/licenses/>.
setState(State.CONNECTED); */
this.localClient = new LocalClient( package ru.windcorp.progressia.client.comms.localhost;
server.getClientManager().grabClientId(),
login, import ru.windcorp.progressia.client.comms.ServerCommsChannel;
this import ru.windcorp.progressia.common.comms.packets.Packet;
); import ru.windcorp.progressia.server.Server;
server.getClientManager().addClient(localClient); public class LocalServerCommsChannel extends ServerCommsChannel {
}
private LocalClient localClient;
@Override private final Server server;
protected void doSendPacket(Packet packet) {
localClient.relayPacketToServer(packet); public LocalServerCommsChannel(Server server) {
} this.server = server;
}
public void relayPacketToClient(Packet packet) {
onPacketReceived(packet); public void connect(String login) {
} setState(State.CONNECTED);
@Override this.localClient = new LocalClient(
public void disconnect() { server.getClientManager().grabClientId(),
// Do nothing login,
} this
);
}
server.getClientManager().addClient(localClient);
}
@Override
protected void doSendPacket(Packet packet) {
localClient.relayPacketToServer(packet);
}
public void relayPacketToClient(Packet packet) {
onPacketReceived(packet);
}
@Override
public void disconnect() {
// Do nothing
}
}

View File

@ -1,61 +1,62 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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
WHITE = toVector(0xFFFFFFFF), public static final Vec4 WHITE = toVector(0xFFFFFFFF),
BLACK = toVector(0xFF000000), BLACK = toVector(0xFF000000),
GRAY_4 = toVector(0xFF444444), GRAY_4 = toVector(0xFF444444),
GRAY = toVector(0xFF888888), GRAY = toVector(0xFF888888),
GRAY_A = toVector(0xFFAAAAAA), GRAY_A = toVector(0xFFAAAAAA),
DEBUG_RED = toVector(0xFFFF0000), DEBUG_RED = toVector(0xFFFF0000),
DEBUG_GREEN = toVector(0xFF00FF00), DEBUG_GREEN = toVector(0xFF00FF00),
DEBUG_BLUE = toVector(0xFF0000FF), DEBUG_BLUE = toVector(0xFF0000FF),
DEBUG_CYAN = toVector(0xFF00FFFF), DEBUG_CYAN = toVector(0xFF00FFFF),
DEBUG_MAGENTA = toVector(0xFFFF00FF), DEBUG_MAGENTA = toVector(0xFFFF00FF),
DEBUG_YELLOW = toVector(0xFFFFFF00); DEBUG_YELLOW = toVector(0xFFFFFF00);
public static Vec4 toVector(int argb) { public static Vec4 toVector(int argb) {
return toVector(argb, new Vec4()); return toVector(argb, new Vec4());
} }
public static Vec4 multiplyRGB(Vec4 color, float multiplier) { public static Vec4 multiplyRGB(Vec4 color, float multiplier) {
return color.mul(multiplier, multiplier, multiplier, 1); return color.mul(multiplier, multiplier, multiplier, 1);
} }
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)
return color.mul(multiplier, multiplier, multiplier, 1, output); output = new Vec4();
} return color.mul(multiplier, multiplier, multiplier, 1, output);
}
public static Vec4 toVector(int argb, Vec4 output) {
output.w = ((argb & 0xFF000000) >>> 24) / 256f; // Alpha public static Vec4 toVector(int argb, Vec4 output) {
output.x = ((argb & 0x00FF0000) >>> 16) / 256f; // Red output.w = ((argb & 0xFF000000) >>> 24) / (float) 0xFF; // Alpha
output.y = ((argb & 0x0000FF00) >>> 8) / 256f; // Green output.x = ((argb & 0x00FF0000) >>> 16) / (float) 0xFF; // Red
output.z = ((argb & 0x000000FF) ) / 256f; // Blue output.y = ((argb & 0x0000FF00) >>> 8) / (float) 0xFF; // Green
output.z = ((argb & 0x000000FF)) / (float) 0xFF; // Blue
return output;
} return output;
}
}
}

View File

@ -1,108 +1,133 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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.List; import java.util.ArrayList;
import java.util.Collections;
import com.google.common.eventbus.Subscribe; import java.util.List;
import ru.windcorp.progressia.client.graphics.input.CursorEvent; import com.google.common.eventbus.Subscribe;
import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent;
import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.CursorEvent;
import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent;
import ru.windcorp.progressia.client.graphics.input.WheelEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent;
import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.input.KeyEvent;
import ru.windcorp.progressia.client.graphics.input.WheelEvent;
public class GUI { import ru.windcorp.progressia.client.graphics.input.bus.Input;
private static final List<Layer> LAYERS = new ArrayList<>(); public class GUI {
private static class ModifiableInput extends Input { private static final List<Layer> LAYERS = Collections.synchronizedList(new ArrayList<>());
@Override private static final List<Layer> UNMODIFIABLE_LAYERS = Collections.unmodifiableList(LAYERS);
public void initialize(InputEvent event, Target target) {
super.initialize(event, target); @FunctionalInterface
} private interface LayerStackModification {
} void affect(List<Layer> layers);
}
private static final ModifiableInput THE_INPUT = new ModifiableInput();
private static final List<LayerStackModification> MODIFICATION_QUEUE = Collections
private GUI() {} .synchronizedList(new ArrayList<>());
public synchronized static void addBottomLayer(Layer layer) { private static class ModifiableInput extends Input {
LAYERS.add(layer); @Override
} public void initialize(InputEvent event, Target target) {
super.initialize(event, target);
public synchronized static void addTopLayer(Layer layer) { }
LAYERS.add(0, layer); }
}
private static final ModifiableInput THE_INPUT = new ModifiableInput();
public synchronized static void removeLayer(Layer layer) {
LAYERS.remove(layer); private GUI() {
} }
public synchronized static void render() { public static void addBottomLayer(Layer layer) {
for (int i = LAYERS.size() - 1; i >= 0; --i) { modify(layers -> layers.add(layer));
LAYERS.get(i).render(); }
}
} public static void addTopLayer(Layer layer) {
modify(layers -> layers.add(0, layer));
public static void invalidateEverything() { }
LAYERS.forEach(Layer::invalidate);
} public static void removeLayer(Layer layer) {
modify(layers -> layers.remove(layer));
private static void dispatchInputEvent(InputEvent event) { }
Input.Target target;
private static void modify(LayerStackModification mod) {
if (event instanceof KeyEvent) { MODIFICATION_QUEUE.add(mod);
if (((KeyEvent) event).isMouse()) { }
target = Input.Target.HOVERED;
} else { public static List<Layer> getLayers() {
target = Input.Target.FOCUSED; return UNMODIFIABLE_LAYERS;
} }
} else if (event instanceof CursorEvent) {
target = Input.Target.HOVERED; public static void render() {
} else if (event instanceof WheelEvent) { synchronized (LAYERS) {
target = Input.Target.HOVERED; MODIFICATION_QUEUE.forEach(action -> action.affect(LAYERS));
} else if (event instanceof FrameResizeEvent) { MODIFICATION_QUEUE.clear();
return;
} else { for (int i = LAYERS.size() - 1; i >= 0; --i) {
target = Input.Target.ALL; LAYERS.get(i).render();
} }
}
THE_INPUT.initialize(event, target); }
LAYERS.forEach(l -> l.handleInput(THE_INPUT));
} public static void invalidateEverything() {
LAYERS.forEach(Layer::invalidate);
public static Object getEventSubscriber() { }
return new Object() {
private static void dispatchInputEvent(InputEvent event) {
@Subscribe Input.Target target;
public void onFrameResized(FrameResizeEvent event) {
GUI.invalidateEverything(); if (event instanceof KeyEvent) {
} if (((KeyEvent) event).isMouse()) {
target = Input.Target.HOVERED;
@Subscribe } else {
public void onInput(InputEvent event) { target = Input.Target.FOCUSED;
dispatchInputEvent(event); }
} } else if (event instanceof CursorEvent) {
target = Input.Target.HOVERED;
}; } else if (event instanceof WheelEvent) {
} target = Input.Target.HOVERED;
} else if (event instanceof FrameResizeEvent) {
} return;
} else {
target = Input.Target.ALL;
}
THE_INPUT.initialize(event, target);
LAYERS.forEach(l -> l.handleInput(THE_INPUT));
}
public static Object getEventSubscriber() {
return new Object() {
@Subscribe
public void onFrameResized(FrameResizeEvent event) {
GUI.invalidateEverything();
}
@Subscribe
public void onInput(InputEvent event) {
dispatchInputEvent(event);
}
};
}
}

View File

@ -1,81 +1,82 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
import ru.windcorp.progressia.client.graphics.input.bus.Input;
public abstract class Layer {
public abstract class Layer {
private final String name;
private final String name;
private boolean hasInitialized = false;
private boolean hasInitialized = false;
private final AtomicBoolean isValid = new AtomicBoolean(false);
private final AtomicBoolean isValid = new AtomicBoolean(false);
public Layer(String name) {
this.name = name; public Layer(String name) {
} this.name = name;
}
@Override
public String toString() { @Override
return "Layer " + name; public String toString() {
} return "Layer " + name;
}
void render() {
GraphicsInterface.startNextLayer(); void render() {
GraphicsInterface.startNextLayer();
validate();
validate();
if (!hasInitialized) {
initialize(); if (!hasInitialized) {
hasInitialized = true; initialize();
} hasInitialized = true;
}
doRender();
} doRender();
}
void validate() {
if (isValid.compareAndSet(false, true)) { void validate() {
doValidate(); if (isValid.compareAndSet(false, true)) {
} doValidate();
} }
}
public void invalidate() {
isValid.set(false); public void invalidate() {
} isValid.set(false);
}
protected abstract void initialize();
protected abstract void initialize();
protected abstract void doValidate();
protected abstract void doValidate();
protected abstract void doRender();
protected abstract void doRender();
protected abstract void handleInput(Input input);
protected abstract void handleInput(Input input);
protected int getWidth() {
return GraphicsInterface.getFrameWidth(); protected int getWidth() {
} return GraphicsInterface.getFrameWidth();
}
protected int getHeight() {
return GraphicsInterface.getFrameHeight(); protected int getHeight() {
} return GraphicsInterface.getFrameHeight();
}
}
}

View File

@ -1,27 +1,46 @@
/*
* 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;
import java.util.Deque; import java.util.Deque;
public class FaceCulling { public class FaceCulling {
private static final Deque<Boolean> STACK = new ArrayDeque<>(); private static final Deque<Boolean> STACK = new ArrayDeque<>();
public static void push(boolean useFaceCulling) { public static void push(boolean useFaceCulling) {
GraphicsBackend.setFaceCulling(useFaceCulling); GraphicsBackend.setFaceCulling(useFaceCulling);
STACK.push(Boolean.valueOf(useFaceCulling)); STACK.push(Boolean.valueOf(useFaceCulling));
} }
public static void pop() { public static void pop() {
STACK.pop(); STACK.pop();
if (STACK.isEmpty()) { if (STACK.isEmpty()) {
GraphicsBackend.setFaceCulling(false); GraphicsBackend.setFaceCulling(false);
} else { } else {
GraphicsBackend.setFaceCulling(STACK.getFirst()); GraphicsBackend.setFaceCulling(STACK.getFirst());
} }
} }
private FaceCulling() {} private FaceCulling() {
}
} }

View File

@ -1,127 +1,195 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 {
private static RenderThread renderThread;
private static RenderThread renderThread;
private static long windowHandle;
private static long windowHandle;
private static final Vec2i FRAME_SIZE = new Vec2i();
private static final Vec2i FRAME_SIZE = new Vec2i();
private static double frameLength = 1.0 / 60; // TODO do something about it
private static long framesRendered = 0; private static double frameLength = 1.0 / 60; // TODO do something about it
private static double frameStart = Double.NaN; private static long framesRendered = 0;
private static double frameStart = Double.NaN;
private static boolean faceCullingEnabled = false;
private static boolean faceCullingEnabled = false;
private GraphicsBackend() {}
private static boolean isFullscreen = false;
public static void initialize() { private static boolean vSyncEnabled = false;
startRenderThread(); private static boolean isGLFWInitialized = false;
} private static boolean isOpenGLInitialized = false;
private static void startRenderThread() { private GraphicsBackend() {
renderThread = new RenderThread(); }
renderThread.start();
} public static boolean isGLFWInitialized() {
return isGLFWInitialized;
public static Thread getRenderThread() { }
return renderThread;
} static void setGLFWInitialized(boolean isGLFWInitialized) {
GraphicsBackend.isGLFWInitialized = isGLFWInitialized;
static void setWindowHandle(long windowHandle) { }
GraphicsBackend.windowHandle = windowHandle;
} public static boolean isOpenGLInitialized() {
return isOpenGLInitialized;
public static long getWindowHandle() { }
return windowHandle;
} static void setOpenGLInitialized(boolean isOpenGLInitialized) {
GraphicsBackend.isOpenGLInitialized = isOpenGLInitialized;
public static int getFrameWidth() { }
return FRAME_SIZE.x;
} public static void initialize() {
startRenderThread();
public static int getFrameHeight() { }
return FRAME_SIZE.y;
} private static void startRenderThread() {
renderThread = new RenderThread();
public static Vec2i getFrameSize() { renderThread.start();
return FRAME_SIZE; }
}
public static Thread getRenderThread() {
static void onFrameResized(long window, int newWidth, int newHeight) { return renderThread;
if (window != windowHandle) return; }
InputHandler.handleFrameResize(newWidth, newHeight); static void setWindowHandle(long windowHandle) {
FRAME_SIZE.set(newWidth, newHeight); GraphicsBackend.windowHandle = windowHandle;
}
glViewport(0, 0, newWidth, newHeight);
} public static long getWindowHandle() {
return windowHandle;
static void startFrame() { }
double now = glfwGetTime();
public static int getFrameWidth() {
if (Double.isNaN(frameStart)) { return FRAME_SIZE.x;
frameStart = now; }
} else {
frameLength = now - frameStart; public static int getFrameHeight() {
frameStart = now; return FRAME_SIZE.y;
} }
}
public static Vec2i getFrameSize() {
static void endFrame() { return FRAME_SIZE;
framesRendered++; }
}
static void onFrameResized(long window, int newWidth, int newHeight) {
public static double getFrameStart() { if (window != windowHandle)
return frameStart; return;
}
InputHandler.handleFrameResize(newWidth, newHeight);
public static double getFrameLength() { FRAME_SIZE.set(newWidth, newHeight);
return frameLength;
} glViewport(0, 0, newWidth, newHeight);
}
public static long getFramesRendered() {
return framesRendered; static void startFrame() {
} double now = glfwGetTime();
public static void startNextLayer() { if (Double.isNaN(frameStart)) {
glClear(GL_DEPTH_BUFFER_BIT); frameStart = now;
} } else {
frameLength = now - frameStart;
public static void setFaceCulling(boolean useFaceCulling) { frameStart = now;
if (useFaceCulling == faceCullingEnabled) return; }
}
if (useFaceCulling) {
glEnable(GL_CULL_FACE); static void endFrame() {
} else { framesRendered++;
glDisable(GL_CULL_FACE); }
}
public static double getFrameStart() {
faceCullingEnabled = useFaceCulling; return frameStart;
} }
} public static double getFrameLength() {
return frameLength;
}
public static long getFramesRendered() {
return framesRendered;
}
public static void startNextLayer() {
glClear(GL_DEPTH_BUFFER_BIT);
}
public static void setFaceCulling(boolean useFaceCulling) {
if (useFaceCulling == faceCullingEnabled)
return;
if (useFaceCulling) {
glEnable(GL_CULL_FACE);
} else {
glDisable(GL_CULL_FACE);
}
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,74 +1,85 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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() { }
return GraphicsBackend.getRenderThread();
} public static Thread getRenderThread() {
return GraphicsBackend.getRenderThread();
public static boolean isRenderThread() { }
return Thread.currentThread() == getRenderThread();
} public static boolean isRenderThread() {
return Thread.currentThread() == getRenderThread();
public static int getFrameWidth() { }
return GraphicsBackend.getFrameWidth();
} public static int getFrameWidth() {
return GraphicsBackend.getFrameWidth();
public static int getFrameHeight() { }
return GraphicsBackend.getFrameHeight();
} public static int getFrameHeight() {
return GraphicsBackend.getFrameHeight();
public static Vec2i getFrameSize() { }
return GraphicsBackend.getFrameSize();
} public static Vec2i getFrameSize() {
return GraphicsBackend.getFrameSize();
public static float getAspectRatio() { }
return ((float) getFrameWidth()) / getFrameHeight();
} public static float getAspectRatio() {
return ((float) getFrameWidth()) / getFrameHeight();
public static double getTime() { }
return GraphicsBackend.getFrameStart();
} public static double getTime() {
return GraphicsBackend.getFrameStart();
public static double getFrameLength() { }
return GraphicsBackend.getFrameLength();
} public static double getFrameLength() {
return GraphicsBackend.getFrameLength();
public static double getFPS() { }
return 1 / GraphicsBackend.getFrameLength();
} public static double getFPS() {
return 1 / GraphicsBackend.getFrameLength();
public static long getFramesRendered() { }
return GraphicsBackend.getFramesRendered();
} public static long getFramesRendered() {
return GraphicsBackend.getFramesRendered();
public static void subscribeToInputEvents(Object listener) { }
InputHandler.register(listener);
} public static void subscribeToInputEvents(Object listener) {
InputHandler.register(listener);
public static void startNextLayer() { }
GraphicsBackend.startNextLayer();
} public static void startNextLayer() {
GraphicsBackend.startNextLayer();
} }
public static void makeFullscreen(boolean state) {
if (state) {
GraphicsBackend.setFullscreen();
} else {
GraphicsBackend.setWindowed();
}
GraphicsBackend.setVSyncEnabled(GraphicsBackend.isVSyncEnabled());
}
}

View File

@ -1,182 +1,183 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.EventBus;
import ru.windcorp.progressia.client.graphics.input.*;
import ru.windcorp.progressia.common.util.crash.ReportingEventBus; import ru.windcorp.progressia.client.graphics.input.*;
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
public class InputHandler {
public class InputHandler {
private static final EventBus INPUT_EVENT_BUS = ReportingEventBus.create("Input");
private static final EventBus INPUT_EVENT_BUS = ReportingEventBus.create("Input");
// KeyEvent
// KeyEvent
private static class ModifiableKeyEvent extends KeyEvent {
private static class ModifiableKeyEvent extends KeyEvent {
protected ModifiableKeyEvent() {
super(0, 0, 0, 0, Double.NaN); protected ModifiableKeyEvent() {
} super(0, 0, 0, 0, Double.NaN);
}
public void initialize(int key, int scancode, int action, int mods) {
this.setTime(GraphicsInterface.getTime()); public void initialize(int key, int scancode, int action, int mods) {
this.key = key; this.setTime(GraphicsInterface.getTime());
this.scancode = scancode; this.key = key;
this.action = action; this.scancode = scancode;
this.mods = mods; this.action = action;
} this.mods = mods;
}
}
}
private static final ModifiableKeyEvent THE_KEY_EVENT =
new ModifiableKeyEvent(); private static final ModifiableKeyEvent THE_KEY_EVENT = new ModifiableKeyEvent();
static void handleKeyInput( static void handleKeyInput(
long window, long window,
int key, int key,
int scancode, int scancode,
int action, int action,
int mods int mods
) { ) {
if (GraphicsBackend.getWindowHandle() != window) return; if (GraphicsBackend.getWindowHandle() != window)
THE_KEY_EVENT.initialize(key, scancode, action, mods); return;
dispatch(THE_KEY_EVENT); THE_KEY_EVENT.initialize(key, scancode, action, mods);
dispatch(THE_KEY_EVENT);
switch (action) {
case GLFW.GLFW_PRESS: switch (action) {
InputTracker.setKeyState(key, true); case GLFW.GLFW_PRESS:
break; InputTracker.setKeyState(key, true);
case GLFW.GLFW_RELEASE: break;
InputTracker.setKeyState(key, false); case GLFW.GLFW_RELEASE:
break; InputTracker.setKeyState(key, false);
} break;
} }
}
static void handleMouseButtonInput(
long window, static void handleMouseButtonInput(
int key, long window,
int action, int key,
int mods int action,
) { int mods
handleKeyInput(window, key, Integer.MAX_VALUE - key, action, mods); ) {
} handleKeyInput(window, key, Integer.MAX_VALUE - key, action, mods);
}
// CursorMoveEvent
// CursorMoveEvent
private static class ModifiableCursorMoveEvent extends CursorMoveEvent {
private static class ModifiableCursorMoveEvent extends CursorMoveEvent {
protected ModifiableCursorMoveEvent() {
super(0, 0, Double.NaN); protected ModifiableCursorMoveEvent() {
} super(0, 0, Double.NaN);
}
public void initialize(double x, double y) {
this.setTime(GraphicsInterface.getTime()); public void initialize(double x, double y) {
getNewPosition().set(x, y); this.setTime(GraphicsInterface.getTime());
} getNewPosition().set(x, y);
}
}
}
private static final ModifiableCursorMoveEvent THE_CURSOR_MOVE_EVENT =
new ModifiableCursorMoveEvent(); private static final ModifiableCursorMoveEvent THE_CURSOR_MOVE_EVENT = 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; ) {
y = GraphicsInterface.getFrameHeight() - y; // Flip y axis if (GraphicsBackend.getWindowHandle() != window)
return;
InputTracker.initializeCursorPosition(x, y); y = GraphicsInterface.getFrameHeight() - y; // Flip y axis
THE_CURSOR_MOVE_EVENT.initialize(x, y); InputTracker.initializeCursorPosition(x, y);
dispatch(THE_CURSOR_MOVE_EVENT);
THE_CURSOR_MOVE_EVENT.initialize(x, y);
InputTracker.getCursorPosition().set(x, y); dispatch(THE_CURSOR_MOVE_EVENT);
}
InputTracker.getCursorPosition().set(x, y);
// ScrollEvent }
private static class ModifiableWheelScrollEvent extends WheelScrollEvent { // ScrollEvent
public ModifiableWheelScrollEvent() { private static class ModifiableWheelScrollEvent extends WheelScrollEvent {
super(0, 0, Double.NaN);
} public ModifiableWheelScrollEvent() {
super(0, 0, Double.NaN);
public void initialize(double xOffset, double yOffset) { }
this.setTime(GraphicsInterface.getTime());
this.getOffset().set(xOffset, yOffset); public void initialize(double xOffset, double yOffset) {
} this.setTime(GraphicsInterface.getTime());
this.getOffset().set(xOffset, yOffset);
} }
private static final ModifiableWheelScrollEvent THE_WHEEL_SCROLL_EVENT = }
new ModifiableWheelScrollEvent();
private static final ModifiableWheelScrollEvent THE_WHEEL_SCROLL_EVENT = new ModifiableWheelScrollEvent();
static void handleWheelScroll(
long window, static void handleWheelScroll(
double xoffset, long window,
double yoffset double xoffset,
) { double yoffset
if (GraphicsBackend.getWindowHandle() != window) return; ) {
THE_WHEEL_SCROLL_EVENT.initialize(xoffset, yoffset); if (GraphicsBackend.getWindowHandle() != window)
dispatch(THE_WHEEL_SCROLL_EVENT); return;
} THE_WHEEL_SCROLL_EVENT.initialize(xoffset, yoffset);
dispatch(THE_WHEEL_SCROLL_EVENT);
// FrameResizeEvent }
private static class ModifiableFrameResizeEvent extends FrameResizeEvent { // FrameResizeEvent
public ModifiableFrameResizeEvent() { private static class ModifiableFrameResizeEvent extends FrameResizeEvent {
super(0, 0, Double.NaN);
} public ModifiableFrameResizeEvent() {
super(0, 0, Double.NaN);
public void initialize(int width, int height) { }
this.setTime(GraphicsInterface.getTime());
this.getNewSize().set(width, height); public void initialize(int width, int height) {
} this.setTime(GraphicsInterface.getTime());
this.getNewSize().set(width, height);
} }
private static final ModifiableFrameResizeEvent THE_FRAME_RESIZE_EVENT = }
new ModifiableFrameResizeEvent();
private static final ModifiableFrameResizeEvent THE_FRAME_RESIZE_EVENT = 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
static void handleFrameResize( */
int width, static void handleFrameResize(
int height int width,
) { int height
THE_FRAME_RESIZE_EVENT.initialize(width, height); ) {
dispatch(THE_FRAME_RESIZE_EVENT); THE_FRAME_RESIZE_EVENT.initialize(width, height);
} dispatch(THE_FRAME_RESIZE_EVENT);
}
// Misc
// Misc
private static void dispatch(InputEvent event) {
INPUT_EVENT_BUS.post(event); private static void dispatch(InputEvent event) {
} INPUT_EVENT_BUS.post(event);
}
public static void register(Object listener) {
INPUT_EVENT_BUS.register(listener); public static void register(Object listener) {
} INPUT_EVENT_BUS.register(listener);
}
}
}

View File

@ -1,72 +1,75 @@
/******************************************************************************* /*
* 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
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 * 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 gnu.trove.set.TIntSet; import glm.vec._2.d.Vec2d;
import gnu.trove.set.hash.TIntHashSet; import gnu.trove.set.TIntSet;
import gnu.trove.set.hash.TIntHashSet;
public class InputTracker {
public class InputTracker {
private static final Vec2d CURSOR_POSITION = new Vec2d(
Double.NaN, Double.NaN private static final Vec2d CURSOR_POSITION = new Vec2d(
); Double.NaN,
Double.NaN
private static final TIntSet PRESSED_KEYS = new TIntHashSet(256); );
private InputTracker() {} private static final TIntSet PRESSED_KEYS = new TIntHashSet(256);
public static double getCursorX() { private InputTracker() {
return CURSOR_POSITION.x; }
}
public static double getCursorX() {
public static double getCursorY() { return CURSOR_POSITION.x;
return CURSOR_POSITION.y; }
}
public static double getCursorY() {
public static Vec2d getCursorPosition() { return CURSOR_POSITION.y;
return CURSOR_POSITION; }
}
public static Vec2d getCursorPosition() {
static void initializeCursorPosition(double x, double y) { return CURSOR_POSITION;
if (Double.isNaN(CURSOR_POSITION.x)) { }
CURSOR_POSITION.set(x, y);
} static void initializeCursorPosition(double x, double y) {
} if (Double.isNaN(CURSOR_POSITION.x)) {
CURSOR_POSITION.set(x, y);
public static boolean isKeyPressed(int glfwCode) { }
return PRESSED_KEYS.contains(glfwCode); }
}
public static boolean isKeyPressed(int glfwCode) {
static void setKeyState(int glfwCode, boolean isPressed) { return PRESSED_KEYS.contains(glfwCode);
if (isPressed) { }
PRESSED_KEYS.add(glfwCode);
} else { static void setKeyState(int glfwCode, boolean isPressed) {
PRESSED_KEYS.remove(glfwCode); if (isPressed) {
} PRESSED_KEYS.add(glfwCode);
} } else {
PRESSED_KEYS.remove(glfwCode);
public static TIntSet getPressedKeys() { }
return PRESSED_KEYS; }
}
public static TIntSet getPressedKeys() {
static void releaseEverything() { return PRESSED_KEYS;
PRESSED_KEYS.clear(); }
}
static void releaseEverything() {
} PRESSED_KEYS.clear();
}
}

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