Merge branch 'master' into moduleSystem
This commit is contained in:
commit
513feb1093
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -2,5 +2,8 @@
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
|
||||
* text=auto eol=lf
|
||||
|
||||
*.bat text eol=crlf
|
||||
|
||||
|
17
.gitignore
vendored
17
.gitignore
vendored
@ -16,7 +16,12 @@ bin
|
||||
# Ignore MacOS
|
||||
**/.DS_Store
|
||||
.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
|
||||
build_packages/*
|
||||
@ -25,12 +30,10 @@ build_packages/*
|
||||
!build_packages/NSIS
|
||||
build_packages/NSIS/*
|
||||
!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/progressia-*
|
||||
build_packages/DEB/progressia-*/*
|
||||
!build_packages/DEB/progressia-*/DEBIAN
|
||||
build_packages/DEB/progressia-*/DEBIAN/*
|
||||
!build_packages/DEB/progressia-*/DEBIAN/control
|
||||
!build_packages/DEB/template
|
||||
|
74
README.md
74
README.md
@ -1,46 +1,58 @@
|
||||
# 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
|
||||
|
||||
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
|
||||
|
||||
On GNU/Linux and MacOS:
|
||||
|
||||
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 { ... }`:
|
||||
```
|
||||
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'
|
||||
For a more in-depth explanation, solutions for common problems and tips for IDE configuration
|
||||
please see the [Build Guide](docs/building/BuildGuide.md).
|
||||
|
||||
## Libraries
|
||||
|
||||
* LWJGL - OpenGL, OpenAL, GLFW and several more libraries ported to Java
|
||||
* Google Guava
|
||||
* Trove4j
|
||||
* java-graphics/glm - GLM ported to Java. _Maven Central contains an outdated version, a custom repository used instead_
|
||||
* OpenSimplex2
|
||||
* log4j
|
||||
- [LWJGL](https://www.lwjgl.org/) ([GitHub](https://github.com/LWJGL/lwjgl3)) – OpenGL, OpenAL, GLFW and STB libraries ported to Java
|
||||
- [OpenGL](https://en.wikipedia.org/wiki/OpenGL) – a low-level graphics interface
|
||||
- [OpenAL](https://en.wikipedia.org/wiki/OpenAL) – a low-level audio interface
|
||||
- [GLFW](https://www.glfw.org/) ([GitHub](https://github.com/glfw/glfw)) – a minimalistic OpenGL-capable windowing library
|
||||
- [STB (GitHub)](https://github.com/nothings/stb) – a collection of various algorithms. `stb_vorbis` is used
|
||||
- [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
|
||||
|
112
buildPackages.sh
112
buildPackages.sh
@ -1,24 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Progressia
|
||||
# Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
echoerr() { echo "$@" 1>&2; }
|
||||
|
||||
buildDebianPackage() {
|
||||
|
||||
# Commands that must be available to execute this action
|
||||
requiredCommands='dpkg-deb fakeroot'
|
||||
|
||||
# Version that the package will receive
|
||||
version='0.1_all'
|
||||
|
||||
directory="build_packages/DEB/progressia-$version"
|
||||
|
||||
# .deb control file that must be present
|
||||
configurationFile="$directory/DEBIAN/control"
|
||||
|
||||
outputFile="build_packages/DEB/progressia-$version.deb"
|
||||
|
||||
# Package name. Sync with control file manually!
|
||||
name='progressia-techdemo'
|
||||
# Version that the package will receive. Sync with control file manually!
|
||||
version='1.0_all'
|
||||
|
||||
# This directory will be copied into $tmpDir
|
||||
templateDirectory="build_packages/DEB/template"
|
||||
|
||||
# Files that must be present
|
||||
requiredFiles="$templateDirectory/DEBIAN/control"
|
||||
|
||||
nameAndVersion="$name-$version"
|
||||
tmpDir="build_packages/DEB/$nameAndVersion"
|
||||
outputFile="build_packages/DEB/$nameAndVersion.deb"
|
||||
|
||||
echo "Checking environment to build Debian package"
|
||||
|
||||
|
||||
for item in $requiredCommands; do
|
||||
if command -v "$item" &> /dev/null; then
|
||||
echo "- $item found"
|
||||
@ -27,43 +50,46 @@ buildDebianPackage() {
|
||||
exit 100
|
||||
fi
|
||||
done
|
||||
|
||||
if ! [ -r "$configurationFile" ]; then
|
||||
echoerr "$configurationFile is missing or not readable, cannot package"
|
||||
exit 101
|
||||
else
|
||||
echo "- $configurationFile is present and readable"
|
||||
fi
|
||||
|
||||
|
||||
for file in $requiredFiles; do
|
||||
if ! [ -r "$file" ]; then
|
||||
echoerr "$file is missing or not readable, cannot package"
|
||||
exit 101
|
||||
else
|
||||
echo "- $file is present and readable"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Environment OK; packaging Debian package"
|
||||
exitCode=0
|
||||
|
||||
|
||||
{
|
||||
user=`whoami`
|
||||
homeDir="$directory/home/$user/Progressia/"
|
||||
|
||||
mkdir -p "$homeDir" &&
|
||||
cp -r 'build/libs/lib' "$homeDir/lib" &&
|
||||
cp 'build/libs/Progressia.jar' "$homeDir/Progressia.jar" &&
|
||||
echo "------ DPKG-DEB ------" &&
|
||||
fakeroot dpkg-deb --build "$directory" &&
|
||||
echo "---- DPKG-DEB END ----" &&
|
||||
shareDir="$tmpDir/usr/share/progressia"
|
||||
|
||||
mkdir -p "$tmpDir" &&
|
||||
mkdir -p "$shareDir" &&
|
||||
cp -r "$templateDirectory"/* "$tmpDir" &&
|
||||
cp -r 'build/libs/lib' "$shareDir/lib" &&
|
||||
cp 'build/libs/Progressia.jar' "$shareDir/Progressia.jar" &&
|
||||
echo "------ DPKG-DEB ------" &&
|
||||
fakeroot dpkg-deb --build "$tmpDir" &&
|
||||
echo "---- DPKG-DEB END ----" &&
|
||||
mv "$outputFile" build_packages
|
||||
} || {
|
||||
echoerr "Could not create Debian package"
|
||||
exitCode=1
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
if [ -d "$homeDir" ]; then
|
||||
rm -r "$homeDir"
|
||||
if [ -d "$tmpDir" ]; then
|
||||
rm -r "$tmpDir"
|
||||
fi
|
||||
echo "Cleaned up"
|
||||
} || {
|
||||
echoerr "Could not clean up after packaging Debian package"
|
||||
exitCode=2
|
||||
}
|
||||
|
||||
|
||||
exit "$exitCode"
|
||||
}
|
||||
|
||||
@ -71,15 +97,15 @@ buildWindowsInstaller() {
|
||||
|
||||
# Commands that must be available to execute this action
|
||||
requiredCommands='makensis'
|
||||
|
||||
|
||||
# NSIS configuration file that must be present
|
||||
configurationFile='build_packages/NSIS/ProgressiaInstaller.nsi'
|
||||
|
||||
|
||||
# File that will be output
|
||||
outputFile='build_packages/NSIS/ProgressiaInstaller.exe'
|
||||
|
||||
echo "Checking environment to build Windows installer"
|
||||
|
||||
|
||||
for item in $requiredCommands; do
|
||||
if command -v "$item" &> /dev/null; then
|
||||
echo "- $item found"
|
||||
@ -88,20 +114,21 @@ buildWindowsInstaller() {
|
||||
exit 100
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
if ! [ -r "$configurationFile" ]; then
|
||||
echoerr "$configurationFile is missing or not readable, cannot build"
|
||||
exit 101
|
||||
else
|
||||
echo "- $configurationFile is present and readable"
|
||||
fi
|
||||
|
||||
|
||||
echo "Environment OK; building Windows installer"
|
||||
exitCode=0
|
||||
|
||||
|
||||
{
|
||||
cp -r 'build/libs/lib' 'build_packages/NSIS/lib' &&
|
||||
cp 'build/libs/Progressia.jar' 'build_packages/NSIS/Progressia.jar' &&
|
||||
cp 'LICENSE' 'build_packages/NSIS/LICENSE.txt' &&
|
||||
echo "------ NSIS ------" &&
|
||||
makensis "$configurationFile" &&
|
||||
echo "---- NSIS END ----" &&
|
||||
@ -110,7 +137,7 @@ buildWindowsInstaller() {
|
||||
echoerr "Could not build Windows installer"
|
||||
exitCode=1
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
if [ -d 'build_packages/NSIS/lib' ]; then
|
||||
rm -r 'build_packages/NSIS/lib'
|
||||
@ -118,12 +145,15 @@ buildWindowsInstaller() {
|
||||
if [ -e 'build_packages/NSIS/Progressia.jar' ]; then
|
||||
rm 'build_packages/NSIS/Progressia.jar'
|
||||
fi
|
||||
if [ -e 'build_packages/NSIS/LICENSE.txt' ]; then
|
||||
rm 'build_packages/NSIS/LICENSE.txt'
|
||||
fi
|
||||
echo "Cleaned up"
|
||||
} || {
|
||||
echoerr "Could not clean up after building Windows installer"
|
||||
exitCode=2
|
||||
}
|
||||
|
||||
|
||||
exit "$exitCode"
|
||||
}
|
||||
|
||||
|
@ -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
|
8
build_packages/DEB/template/DEBIAN/control
Normal file
8
build_packages/DEB/template/DEBIAN/control
Normal 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
|
@ -10,16 +10,32 @@
|
||||
;--------------------------------
|
||||
;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 "Progressia"
|
||||
OutFile "ProgressiaInstaller.exe"
|
||||
Name "${PROJECT_NAME}"
|
||||
OutFile "${PROJECT_NAME}Installer.exe"
|
||||
Unicode True
|
||||
|
||||
;Default installation folder
|
||||
InstallDir "$PROGRAMFILES\Progressia"
|
||||
InstallDir "$PROGRAMFILES\${PROJECT_NAME}"
|
||||
|
||||
;Get installation folder from registry if available
|
||||
InstallDirRegKey HKLM "Software\Progressia" "Install_Dir"
|
||||
InstallDirRegKey HKLM "Software\${PROJECT_NAME}" ""
|
||||
|
||||
;Request application privileges for Windows Vista
|
||||
RequestExecutionLevel admin
|
||||
@ -33,14 +49,18 @@
|
||||
;Pages
|
||||
|
||||
!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_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!define MUI_FINISHPAGE_RUN
|
||||
!define MUI_FINISHPAGE_RUN_TEXT "Start ${PROJECT_NAME}"
|
||||
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchLink"
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
!insertmacro MUI_UNPAGE_WELCOME
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_COMPONENTS
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
@ -52,35 +72,40 @@
|
||||
;--------------------------------
|
||||
;Installer Sections
|
||||
|
||||
Section "Install Progressia" SecDummy
|
||||
Section "Install ${PROJECT_NAME}" SEC0000
|
||||
|
||||
SectionIn RO ;Make it read-only
|
||||
SetOutPath "$INSTDIR"
|
||||
SetOverwrite on
|
||||
|
||||
;Files
|
||||
File Progressia.jar
|
||||
File logo.ico
|
||||
File /r lib
|
||||
|
||||
;Store installation folder
|
||||
WriteRegStr HKLM SOFTWARE\Progressia "Install_Dir" "$INSTDIR"
|
||||
|
||||
;Create uninstaller
|
||||
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Progressia" "DisplayName" "Progressia (remove only)"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Progressia" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "DisplayName" "${PROJECT_NAME} (remove only)"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Descriptions
|
||||
Section "Create Desktop Shortcut" SEC0001
|
||||
SetOutPath "$APPDATA\${PROJECT_NAME}"
|
||||
CreateShortCut "$DESKTOP\${PROJECT_NAME}.lnk" "$INSTDIR\${PROJECT_NAME}.jar" "" "$INSTDIR\logo.ico"
|
||||
SectionEnd
|
||||
|
||||
;Language strings
|
||||
LangString DESC_SecDummy ${LANG_ENGLISH} "A test section."
|
||||
Section "Start Menu Shortcuts" SEC0002
|
||||
|
||||
;Assign language strings to sections
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SecDummy} $(DESC_SecDummy)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
CreateDirectory "$SMPROGRAMS\${PROJECT_NAME}"
|
||||
CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
CreateShortcut "$SMPROGRAMS\${PROJECT_NAME}\${PROJECT_NAME}.lnk" "$INSTDIR\${PROJECT_NAME}.jar" "" "$INSTDIR\logo.ico"
|
||||
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Uninstaller Section
|
||||
@ -92,9 +117,45 @@ Section "Uninstall"
|
||||
Delete $INSTDIR\Uninstall.exe
|
||||
Delete $INSTDIR\Progressia.jar
|
||||
Delete $INSTDIR\lib\*.*
|
||||
Delete $INSTDIR\logo.ico
|
||||
|
||||
RMDir /r "$INSTDIR"
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Progressia"
|
||||
DeleteRegKey HKLM "Software\Progressia"
|
||||
RMDir $INSTDIR\lib
|
||||
|
||||
Delete $DESKTOP\${PROJECT_NAME}.lnk
|
||||
|
||||
Delete $SMPROGRAMS\${PROJECT_NAME}\Uninstall.lnk
|
||||
Delete $SMPROGRAMS\${PROJECT_NAME}\${PROJECT_NAME}.lnk
|
||||
|
||||
RMDir $INSTDIR
|
||||
|
||||
RMDir /r $SMPROGRAMS\${PROJECT_NAME}
|
||||
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROJECT_NAME}"
|
||||
DeleteRegKey HKLM "Software\${PROJECT_NAME}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "un.Remove user data"
|
||||
|
||||
RMDir /r "$APPDATA\${PROJECT_NAME}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Functions
|
||||
|
||||
Function LaunchLink
|
||||
SetOutPath "$APPDATA\${PROJECT_NAME}"
|
||||
ExecShell "" "$INSTDIR\${PROJECT_NAME}.jar"
|
||||
FunctionEnd
|
||||
|
||||
;--------------------------------
|
||||
;Descriptions
|
||||
|
||||
;Language strings
|
||||
LangString DESC_SecDummy ${LANG_ENGLISH} "Install ${PROJECT_NAME}."
|
||||
|
||||
;Assign language strings to sections
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC0000} $(DESC_SecDummy)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
BIN
build_packages/NSIS/left_side.bmp
Normal file
BIN
build_packages/NSIS/left_side.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
BIN
build_packages/NSIS/logo.ico
Normal file
BIN
build_packages/NSIS/logo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 187 KiB |
69
docs/CONTRIBUTING.md
Normal file
69
docs/CONTRIBUTING.md
Normal 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
203
docs/building/BuildGuide.md
Normal 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.
|
125
docs/building/EclipseGuide.md
Normal file
125
docs/building/EclipseGuide.md
Normal 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.
|
44
docs/building/IntelliJIDEAGuide.md
Normal file
44
docs/building/IntelliJIDEAGuide.md
Normal 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
1
run/.dummy
Normal file
@ -0,0 +1 @@
|
||||
This is a dummy file to make sure run/ directory is stored and created by git.
|
@ -3,9 +3,11 @@ package kdotjpg.opensimplex2.areagen;
|
||||
* This file has been modified in the following ways:
|
||||
* - added a package declaration at line 1;
|
||||
* - 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
|
||||
* 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
@ -1,20 +1,21 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* 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/>.
|
||||
*******************************************************************************/
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil;
|
||||
|
||||
import java.io.OutputStream;
|
||||
@ -22,53 +23,53 @@ import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
public class CSVWriter {
|
||||
|
||||
|
||||
private String columnSeparator = ";";
|
||||
private String rowSeparator = "\n";
|
||||
|
||||
|
||||
private boolean shouldAddSeparator = false;
|
||||
|
||||
|
||||
private final PrintWriter parent;
|
||||
|
||||
|
||||
public CSVWriter(PrintWriter output) {
|
||||
this.parent = output;
|
||||
}
|
||||
|
||||
|
||||
public CSVWriter(Writer output) {
|
||||
this(new PrintWriter(output));
|
||||
}
|
||||
|
||||
|
||||
public CSVWriter(OutputStream output) {
|
||||
this(new PrintWriter(output));
|
||||
}
|
||||
|
||||
|
||||
public PrintWriter getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
||||
public String getColumnSeparator() {
|
||||
return columnSeparator;
|
||||
}
|
||||
|
||||
|
||||
public CSVWriter setColumnSeparator(String columnSeparator) {
|
||||
this.columnSeparator = columnSeparator;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public String getRowSeparator() {
|
||||
return rowSeparator;
|
||||
}
|
||||
|
||||
|
||||
public CSVWriter setRowSeparator(String rowSeparator) {
|
||||
this.rowSeparator = rowSeparator;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public void print(Object object) {
|
||||
skip();
|
||||
getParent().print(String.valueOf(object));
|
||||
}
|
||||
|
||||
|
||||
public void skip() {
|
||||
if (shouldAddSeparator) {
|
||||
getParent().print(getColumnSeparator());
|
||||
@ -76,27 +77,27 @@ public class CSVWriter {
|
||||
shouldAddSeparator = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void skip(int amount) {
|
||||
for (int i = 0; i < amount; ++i) {
|
||||
skip();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void endRow() {
|
||||
getParent().print(getRowSeparator());
|
||||
shouldAddSeparator = false;
|
||||
}
|
||||
|
||||
|
||||
public void endRow(Object object) {
|
||||
print(object);
|
||||
endRow();
|
||||
}
|
||||
|
||||
|
||||
public void flush() {
|
||||
getParent().flush();
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
getParent().close();
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
/*
|
||||
* 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
|
||||
* 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
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PrimitiveUtil {
|
||||
|
||||
private PrimitiveUtil() {}
|
||||
|
||||
private PrimitiveUtil() {
|
||||
}
|
||||
|
||||
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_BOXED = new HashMap<>();
|
||||
private static final Map<Class<?>, Object> PRIMITIVE_TO_NULL = new HashMap<>();
|
||||
|
||||
|
||||
static {
|
||||
for (Class<?> boxed : new Class<?>[] {
|
||||
Boolean.class, Byte.class, Short.class, Character.class,
|
||||
Integer.class, Long.class, Float.class, Double.class
|
||||
}) {
|
||||
for (
|
||||
Class<?> boxed : new Class<?>[] {
|
||||
Boolean.class,
|
||||
Byte.class,
|
||||
Short.class,
|
||||
Character.class,
|
||||
Integer.class,
|
||||
Long.class,
|
||||
Float.class,
|
||||
Double.class
|
||||
}
|
||||
) {
|
||||
try {
|
||||
PRIMITIVE_TO_BOXED.put((Class<?>) boxed.getField("TYPE").get(null), boxed);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
PRIMITIVE_TO_NULL.put(Boolean.TYPE, Boolean.FALSE);
|
||||
PRIMITIVE_TO_NULL.put(Byte.TYPE, Byte.valueOf((byte) 0));
|
||||
PRIMITIVE_TO_NULL.put(Short.TYPE, Short.valueOf((short) 0));
|
||||
PRIMITIVE_TO_NULL.put(Integer.TYPE, Integer.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(Double.TYPE, Double.valueOf(Double.NaN));
|
||||
PRIMITIVE_TO_NULL.put(Character.TYPE, Character.valueOf('\u0000'));
|
||||
|
||||
PRIMITIVE_TO_NULL.put(Boolean.TYPE, Boolean.FALSE);
|
||||
PRIMITIVE_TO_NULL.put(Byte.TYPE, Byte.valueOf((byte) 0));
|
||||
PRIMITIVE_TO_NULL.put(Short.TYPE, Short.valueOf((short) 0));
|
||||
PRIMITIVE_TO_NULL.put(Integer.TYPE, Integer.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(Double.TYPE, Double.valueOf(Double.NaN));
|
||||
PRIMITIVE_TO_NULL.put(Character.TYPE, Character.valueOf('\u0000'));
|
||||
}
|
||||
|
||||
|
||||
public static Class<?> getBoxedClass(Class<?> primitiveClass) {
|
||||
return PRIMITIVE_TO_BOXED.getOrDefault(primitiveClass, primitiveClass);
|
||||
}
|
||||
|
||||
|
||||
public static Object getPrimitiveNull(Class<?> primitiveClass) {
|
||||
return PRIMITIVE_TO_NULL.get(primitiveClass);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,44 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil;
|
||||
|
||||
public class SyntaxException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -4052144233640072750L;
|
||||
|
||||
public SyntaxException() {
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SyntaxException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil;
|
||||
|
||||
public class SyntaxException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -4052144233640072750L;
|
||||
|
||||
public SyntaxException() {
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public SyntaxException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,128 +1,132 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
|
||||
public class CharArrayIterator implements CharacterIterator {
|
||||
|
||||
private final char[] array;
|
||||
private int pos;
|
||||
|
||||
public CharArrayIterator(char[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public CharArrayIterator(String src) {
|
||||
this(src.toCharArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public char first() {
|
||||
pos = 0;
|
||||
if (array.length != 0) {
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char last() {
|
||||
pos = array.length;
|
||||
if (array.length != 0) {
|
||||
pos -= 1;
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char current() {
|
||||
if (array.length != 0 && pos < array.length) {
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char next() {
|
||||
pos += 1;
|
||||
if (pos >= array.length) {
|
||||
pos = array.length;
|
||||
return DONE;
|
||||
}
|
||||
return current();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char previous() {
|
||||
if (pos == 0) {
|
||||
return DONE;
|
||||
}
|
||||
pos -= 1;
|
||||
return current();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char setIndex(int position) {
|
||||
if (position < 0 || position > array.length) {
|
||||
throw new IllegalArgumentException("bad position: " + position);
|
||||
}
|
||||
|
||||
pos = position;
|
||||
|
||||
if (pos != array.length && array.length != 0) {
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeginIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndIndex() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
// @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 CharArrayIterator clone() {
|
||||
try {
|
||||
return (CharArrayIterator) super.clone();
|
||||
} catch (CloneNotSupportedException cnse) {
|
||||
// Impossible
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
|
||||
public class CharArrayIterator implements CharacterIterator {
|
||||
|
||||
private final char[] array;
|
||||
private int pos;
|
||||
|
||||
public CharArrayIterator(char[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public CharArrayIterator(String src) {
|
||||
this(src.toCharArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public char first() {
|
||||
pos = 0;
|
||||
if (array.length != 0) {
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char last() {
|
||||
pos = array.length;
|
||||
if (array.length != 0) {
|
||||
pos -= 1;
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char current() {
|
||||
if (array.length != 0 && pos < array.length) {
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char next() {
|
||||
pos += 1;
|
||||
if (pos >= array.length) {
|
||||
pos = array.length;
|
||||
return DONE;
|
||||
}
|
||||
return current();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char previous() {
|
||||
if (pos == 0) {
|
||||
return DONE;
|
||||
}
|
||||
pos -= 1;
|
||||
return current();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char setIndex(int position) {
|
||||
if (position < 0 || position > array.length) {
|
||||
throw new IllegalArgumentException("bad position: " + position);
|
||||
}
|
||||
|
||||
pos = position;
|
||||
|
||||
if (pos != array.length && array.length != 0) {
|
||||
return array[pos];
|
||||
}
|
||||
return DONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeginIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndIndex() {
|
||||
return array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
// @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 CharArrayIterator clone() {
|
||||
try {
|
||||
return (CharArrayIterator) super.clone();
|
||||
} catch (CloneNotSupportedException cnse) {
|
||||
// Impossible
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,42 +1,43 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.function.IntConsumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CharConsumer {
|
||||
|
||||
void accept(char c);
|
||||
|
||||
public static CharConsumer andThen(CharConsumer first, CharConsumer second) {
|
||||
return c -> {
|
||||
first.accept(c);
|
||||
second.accept(c);
|
||||
};
|
||||
}
|
||||
|
||||
public static IntConsumer toInt(CharConsumer consumer) {
|
||||
return i -> consumer.accept((char) i);
|
||||
}
|
||||
|
||||
public static CharConsumer toChar(IntConsumer consumer) {
|
||||
return consumer::accept;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.function.IntConsumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CharConsumer {
|
||||
|
||||
void accept(char c);
|
||||
|
||||
public static CharConsumer andThen(CharConsumer first, CharConsumer second) {
|
||||
return c -> {
|
||||
first.accept(c);
|
||||
second.accept(c);
|
||||
};
|
||||
}
|
||||
|
||||
public static IntConsumer toInt(CharConsumer consumer) {
|
||||
return i -> consumer.accept((char) i);
|
||||
}
|
||||
|
||||
public static CharConsumer toChar(IntConsumer consumer) {
|
||||
return consumer::accept;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,69 +1,70 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public class 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) {
|
||||
return fillArray(array, 0, -1);
|
||||
}
|
||||
|
||||
private static class ArrayFiller implements CharConsumer {
|
||||
|
||||
final char[] array;
|
||||
int i;
|
||||
final int end;
|
||||
|
||||
/**
|
||||
* @param array
|
||||
* @param offset
|
||||
* @param length
|
||||
*/
|
||||
ArrayFiller(char[] array, int offset, int length) {
|
||||
this.array = Objects.requireNonNull(array, "array");
|
||||
this.end = ArrayUtil.checkArrayStartEnd(array, offset, offset + length);
|
||||
this.i = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.CharConsumer#accept(char)
|
||||
*/
|
||||
@Override
|
||||
public void accept(char c) {
|
||||
if (i == end)
|
||||
throw new ArrayIndexOutOfBoundsException(end);
|
||||
array[i++] = c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public class 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) {
|
||||
return fillArray(array, 0, -1);
|
||||
}
|
||||
|
||||
private static class ArrayFiller implements CharConsumer {
|
||||
|
||||
final char[] array;
|
||||
int i;
|
||||
final int end;
|
||||
|
||||
/**
|
||||
* @param array
|
||||
* @param offset
|
||||
* @param length
|
||||
*/
|
||||
ArrayFiller(char[] array, int offset, int length) {
|
||||
this.array = Objects.requireNonNull(array, "array");
|
||||
this.end = ArrayUtil.checkArrayStartEnd(array, offset, offset + length);
|
||||
this.i = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.CharConsumer#accept(char)
|
||||
*/
|
||||
@Override
|
||||
public void accept(char c) {
|
||||
if (i == end)
|
||||
throw new ArrayIndexOutOfBoundsException(end);
|
||||
array[i++] = c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,84 +1,85 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.IntPredicate;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CharPredicate {
|
||||
|
||||
boolean test(char 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 negate(CharPredicate predicate) {
|
||||
return c -> !predicate.test(c);
|
||||
}
|
||||
|
||||
public static IntPredicate toInt(CharPredicate predicate) {
|
||||
return i -> predicate.test((char) i);
|
||||
}
|
||||
|
||||
public static CharPredicate toChar(IntPredicate predicate) {
|
||||
return predicate::test;
|
||||
}
|
||||
|
||||
public static CharPredicate forArray(char... chars) {
|
||||
if (chars.length == 0) {
|
||||
return c -> false;
|
||||
}
|
||||
|
||||
if (chars.length == 1) {
|
||||
return forChar(chars[0]);
|
||||
}
|
||||
|
||||
if (chars.length < 16) {
|
||||
return c -> ArrayUtil.firstIndexOf(chars, c) >= 0;
|
||||
} else {
|
||||
final char[] sorted = Arrays.copyOf(chars, chars.length);
|
||||
Arrays.sort(sorted);
|
||||
return c -> Arrays.binarySearch(chars, c) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static CharPredicate forChar(final char c) {
|
||||
return given -> given == c;
|
||||
}
|
||||
|
||||
public static CharPredicate forRange(final char minInclusive, final char maxExclusive) {
|
||||
if (minInclusive > maxExclusive) {
|
||||
throw new IllegalArgumentException("min > max: " + minInclusive + " > " + maxExclusive);
|
||||
}
|
||||
|
||||
if (minInclusive == maxExclusive) {
|
||||
return c -> false;
|
||||
}
|
||||
|
||||
return c -> c >= minInclusive && c < maxExclusive;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.IntPredicate;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CharPredicate {
|
||||
|
||||
boolean test(char 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 negate(CharPredicate predicate) {
|
||||
return c -> !predicate.test(c);
|
||||
}
|
||||
|
||||
public static IntPredicate toInt(CharPredicate predicate) {
|
||||
return i -> predicate.test((char) i);
|
||||
}
|
||||
|
||||
public static CharPredicate toChar(IntPredicate predicate) {
|
||||
return predicate::test;
|
||||
}
|
||||
|
||||
public static CharPredicate forArray(char... chars) {
|
||||
if (chars.length == 0) {
|
||||
return c -> false;
|
||||
}
|
||||
|
||||
if (chars.length == 1) {
|
||||
return forChar(chars[0]);
|
||||
}
|
||||
|
||||
if (chars.length < 16) {
|
||||
return c -> ArrayUtil.firstIndexOf(chars, c) >= 0;
|
||||
} else {
|
||||
final char[] sorted = Arrays.copyOf(chars, chars.length);
|
||||
Arrays.sort(sorted);
|
||||
return c -> Arrays.binarySearch(chars, c) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static CharPredicate forChar(final char c) {
|
||||
return given -> given == c;
|
||||
}
|
||||
|
||||
public static CharPredicate forRange(final char minInclusive, final char maxExclusive) {
|
||||
if (minInclusive > maxExclusive) {
|
||||
throw new IllegalArgumentException("min > max: " + minInclusive + " > " + maxExclusive);
|
||||
}
|
||||
|
||||
if (minInclusive == maxExclusive) {
|
||||
return c -> false;
|
||||
}
|
||||
|
||||
return c -> c >= minInclusive && c < maxExclusive;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,35 +1,36 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CharSupplier {
|
||||
|
||||
char getAsChar();
|
||||
|
||||
public static IntSupplier toInt(CharSupplier consumer) {
|
||||
return consumer::getAsChar;
|
||||
}
|
||||
|
||||
public static CharSupplier toChar(IntSupplier consumer) {
|
||||
return () -> (char) consumer.getAsInt();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CharSupplier {
|
||||
|
||||
char getAsChar();
|
||||
|
||||
public static IntSupplier toInt(CharSupplier consumer) {
|
||||
return consumer::getAsChar;
|
||||
}
|
||||
|
||||
public static CharSupplier toChar(IntSupplier consumer) {
|
||||
return () -> (char) consumer.getAsInt();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,44 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
public class EscapeException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -3647188859290365053L;
|
||||
|
||||
public EscapeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
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) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EscapeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
public class EscapeException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -3647188859290365053L;
|
||||
|
||||
public EscapeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
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) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EscapeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,474 +1,514 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
import ru.windcorp.jputil.chars.reader.CharReader;
|
||||
import ru.windcorp.jputil.chars.reader.CharReaders;
|
||||
|
||||
public class Escaper {
|
||||
|
||||
public static class EscaperBuilder {
|
||||
private char escapeChar = '\\';
|
||||
private char unicodeEscapeChar = 'u';
|
||||
private char[] safes = null;
|
||||
private char[] unsafes = null;
|
||||
|
||||
private boolean preferUnicode = false;
|
||||
private boolean strict = true;
|
||||
|
||||
public EscaperBuilder withEscapeChar(char escapeChar) {
|
||||
this.escapeChar = escapeChar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withUnicodeEscapeChar(char unicodeEscapeChar) {
|
||||
this.unicodeEscapeChar = unicodeEscapeChar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(char[] safes, char[] unsafes) {
|
||||
this.safes = safes;
|
||||
this.unsafes = unsafes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(String safes, String unsafes) {
|
||||
this.safes = safes.toCharArray();
|
||||
this.unsafes = unsafes.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(char[] chars) {
|
||||
this.safes = this.unsafes = chars;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(String chars) {
|
||||
this.safes = this.unsafes = chars.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withSafes(char[] safes) {
|
||||
this.safes = safes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withSafes(String safes) {
|
||||
this.safes = safes.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withUnsafes(char[] unsafes) {
|
||||
this.unsafes = unsafes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withUnsafes(String unsafes) {
|
||||
this.unsafes = unsafes.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder preferUnicode(boolean preferUnicode) {
|
||||
this.preferUnicode = preferUnicode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder strict(boolean strict) {
|
||||
this.strict = strict;
|
||||
return this;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
private final char escapeChar;
|
||||
private final char unicodeEscapeChar;
|
||||
private final char[] safes;
|
||||
private final char[] unsafes;
|
||||
|
||||
private final boolean preferUnicode;
|
||||
private final boolean strict;
|
||||
|
||||
protected Escaper(
|
||||
char escapeChar, char unicodeEscapeChar,
|
||||
char[] safes, char[] unsafes,
|
||||
boolean preferUnicode, boolean strict) {
|
||||
this.escapeChar = escapeChar;
|
||||
this.unicodeEscapeChar = unicodeEscapeChar;
|
||||
this.safes = safes;
|
||||
this.unsafes = unsafes;
|
||||
this.preferUnicode = preferUnicode;
|
||||
this.strict = strict;
|
||||
|
||||
int duplicate;
|
||||
if ((duplicate = ArrayUtil.hasDuplicates(safes)) != -1)
|
||||
throw new IllegalArgumentException("Duplicate safe character '" + safes[duplicate] + "'");
|
||||
|
||||
if ((duplicate = ArrayUtil.hasDuplicates(unsafes)) != -1)
|
||||
throw new IllegalArgumentException("Duplicate unsafe character '" + unsafes[duplicate] + "'");
|
||||
|
||||
for (char c : safes) {
|
||||
if (c == escapeChar) throw new IllegalArgumentException("Safe characters contain escape chatacter");
|
||||
if (c == unicodeEscapeChar) throw new IllegalArgumentException("Safe characters contain Unicode escape chatacter");
|
||||
}
|
||||
|
||||
for (char c : unsafes) {
|
||||
if (c == escapeChar) throw new IllegalArgumentException("Unsafe characters contain escape chatacter (escape character is escaped automatically)");
|
||||
if (c == unicodeEscapeChar) throw new IllegalArgumentException("Unsafe characters contain Unicode escape chatacter");
|
||||
}
|
||||
}
|
||||
|
||||
public static EscaperBuilder create() {
|
||||
return new EscaperBuilder();
|
||||
}
|
||||
|
||||
/*
|
||||
* Logic - escape
|
||||
*/
|
||||
|
||||
public void escape(CharReader src, int length, CharPredicate until, CharConsumer output) {
|
||||
int end;
|
||||
if (length < 0) end = Integer.MAX_VALUE;
|
||||
else end = src.getPosition() + length;
|
||||
while (src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current())))
|
||||
escape(src.consume(), output);
|
||||
}
|
||||
|
||||
public void escape(char c, CharConsumer output) {
|
||||
if (c == escapeChar) {
|
||||
output.accept(escapeChar);
|
||||
output.accept(escapeChar);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = ArrayUtil.firstIndexOf(unsafes, c);
|
||||
|
||||
if (index >= 0) {
|
||||
output.accept(escapeChar);
|
||||
output.accept(safes[index]);
|
||||
} else {
|
||||
if (preferUnicode && !isRegular(c)) {
|
||||
escapeAsHex(c, output);
|
||||
} else {
|
||||
output.accept(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SonarLint: Assignments should not be made from within sub-expressions (java:S1121)
|
||||
// Seems self-evident enough
|
||||
@SuppressWarnings("squid:S1121")
|
||||
|
||||
private void escapeAsHex(char c, CharConsumer output) {
|
||||
output.accept(escapeChar);
|
||||
output.accept(unicodeEscapeChar);
|
||||
output.accept(StringUtil.hexDigit(c >>= (4 * 3)));
|
||||
output.accept(StringUtil.hexDigit(c >>= (4 * 2)));
|
||||
output.accept(StringUtil.hexDigit(c >>= (4 * 1)));
|
||||
output.accept(StringUtil.hexDigit(c >> (4 * 0)));
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src, int length, CharPredicate until) {
|
||||
int end;
|
||||
if (length < 0) end = Integer.MAX_VALUE;
|
||||
else end = src.getPosition() + length;
|
||||
|
||||
int result = 0;
|
||||
|
||||
while (src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current()))) {
|
||||
result += getEscapedLength(src.consume());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int getEscapedLength(char c) {
|
||||
if (c == escapeChar || ArrayUtil.firstIndexOf(unsafes, c) >= 0)
|
||||
return 2;
|
||||
else {
|
||||
if (preferUnicode && !isRegular(c))
|
||||
return 6;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Logic - unescape
|
||||
*/
|
||||
|
||||
public void unescape(CharReader src, int length, CharPredicate until, CharConsumer output) throws EscapeException {
|
||||
int end;
|
||||
if (length < 0) end = Integer.MAX_VALUE;
|
||||
else end = src.getPosition() + length;
|
||||
while (src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current()))) {
|
||||
output.accept(unescapeOneSequence(src));
|
||||
}
|
||||
}
|
||||
|
||||
public char unescapeOneSequence(CharReader src) throws EscapeException {
|
||||
int resetPos = src.getPosition();
|
||||
try {
|
||||
if (src.current() == escapeChar) {
|
||||
src.next();
|
||||
|
||||
if (src.isEnd())
|
||||
throw new EscapeException("Incomplete escape sequence at the end");
|
||||
|
||||
if (src.current() == escapeChar) {
|
||||
src.next();
|
||||
return escapeChar;
|
||||
}
|
||||
|
||||
if (src.current() == unicodeEscapeChar) {
|
||||
src.next();
|
||||
return (char) (
|
||||
hexValue(src.consume()) << (4 * 3) |
|
||||
hexValue(src.consume()) << (4 * 2) |
|
||||
hexValue(src.consume()) << (4 * 1) |
|
||||
hexValue(src.consume()) << (4 * 0)
|
||||
);
|
||||
}
|
||||
|
||||
int index = ArrayUtil.firstIndexOf(safes, src.current());
|
||||
if (index >= 0) {
|
||||
src.next();
|
||||
return unsafes[index];
|
||||
}
|
||||
|
||||
if (strict)
|
||||
throw new EscapeException("Unknown escape sequence \"" + escapeChar + src.current() + "\"");
|
||||
else
|
||||
return src.consume();
|
||||
} else
|
||||
return src.consume();
|
||||
} catch (EscapeException | RuntimeException e) {
|
||||
src.setPosition(resetPos);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src, int length, CharPredicate until) {
|
||||
int end;
|
||||
if (length < 0) end = Integer.MAX_VALUE;
|
||||
else end = src.getPosition() + length;
|
||||
|
||||
int result = 0;
|
||||
|
||||
while (src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current()))) {
|
||||
skipOneSequence(src);
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void skipOneSequence(CharReader src) {
|
||||
if (
|
||||
src.current() == escapeChar
|
||||
&&
|
||||
src.next() == unicodeEscapeChar
|
||||
) {
|
||||
src.advance(4);
|
||||
}
|
||||
src.next();
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility
|
||||
*/
|
||||
|
||||
public void escape(CharReader src, int length, CharConsumer output) {
|
||||
escape(src, length, null, output);
|
||||
}
|
||||
|
||||
public void escape(CharReader src, CharPredicate until, CharConsumer output) {
|
||||
escape(src, -1, until, output);
|
||||
}
|
||||
|
||||
public void escape(CharReader src, CharConsumer output) {
|
||||
escape(src, -1, null, output);
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src, int length) {
|
||||
return getEscapedLength(src, length, null);
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src, CharPredicate until) {
|
||||
return getEscapedLength(src, -1, until);
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src) {
|
||||
return getEscapedLength(src, -1, null);
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src, int length, CharPredicate until) {
|
||||
src.mark();
|
||||
char[] result = new char[getEscapedLength(src, length, until)];
|
||||
src.reset();
|
||||
escape(src, length, until, CharConsumers.fillArray(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src, int length) {
|
||||
return escape(src, length, (CharPredicate) null);
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src, CharPredicate until) {
|
||||
return escape(src, -1, until);
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src) {
|
||||
return escape(src, -1, (CharPredicate) null);
|
||||
}
|
||||
|
||||
public void unescape(CharReader src, int length, CharConsumer output) throws EscapeException {
|
||||
unescape(src, length, null, output);
|
||||
}
|
||||
|
||||
public void unescape(CharReader src, CharPredicate until, CharConsumer output) throws EscapeException {
|
||||
unescape(src, -1, until, output);
|
||||
}
|
||||
|
||||
public void unescape(CharReader src, CharConsumer output) throws EscapeException {
|
||||
unescape(src, -1, null, output);
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src, int length) {
|
||||
return getUnescapedLength(src, length, null);
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src, CharPredicate until) {
|
||||
return getUnescapedLength(src, -1, until);
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src) {
|
||||
return getUnescapedLength(src, -1, null);
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src, int length, CharPredicate until) throws EscapeException {
|
||||
src.mark();
|
||||
char[] result = new char[getUnescapedLength(src, length, until)];
|
||||
src.reset();
|
||||
unescape(src, length, until, CharConsumers.fillArray(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src, int length) throws EscapeException {
|
||||
return unescape(src, length, (CharPredicate) null);
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src, CharPredicate until) throws EscapeException {
|
||||
return unescape(src, -1, until);
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src) throws EscapeException {
|
||||
return unescape(src, -1, (CharPredicate) null);
|
||||
}
|
||||
|
||||
@Deprecated()
|
||||
public char[] unescape(CharacterIterator src, char until) throws EscapeException {
|
||||
int index = src.getIndex();
|
||||
CharReader reader = CharReaders.wrap(src);
|
||||
|
||||
char[] result = unescape(reader, -1, CharPredicate.forChar(until));
|
||||
|
||||
src.setIndex(index + reader.getPosition());
|
||||
return result;
|
||||
}
|
||||
|
||||
public String escape(String src) {
|
||||
StringBuilder result = new StringBuilder(src.length());
|
||||
escape(CharReaders.wrap(src), (CharConsumer) result::append);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public String unescape(String src) throws EscapeException {
|
||||
StringBuilder result = new StringBuilder(src.length());
|
||||
unescape(CharReaders.wrap(src), (CharConsumer) result::append);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
|
||||
private static int hexValue(char c) throws EscapeException {
|
||||
if (c < '0') throw thisIsNotAHexDigit(c);
|
||||
if (c <= '9') return c - '0';
|
||||
if (c < 'A') throw thisIsNotAHexDigit(c);
|
||||
if (c <= 'F') return c - 'A';
|
||||
if (c < 'a') throw thisIsNotAHexDigit(c);
|
||||
if (c <= 'f') return c - 'a';
|
||||
if (c == CharReader.DONE) throw new EscapeException("Incomplete Unicode escape sequence at the end");
|
||||
throw thisIsNotAHexDigit(c);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
import ru.windcorp.jputil.chars.reader.CharReader;
|
||||
import ru.windcorp.jputil.chars.reader.CharReaders;
|
||||
|
||||
public class Escaper {
|
||||
|
||||
public static class EscaperBuilder {
|
||||
private char escapeChar = '\\';
|
||||
private char unicodeEscapeChar = 'u';
|
||||
private char[] safes = null;
|
||||
private char[] unsafes = null;
|
||||
|
||||
private boolean preferUnicode = false;
|
||||
private boolean strict = true;
|
||||
|
||||
public EscaperBuilder withEscapeChar(char escapeChar) {
|
||||
this.escapeChar = escapeChar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withUnicodeEscapeChar(char unicodeEscapeChar) {
|
||||
this.unicodeEscapeChar = unicodeEscapeChar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(char[] safes, char[] unsafes) {
|
||||
this.safes = safes;
|
||||
this.unsafes = unsafes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(String safes, String unsafes) {
|
||||
this.safes = safes.toCharArray();
|
||||
this.unsafes = unsafes.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(char[] chars) {
|
||||
this.safes = this.unsafes = chars;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withChars(String chars) {
|
||||
this.safes = this.unsafes = chars.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withSafes(char[] safes) {
|
||||
this.safes = safes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withSafes(String safes) {
|
||||
this.safes = safes.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withUnsafes(char[] unsafes) {
|
||||
this.unsafes = unsafes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder withUnsafes(String unsafes) {
|
||||
this.unsafes = unsafes.toCharArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder preferUnicode(boolean preferUnicode) {
|
||||
this.preferUnicode = preferUnicode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EscaperBuilder strict(boolean strict) {
|
||||
this.strict = strict;
|
||||
return this;
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
private final char escapeChar;
|
||||
private final char unicodeEscapeChar;
|
||||
private final char[] safes;
|
||||
private final char[] unsafes;
|
||||
|
||||
private final boolean preferUnicode;
|
||||
private final boolean strict;
|
||||
|
||||
protected Escaper(
|
||||
char escapeChar,
|
||||
char unicodeEscapeChar,
|
||||
char[] safes,
|
||||
char[] unsafes,
|
||||
boolean preferUnicode,
|
||||
boolean strict
|
||||
) {
|
||||
this.escapeChar = escapeChar;
|
||||
this.unicodeEscapeChar = unicodeEscapeChar;
|
||||
this.safes = safes;
|
||||
this.unsafes = unsafes;
|
||||
this.preferUnicode = preferUnicode;
|
||||
this.strict = strict;
|
||||
|
||||
int duplicate;
|
||||
if ((duplicate = ArrayUtil.hasDuplicates(safes)) != -1)
|
||||
throw new IllegalArgumentException("Duplicate safe character '" + safes[duplicate] + "'");
|
||||
|
||||
if ((duplicate = ArrayUtil.hasDuplicates(unsafes)) != -1)
|
||||
throw new IllegalArgumentException("Duplicate unsafe character '" + unsafes[duplicate] + "'");
|
||||
|
||||
for (char c : safes) {
|
||||
if (c == escapeChar)
|
||||
throw new IllegalArgumentException("Safe characters contain escape chatacter");
|
||||
if (c == unicodeEscapeChar)
|
||||
throw new IllegalArgumentException("Safe characters contain Unicode escape chatacter");
|
||||
}
|
||||
|
||||
for (char c : unsafes) {
|
||||
if (c == escapeChar)
|
||||
throw new IllegalArgumentException(
|
||||
"Unsafe characters contain escape chatacter (escape character is escaped automatically)"
|
||||
);
|
||||
if (c == unicodeEscapeChar)
|
||||
throw new IllegalArgumentException("Unsafe characters contain Unicode escape chatacter");
|
||||
}
|
||||
}
|
||||
|
||||
public static EscaperBuilder create() {
|
||||
return new EscaperBuilder();
|
||||
}
|
||||
|
||||
/*
|
||||
* Logic - escape
|
||||
*/
|
||||
|
||||
public void escape(CharReader src, int length, CharPredicate until, CharConsumer output) {
|
||||
int end;
|
||||
if (length < 0)
|
||||
end = Integer.MAX_VALUE;
|
||||
else
|
||||
end = src.getPosition() + length;
|
||||
while (
|
||||
src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current()))
|
||||
)
|
||||
escape(src.consume(), output);
|
||||
}
|
||||
|
||||
public void escape(char c, CharConsumer output) {
|
||||
if (c == escapeChar) {
|
||||
output.accept(escapeChar);
|
||||
output.accept(escapeChar);
|
||||
return;
|
||||
}
|
||||
|
||||
int index = ArrayUtil.firstIndexOf(unsafes, c);
|
||||
|
||||
if (index >= 0) {
|
||||
output.accept(escapeChar);
|
||||
output.accept(safes[index]);
|
||||
} else {
|
||||
if (preferUnicode && !isRegular(c)) {
|
||||
escapeAsHex(c, output);
|
||||
} else {
|
||||
output.accept(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SonarLint: Assignments should not be made from within sub-expressions
|
||||
// (java:S1121)
|
||||
// Seems self-evident enough
|
||||
@SuppressWarnings("squid:S1121")
|
||||
|
||||
private void escapeAsHex(char c, CharConsumer output) {
|
||||
output.accept(escapeChar);
|
||||
output.accept(unicodeEscapeChar);
|
||||
output.accept(StringUtil.hexDigit(c >>= (4 * 3)));
|
||||
output.accept(StringUtil.hexDigit(c >>= (4 * 2)));
|
||||
output.accept(StringUtil.hexDigit(c >>= (4 * 1)));
|
||||
output.accept(StringUtil.hexDigit(c >> (4 * 0)));
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src, int length, CharPredicate until) {
|
||||
int end;
|
||||
if (length < 0)
|
||||
end = Integer.MAX_VALUE;
|
||||
else
|
||||
end = src.getPosition() + length;
|
||||
|
||||
int result = 0;
|
||||
|
||||
while (
|
||||
src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current()))
|
||||
) {
|
||||
result += getEscapedLength(src.consume());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int getEscapedLength(char c) {
|
||||
if (c == escapeChar || ArrayUtil.firstIndexOf(unsafes, c) >= 0)
|
||||
return 2;
|
||||
else {
|
||||
if (preferUnicode && !isRegular(c))
|
||||
return 6;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Logic - unescape
|
||||
*/
|
||||
|
||||
public void unescape(CharReader src, int length, CharPredicate until, CharConsumer output) throws EscapeException {
|
||||
int end;
|
||||
if (length < 0)
|
||||
end = Integer.MAX_VALUE;
|
||||
else
|
||||
end = src.getPosition() + length;
|
||||
while (
|
||||
src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current()))
|
||||
) {
|
||||
output.accept(unescapeOneSequence(src));
|
||||
}
|
||||
}
|
||||
|
||||
public char unescapeOneSequence(CharReader src) throws EscapeException {
|
||||
int resetPos = src.getPosition();
|
||||
try {
|
||||
if (src.current() == escapeChar) {
|
||||
src.next();
|
||||
|
||||
if (src.isEnd())
|
||||
throw new EscapeException("Incomplete escape sequence at the end");
|
||||
|
||||
if (src.current() == escapeChar) {
|
||||
src.next();
|
||||
return escapeChar;
|
||||
}
|
||||
|
||||
if (src.current() == unicodeEscapeChar) {
|
||||
src.next();
|
||||
return (char) (hexValue(src.consume()) << (4 * 3) |
|
||||
hexValue(src.consume()) << (4 * 2) |
|
||||
hexValue(src.consume()) << (4 * 1) |
|
||||
hexValue(src.consume()) << (4 * 0));
|
||||
}
|
||||
|
||||
int index = ArrayUtil.firstIndexOf(safes, src.current());
|
||||
if (index >= 0) {
|
||||
src.next();
|
||||
return unsafes[index];
|
||||
}
|
||||
|
||||
if (strict)
|
||||
throw new EscapeException("Unknown escape sequence \"" + escapeChar + src.current() + "\"");
|
||||
else
|
||||
return src.consume();
|
||||
} else
|
||||
return src.consume();
|
||||
} catch (EscapeException | RuntimeException e) {
|
||||
src.setPosition(resetPos);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src, int length, CharPredicate until) {
|
||||
int end;
|
||||
if (length < 0)
|
||||
end = Integer.MAX_VALUE;
|
||||
else
|
||||
end = src.getPosition() + length;
|
||||
|
||||
int result = 0;
|
||||
|
||||
while (
|
||||
src.has() &&
|
||||
src.getPosition() < end &&
|
||||
(until == null || !until.test(src.current()))
|
||||
) {
|
||||
skipOneSequence(src);
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void skipOneSequence(CharReader src) {
|
||||
if (
|
||||
src.current() == escapeChar
|
||||
&&
|
||||
src.next() == unicodeEscapeChar
|
||||
) {
|
||||
src.advance(4);
|
||||
}
|
||||
src.next();
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility
|
||||
*/
|
||||
|
||||
public void escape(CharReader src, int length, CharConsumer output) {
|
||||
escape(src, length, null, output);
|
||||
}
|
||||
|
||||
public void escape(CharReader src, CharPredicate until, CharConsumer output) {
|
||||
escape(src, -1, until, output);
|
||||
}
|
||||
|
||||
public void escape(CharReader src, CharConsumer output) {
|
||||
escape(src, -1, null, output);
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src, int length) {
|
||||
return getEscapedLength(src, length, null);
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src, CharPredicate until) {
|
||||
return getEscapedLength(src, -1, until);
|
||||
}
|
||||
|
||||
public int getEscapedLength(CharReader src) {
|
||||
return getEscapedLength(src, -1, null);
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src, int length, CharPredicate until) {
|
||||
src.mark();
|
||||
char[] result = new char[getEscapedLength(src, length, until)];
|
||||
src.reset();
|
||||
escape(src, length, until, CharConsumers.fillArray(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src, int length) {
|
||||
return escape(src, length, (CharPredicate) null);
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src, CharPredicate until) {
|
||||
return escape(src, -1, until);
|
||||
}
|
||||
|
||||
public char[] escape(CharReader src) {
|
||||
return escape(src, -1, (CharPredicate) null);
|
||||
}
|
||||
|
||||
public void unescape(CharReader src, int length, CharConsumer output) throws EscapeException {
|
||||
unescape(src, length, null, output);
|
||||
}
|
||||
|
||||
public void unescape(CharReader src, CharPredicate until, CharConsumer output) throws EscapeException {
|
||||
unescape(src, -1, until, output);
|
||||
}
|
||||
|
||||
public void unescape(CharReader src, CharConsumer output) throws EscapeException {
|
||||
unescape(src, -1, null, output);
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src, int length) {
|
||||
return getUnescapedLength(src, length, null);
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src, CharPredicate until) {
|
||||
return getUnescapedLength(src, -1, until);
|
||||
}
|
||||
|
||||
public int getUnescapedLength(CharReader src) {
|
||||
return getUnescapedLength(src, -1, null);
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src, int length, CharPredicate until) throws EscapeException {
|
||||
src.mark();
|
||||
char[] result = new char[getUnescapedLength(src, length, until)];
|
||||
src.reset();
|
||||
unescape(src, length, until, CharConsumers.fillArray(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src, int length) throws EscapeException {
|
||||
return unescape(src, length, (CharPredicate) null);
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src, CharPredicate until) throws EscapeException {
|
||||
return unescape(src, -1, until);
|
||||
}
|
||||
|
||||
public char[] unescape(CharReader src) throws EscapeException {
|
||||
return unescape(src, -1, (CharPredicate) null);
|
||||
}
|
||||
|
||||
@Deprecated()
|
||||
public char[] unescape(CharacterIterator src, char until) throws EscapeException {
|
||||
int index = src.getIndex();
|
||||
CharReader reader = CharReaders.wrap(src);
|
||||
|
||||
char[] result = unescape(reader, -1, CharPredicate.forChar(until));
|
||||
|
||||
src.setIndex(index + reader.getPosition());
|
||||
return result;
|
||||
}
|
||||
|
||||
public String escape(String src) {
|
||||
StringBuilder result = new StringBuilder(src.length());
|
||||
escape(CharReaders.wrap(src), (CharConsumer) result::append);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public String unescape(String src) throws EscapeException {
|
||||
StringBuilder result = new StringBuilder(src.length());
|
||||
unescape(CharReaders.wrap(src), (CharConsumer) result::append);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
|
||||
private static int hexValue(char c) throws EscapeException {
|
||||
if (c < '0')
|
||||
throw thisIsNotAHexDigit(c);
|
||||
if (c <= '9')
|
||||
return c - '0';
|
||||
if (c < 'A')
|
||||
throw thisIsNotAHexDigit(c);
|
||||
if (c <= 'F')
|
||||
return c - 'A';
|
||||
if (c < 'a')
|
||||
throw thisIsNotAHexDigit(c);
|
||||
if (c <= 'f')
|
||||
return c - 'a';
|
||||
if (c == CharReader.DONE)
|
||||
throw new EscapeException("Incomplete Unicode escape sequence at the end");
|
||||
throw thisIsNotAHexDigit(c);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,17 +1,21 @@
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* 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.
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.text.CharacterIterator;
|
||||
@ -26,77 +30,81 @@ public class FancyCharacterIterator implements CharacterIterator {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public char first() {
|
||||
return obj.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public char last() {
|
||||
return obj.last();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public char setIndex(int p) {
|
||||
return obj.setIndex(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public char current() {
|
||||
return obj.current();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public char next() {
|
||||
return obj.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public char previous() {
|
||||
return obj.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public int getBeginIndex() {
|
||||
return obj.getBeginIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public int getEndIndex() {
|
||||
return obj.getEndIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return obj.getIndex();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("\"");
|
||||
sb.append(data);
|
||||
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.");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,135 +1,138 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
public class IndentedStringBuilder {
|
||||
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
|
||||
private int indentLevel = 0;
|
||||
private boolean indentApplied = false;
|
||||
|
||||
private String[] indentCache = new String[16];
|
||||
private String indent = "";
|
||||
private final char[] indentFill;
|
||||
|
||||
public IndentedStringBuilder(char[] indentFill) {
|
||||
this.indentFill = indentFill;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder(String indentFill) {
|
||||
this(indentFill.toCharArray());
|
||||
}
|
||||
|
||||
public IndentedStringBuilder(char indentChar, int length) {
|
||||
this(StringUtil.sequence(indentChar, length));
|
||||
}
|
||||
|
||||
public IndentedStringBuilder() {
|
||||
this(new char[] {' '});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getIndentLevel() {
|
||||
return indentLevel;
|
||||
}
|
||||
|
||||
public void setIndentLevel(int level) {
|
||||
this.indentLevel = level;
|
||||
updateIndent();
|
||||
}
|
||||
|
||||
public char[] getIndentFill() {
|
||||
return indentFill;
|
||||
}
|
||||
|
||||
protected void updateIndent() {
|
||||
if (indentLevel < indentCache.length) {
|
||||
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)
|
||||
System.arraycopy(fill, 0, array, i, fill.length);
|
||||
indent = new String(array);
|
||||
|
||||
if (indentLevel < indentCache.length) {
|
||||
indentCache[indentLevel] = indent;
|
||||
}
|
||||
}
|
||||
|
||||
public IndentedStringBuilder indent() {
|
||||
setIndentLevel(getIndentLevel() + 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder unindent() {
|
||||
setIndentLevel(getIndentLevel() - 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder append(Object x) {
|
||||
if (x == null) {
|
||||
appendRaw("null");
|
||||
return this;
|
||||
}
|
||||
|
||||
String str = x.toString();
|
||||
int newLines = StringUtil.count(str, '\n');
|
||||
|
||||
if (newLines == 0) {
|
||||
appendRaw(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
String[] lines = StringUtil.split(str, '\n', newLines + 1);
|
||||
appendRaw(lines[0]);
|
||||
|
||||
for (int i = 1; i < lines.length; ++i) {
|
||||
newLine();
|
||||
appendRaw(lines[i]);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder appendRaw(String str) {
|
||||
if (str.isEmpty()) return this; // Do not append indent
|
||||
|
||||
if (!indentApplied) {
|
||||
sb.append(indent);
|
||||
indentApplied = true;
|
||||
}
|
||||
|
||||
sb.append(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder newLine() {
|
||||
sb.append('\n');
|
||||
indentApplied = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
public class IndentedStringBuilder {
|
||||
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
|
||||
private int indentLevel = 0;
|
||||
private boolean indentApplied = false;
|
||||
|
||||
private String[] indentCache = new String[16];
|
||||
private String indent = "";
|
||||
private final char[] indentFill;
|
||||
|
||||
public IndentedStringBuilder(char[] indentFill) {
|
||||
this.indentFill = indentFill;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder(String indentFill) {
|
||||
this(indentFill.toCharArray());
|
||||
}
|
||||
|
||||
public IndentedStringBuilder(char indentChar, int length) {
|
||||
this(StringUtil.sequence(indentChar, length));
|
||||
}
|
||||
|
||||
public IndentedStringBuilder() {
|
||||
this(new char[] { ' ' });
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getIndentLevel() {
|
||||
return indentLevel;
|
||||
}
|
||||
|
||||
public void setIndentLevel(int level) {
|
||||
this.indentLevel = level;
|
||||
updateIndent();
|
||||
}
|
||||
|
||||
public char[] getIndentFill() {
|
||||
return indentFill;
|
||||
}
|
||||
|
||||
protected void updateIndent() {
|
||||
if (indentLevel < indentCache.length) {
|
||||
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)
|
||||
System.arraycopy(fill, 0, array, i, fill.length);
|
||||
indent = new String(array);
|
||||
|
||||
if (indentLevel < indentCache.length) {
|
||||
indentCache[indentLevel] = indent;
|
||||
}
|
||||
}
|
||||
|
||||
public IndentedStringBuilder indent() {
|
||||
setIndentLevel(getIndentLevel() + 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder unindent() {
|
||||
setIndentLevel(getIndentLevel() - 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder append(Object x) {
|
||||
if (x == null) {
|
||||
appendRaw("null");
|
||||
return this;
|
||||
}
|
||||
|
||||
String str = x.toString();
|
||||
int newLines = StringUtil.count(str, '\n');
|
||||
|
||||
if (newLines == 0) {
|
||||
appendRaw(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
String[] lines = StringUtil.split(str, '\n', newLines + 1);
|
||||
appendRaw(lines[0]);
|
||||
|
||||
for (int i = 1; i < lines.length; ++i) {
|
||||
newLine();
|
||||
appendRaw(lines[i]);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder appendRaw(String str) {
|
||||
if (str.isEmpty())
|
||||
return this; // Do not append indent
|
||||
|
||||
if (!indentApplied) {
|
||||
sb.append(indent);
|
||||
indentApplied = true;
|
||||
}
|
||||
|
||||
sb.append(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
public IndentedStringBuilder newLine() {
|
||||
sb.append('\n');
|
||||
indentApplied = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,37 +1,38 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
public class UncheckedEscapeException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 5392628641744570926L;
|
||||
|
||||
public UncheckedEscapeException(String message, EscapeException cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UncheckedEscapeException(EscapeException cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized EscapeException getCause() {
|
||||
return (EscapeException) super.getCause();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
public class UncheckedEscapeException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 5392628641744570926L;
|
||||
|
||||
public UncheckedEscapeException(String message, EscapeException cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UncheckedEscapeException(EscapeException cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized EscapeException getCause() {
|
||||
return (EscapeException) super.getCause();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,139 +1,143 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class WordReader implements Iterator<String> {
|
||||
|
||||
private final Reader reader;
|
||||
|
||||
private char[] wordBuffer = new char[1024];
|
||||
private final CharBuffer inputBuffer;
|
||||
|
||||
private String next = null;
|
||||
private boolean isExhausted = false;
|
||||
|
||||
private IOException lastException = null;
|
||||
|
||||
public WordReader(Reader src, int bufferSize) {
|
||||
this.reader = src;
|
||||
this.inputBuffer = CharBuffer.allocate(bufferSize);
|
||||
}
|
||||
|
||||
public WordReader(Reader src) {
|
||||
this(src, 2048);
|
||||
}
|
||||
|
||||
public WordReader(char[] array, int offset, int length) {
|
||||
this.reader = null;
|
||||
this.inputBuffer = CharBuffer.wrap(Arrays.copyOfRange(array, offset, length + offset));
|
||||
}
|
||||
|
||||
public WordReader(char[] array) {
|
||||
this.reader = null;
|
||||
this.inputBuffer = CharBuffer.wrap(array);
|
||||
}
|
||||
|
||||
public WordReader(String str) {
|
||||
this(str.toCharArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
String result = next;
|
||||
next = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (next != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isExhausted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
char c;
|
||||
while (true) {
|
||||
c = nextChar();
|
||||
|
||||
if (isExhausted) break;
|
||||
|
||||
if (Character.isWhitespace(c)) {
|
||||
if (length == 0) continue;
|
||||
else break;
|
||||
}
|
||||
|
||||
if (wordBuffer.length == length) {
|
||||
char[] newBuf = new char[wordBuffer.length * 2];
|
||||
System.arraycopy(wordBuffer, 0, newBuf, 0, wordBuffer.length);
|
||||
wordBuffer = newBuf;
|
||||
}
|
||||
|
||||
wordBuffer[length++] = c;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
next = new String(wordBuffer, 0, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
private char nextChar() {
|
||||
if (!inputBuffer.hasRemaining()) {
|
||||
if (reader == null) {
|
||||
isExhausted = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inputBuffer.rewind();
|
||||
try {
|
||||
if (reader.read(inputBuffer) == -1) {
|
||||
isExhausted = true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
lastException = e;
|
||||
isExhausted = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return inputBuffer.get();
|
||||
}
|
||||
|
||||
public IOException getLastException() {
|
||||
return lastException;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.nio.CharBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class WordReader implements Iterator<String> {
|
||||
|
||||
private final Reader reader;
|
||||
|
||||
private char[] wordBuffer = new char[1024];
|
||||
private final CharBuffer inputBuffer;
|
||||
|
||||
private String next = null;
|
||||
private boolean isExhausted = false;
|
||||
|
||||
private IOException lastException = null;
|
||||
|
||||
public WordReader(Reader src, int bufferSize) {
|
||||
this.reader = src;
|
||||
this.inputBuffer = CharBuffer.allocate(bufferSize);
|
||||
}
|
||||
|
||||
public WordReader(Reader src) {
|
||||
this(src, 2048);
|
||||
}
|
||||
|
||||
public WordReader(char[] array, int offset, int length) {
|
||||
this.reader = null;
|
||||
this.inputBuffer = CharBuffer.wrap(Arrays.copyOfRange(array, offset, length + offset));
|
||||
}
|
||||
|
||||
public WordReader(char[] array) {
|
||||
this.reader = null;
|
||||
this.inputBuffer = CharBuffer.wrap(array);
|
||||
}
|
||||
|
||||
public WordReader(String str) {
|
||||
this(str.toCharArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
String result = next;
|
||||
next = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (next != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isExhausted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int length = 0;
|
||||
char c;
|
||||
while (true) {
|
||||
c = nextChar();
|
||||
|
||||
if (isExhausted)
|
||||
break;
|
||||
|
||||
if (Character.isWhitespace(c)) {
|
||||
if (length == 0)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (wordBuffer.length == length) {
|
||||
char[] newBuf = new char[wordBuffer.length * 2];
|
||||
System.arraycopy(wordBuffer, 0, newBuf, 0, wordBuffer.length);
|
||||
wordBuffer = newBuf;
|
||||
}
|
||||
|
||||
wordBuffer[length++] = c;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
next = new String(wordBuffer, 0, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
private char nextChar() {
|
||||
if (!inputBuffer.hasRemaining()) {
|
||||
if (reader == null) {
|
||||
isExhausted = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inputBuffer.rewind();
|
||||
try {
|
||||
if (reader.read(inputBuffer) == -1) {
|
||||
isExhausted = true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
lastException = e;
|
||||
isExhausted = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return inputBuffer.get();
|
||||
}
|
||||
|
||||
public IOException getLastException() {
|
||||
return lastException;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,104 +1,108 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractCharReader implements CharReader {
|
||||
|
||||
protected static final int DEFAULT_MARK_STACK_SIZE = 8;
|
||||
|
||||
/**
|
||||
* Current position of this CharReader. The reader maps its input to positions starting from 0.
|
||||
* Positions that are negative or lower than 0 are invalid. {@link #current()}
|
||||
* will throw an exception if position is invalid.
|
||||
*/
|
||||
protected int position = 0;
|
||||
|
||||
private int[] marks = new int[DEFAULT_MARK_STACK_SIZE];
|
||||
private int nextMark = 0;
|
||||
|
||||
protected static int closestGreaterPowerOf2(int x) {
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#getPosition()
|
||||
*/
|
||||
@Override
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#setPosition(int)
|
||||
*/
|
||||
@Override
|
||||
public int setPosition(int position) {
|
||||
this.position = position;
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#mark()
|
||||
*/
|
||||
@Override
|
||||
public int mark() {
|
||||
ensureMarksCapacity();
|
||||
marks[nextMark++] = position;
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#forget()
|
||||
*/
|
||||
@Override
|
||||
public int forget() {
|
||||
return marks[--nextMark];
|
||||
}
|
||||
|
||||
private void ensureMarksCapacity() {
|
||||
if (nextMark < marks.length) return;
|
||||
int[] newMarks = new int[closestGreaterPowerOf2(nextMark)];
|
||||
System.arraycopy(marks, 0, newMarks, 0, nextMark);
|
||||
marks = newMarks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("\"");
|
||||
|
||||
mark();
|
||||
position = 0;
|
||||
sb.append(getChars());
|
||||
reset();
|
||||
|
||||
sb.append("\"\n ");
|
||||
for (int i = 0; i < position; ++i) sb.append(' ');
|
||||
sb.append("^ (pos " + position + ")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public abstract class AbstractCharReader implements CharReader {
|
||||
|
||||
protected static final int DEFAULT_MARK_STACK_SIZE = 8;
|
||||
|
||||
/**
|
||||
* Current position of this CharReader. The reader maps its input to
|
||||
* positions starting from 0.
|
||||
* Positions that are negative or lower than 0 are invalid.
|
||||
* {@link #current()}
|
||||
* will throw an exception if position is invalid.
|
||||
*/
|
||||
protected int position = 0;
|
||||
|
||||
private int[] marks = new int[DEFAULT_MARK_STACK_SIZE];
|
||||
private int nextMark = 0;
|
||||
|
||||
protected static int closestGreaterPowerOf2(int x) {
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#getPosition()
|
||||
*/
|
||||
@Override
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#setPosition(int)
|
||||
*/
|
||||
@Override
|
||||
public int setPosition(int position) {
|
||||
this.position = position;
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#mark()
|
||||
*/
|
||||
@Override
|
||||
public int mark() {
|
||||
ensureMarksCapacity();
|
||||
marks[nextMark++] = position;
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#forget()
|
||||
*/
|
||||
@Override
|
||||
public int forget() {
|
||||
return marks[--nextMark];
|
||||
}
|
||||
|
||||
private void ensureMarksCapacity() {
|
||||
if (nextMark < marks.length)
|
||||
return;
|
||||
int[] newMarks = new int[closestGreaterPowerOf2(nextMark)];
|
||||
System.arraycopy(marks, 0, newMarks, 0, nextMark);
|
||||
marks = newMarks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("\"");
|
||||
|
||||
mark();
|
||||
position = 0;
|
||||
sb.append(getChars());
|
||||
reset();
|
||||
|
||||
sb.append("\"\n ");
|
||||
for (int i = 0; i < position; ++i)
|
||||
sb.append(' ');
|
||||
sb.append("^ (pos " + position + ")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,59 +1,60 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public class ArrayCharReader extends AbstractCharReader {
|
||||
|
||||
private final char[] array;
|
||||
private final int offset;
|
||||
private final int length;
|
||||
|
||||
public ArrayCharReader(char[] array, int offset, int length) {
|
||||
this.array = Objects.requireNonNull(array, "array");
|
||||
this.length = ArrayUtil.checkArrayOffsetLength(array, offset, length);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#current()
|
||||
*/
|
||||
@Override
|
||||
public char current() {
|
||||
if (position >= length) return DONE;
|
||||
if (position < 0)
|
||||
throw new IllegalStateException("Position " + position + " is invalid");
|
||||
return array[position + offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#remaining()
|
||||
*/
|
||||
@Override
|
||||
public int remaining() {
|
||||
return length - position;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import ru.windcorp.jputil.ArrayUtil;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public class ArrayCharReader extends AbstractCharReader {
|
||||
|
||||
private final char[] array;
|
||||
private final int offset;
|
||||
private final int length;
|
||||
|
||||
public ArrayCharReader(char[] array, int offset, int length) {
|
||||
this.array = Objects.requireNonNull(array, "array");
|
||||
this.length = ArrayUtil.checkArrayOffsetLength(array, offset, length);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#current()
|
||||
*/
|
||||
@Override
|
||||
public char current() {
|
||||
if (position >= length)
|
||||
return DONE;
|
||||
if (position < 0)
|
||||
throw new IllegalStateException("Position " + position + " is invalid");
|
||||
return array[position + offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#remaining()
|
||||
*/
|
||||
@Override
|
||||
public int remaining() {
|
||||
return length - position;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,122 +1,128 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public abstract class BufferedCharReader extends AbstractCharReader {
|
||||
|
||||
protected static final int DEFAULT_BUFFER_SIZE = 256;
|
||||
/**
|
||||
* Buffer to store data acquired with {@link #pullChars(char[], int, int)}.
|
||||
* Contains characters for positions <code>[0; bufferNextIndex)</code>.
|
||||
*/
|
||||
private char[] buffer = new char[DEFAULT_BUFFER_SIZE];
|
||||
|
||||
/**
|
||||
* The index of the next character.
|
||||
*/
|
||||
private int bufferNextIndex = 0;
|
||||
|
||||
/**
|
||||
* Whether this reader has been buffered completely.
|
||||
*/
|
||||
private boolean exhausted = false;
|
||||
|
||||
/**
|
||||
* Acquires the next character.
|
||||
* @return the character or {@link #DONE} if the end of the reader has been reached
|
||||
*/
|
||||
protected abstract char pullChar();
|
||||
|
||||
/**
|
||||
* Acquires next characters and stores them in the array.
|
||||
*
|
||||
* @param buffer the output array
|
||||
* @param offset index of the first character
|
||||
* @param length maximum amount of characters to be pulled
|
||||
* @return the amount of characters actually pulled
|
||||
*/
|
||||
protected int pullChars(char[] buffer, int offset, int length) {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if ((buffer[offset + i] = pullChar()) == DONE) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int pullChars(int offset, int length) {
|
||||
if (exhausted || length == 0) return 0;
|
||||
|
||||
int pulled = pullChars(buffer, offset, length);
|
||||
if (pulled != length) {
|
||||
exhausted = true;
|
||||
}
|
||||
|
||||
return pulled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char current() {
|
||||
if (getPosition() < 0) {
|
||||
throw new IllegalStateException("Position " + getPosition() + " is invalid");
|
||||
}
|
||||
|
||||
if (getPosition() >= bufferNextIndex) {
|
||||
if (exhausted) return DONE;
|
||||
|
||||
ensureBufferCapacity();
|
||||
|
||||
int needToPull = getPosition() - bufferNextIndex + 1;
|
||||
assert needToPull <= buffer.length : "buffer size not ensured!";
|
||||
|
||||
int pulled = pullChars(bufferNextIndex, needToPull);
|
||||
bufferNextIndex += pulled;
|
||||
|
||||
if (exhausted) return DONE;
|
||||
}
|
||||
|
||||
// TODO test the shit out of current()
|
||||
|
||||
return buffer[getPosition()];
|
||||
}
|
||||
|
||||
private void ensureBufferCapacity() {
|
||||
if (getPosition() < buffer.length) return;
|
||||
char[] newBuffer = new char[closestGreaterPowerOf2(getPosition())];
|
||||
System.arraycopy(buffer, 0, newBuffer, 0, bufferNextIndex);
|
||||
buffer = newBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#remaining()
|
||||
*/
|
||||
@Override
|
||||
public int remaining() {
|
||||
if (exhausted) {
|
||||
return Math.max(bufferNextIndex - getPosition(), 0);
|
||||
}
|
||||
|
||||
return super.remaining();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public abstract class BufferedCharReader extends AbstractCharReader {
|
||||
|
||||
protected static final int DEFAULT_BUFFER_SIZE = 256;
|
||||
/**
|
||||
* Buffer to store data acquired with {@link #pullChars(char[], int, int)}.
|
||||
* Contains characters for positions <code>[0; bufferNextIndex)</code>.
|
||||
*/
|
||||
private char[] buffer = new char[DEFAULT_BUFFER_SIZE];
|
||||
|
||||
/**
|
||||
* The index of the next character.
|
||||
*/
|
||||
private int bufferNextIndex = 0;
|
||||
|
||||
/**
|
||||
* Whether this reader has been buffered completely.
|
||||
*/
|
||||
private boolean exhausted = false;
|
||||
|
||||
/**
|
||||
* Acquires the next character.
|
||||
*
|
||||
* @return the character or {@link #DONE} if the end of the reader has been
|
||||
* reached
|
||||
*/
|
||||
protected abstract char pullChar();
|
||||
|
||||
/**
|
||||
* Acquires next characters and stores them in the array.
|
||||
*
|
||||
* @param buffer the output array
|
||||
* @param offset index of the first character
|
||||
* @param length maximum amount of characters to be pulled
|
||||
* @return the amount of characters actually pulled
|
||||
*/
|
||||
protected int pullChars(char[] buffer, int offset, int length) {
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if ((buffer[offset + i] = pullChar()) == DONE) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
private int pullChars(int offset, int length) {
|
||||
if (exhausted || length == 0)
|
||||
return 0;
|
||||
|
||||
int pulled = pullChars(buffer, offset, length);
|
||||
if (pulled != length) {
|
||||
exhausted = true;
|
||||
}
|
||||
|
||||
return pulled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char current() {
|
||||
if (getPosition() < 0) {
|
||||
throw new IllegalStateException("Position " + getPosition() + " is invalid");
|
||||
}
|
||||
|
||||
if (getPosition() >= bufferNextIndex) {
|
||||
if (exhausted)
|
||||
return DONE;
|
||||
|
||||
ensureBufferCapacity();
|
||||
|
||||
int needToPull = getPosition() - bufferNextIndex + 1;
|
||||
assert needToPull <= buffer.length : "buffer size not ensured!";
|
||||
|
||||
int pulled = pullChars(bufferNextIndex, needToPull);
|
||||
bufferNextIndex += pulled;
|
||||
|
||||
if (exhausted)
|
||||
return DONE;
|
||||
}
|
||||
|
||||
// TODO test the shit out of current()
|
||||
|
||||
return buffer[getPosition()];
|
||||
}
|
||||
|
||||
private void ensureBufferCapacity() {
|
||||
if (getPosition() < buffer.length)
|
||||
return;
|
||||
char[] newBuffer = new char[closestGreaterPowerOf2(getPosition())];
|
||||
System.arraycopy(buffer, 0, newBuffer, 0, bufferNextIndex);
|
||||
buffer = newBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#remaining()
|
||||
*/
|
||||
@Override
|
||||
public int remaining() {
|
||||
if (exhausted) {
|
||||
return Math.max(bufferNextIndex - getPosition(), 0);
|
||||
}
|
||||
|
||||
return super.remaining();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,270 +1,284 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
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.Escaper;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
|
||||
// SonarLint: Constants should not be defined in interfaces (java:S1214)
|
||||
// DONE is an essential part of the interface
|
||||
@SuppressWarnings("squid:S1214")
|
||||
|
||||
public interface CharReader {
|
||||
|
||||
char DONE = '\uFFFF';
|
||||
|
||||
char current();
|
||||
int getPosition();
|
||||
int setPosition(int position);
|
||||
|
||||
default char next() {
|
||||
return advance(1);
|
||||
}
|
||||
|
||||
default char previous() {
|
||||
return rollBack(1);
|
||||
}
|
||||
|
||||
default char consume() {
|
||||
char c = current();
|
||||
advance(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
default char advance(int forward) {
|
||||
setPosition(getPosition() + forward);
|
||||
return current();
|
||||
}
|
||||
|
||||
default char rollBack(int backward) {
|
||||
return advance(-backward);
|
||||
}
|
||||
|
||||
default boolean isEnd() {
|
||||
return current() == DONE;
|
||||
}
|
||||
|
||||
default boolean has() {
|
||||
return current() != DONE;
|
||||
}
|
||||
|
||||
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) {
|
||||
return i;
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
return 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);
|
||||
if (from != length) Arrays.fill(result, from, length, DONE);
|
||||
return result;
|
||||
}
|
||||
|
||||
default char[] getChars() {
|
||||
return getChars(remaining());
|
||||
}
|
||||
|
||||
default String getString(int length) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length && !isEnd(); ++i) sb.append(consume());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
default String getString() {
|
||||
return getString(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
default boolean match(CharSequence seq) {
|
||||
for (int i = 0; i < seq.length(); ++i) {
|
||||
if (isEnd()) return false;
|
||||
if (current() != seq.charAt(i)) return false;
|
||||
next();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean matchOrReset(CharSequence seq) {
|
||||
mark();
|
||||
if (match(seq)) {
|
||||
forget();
|
||||
return true;
|
||||
} else {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
default boolean match(char[] array) {
|
||||
for (int i = 0; i < array.length; ++i) {
|
||||
if (isEnd()) return false;
|
||||
if (current() != array[i]) return false;
|
||||
next();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean matchOrReset(char[] array) {
|
||||
mark();
|
||||
if (match(array)) {
|
||||
forget();
|
||||
return true;
|
||||
} else {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
default int skip(CharPredicate condition) {
|
||||
int i = 0;
|
||||
|
||||
while (has() && condition.test(current())) {
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
default int skipWhitespace() {
|
||||
return skip(Character::isWhitespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips to the end of the current line. Both <code>"\n"</code>, <code>"\r"</code>
|
||||
* and <code>"\r\n"</code> are considered line separators.
|
||||
* @return the amount of characters in the skipped line
|
||||
*/
|
||||
default int skipLine() {
|
||||
int i = 0;
|
||||
|
||||
while (!isEnd()) {
|
||||
if (current() == '\r') {
|
||||
if (next() == '\n') {
|
||||
next();
|
||||
}
|
||||
break;
|
||||
} else if (current() == '\n') {
|
||||
next();
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
default char[] readWhile(CharPredicate condition) {
|
||||
return readUntil(CharPredicate.negate(condition));
|
||||
}
|
||||
|
||||
default char[] readUntil(CharPredicate condition) {
|
||||
mark();
|
||||
int length = 0;
|
||||
while (!isEnd() && !condition.test(current())) {
|
||||
length++;
|
||||
next();
|
||||
}
|
||||
reset();
|
||||
|
||||
char[] result = new char[length];
|
||||
for (int i = 0; i < length; ++i) result[i] = consume();
|
||||
return result;
|
||||
}
|
||||
|
||||
default char[] readWord() {
|
||||
skipWhitespace();
|
||||
return readUntil(Character::isWhitespace);
|
||||
}
|
||||
|
||||
default char[] readWord(Escaper escaper, char quotes) throws EscapeException {
|
||||
skipWhitespace();
|
||||
|
||||
if (current() == quotes) {
|
||||
return escaper.unescape(this, quotes);
|
||||
} else {
|
||||
return readWord();
|
||||
}
|
||||
}
|
||||
|
||||
default char[] readLine() {
|
||||
mark();
|
||||
int length = skipLine();
|
||||
reset();
|
||||
|
||||
char[] result = new char[length];
|
||||
for (int i = 0; i < result.length; ++i) result[i] = consume();
|
||||
return result;
|
||||
}
|
||||
|
||||
default int remaining() {
|
||||
mark();
|
||||
int result = 0;
|
||||
|
||||
while (consume() != DONE) result++;
|
||||
|
||||
reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
int mark();
|
||||
int forget();
|
||||
|
||||
default int reset() {
|
||||
return setPosition(forget());
|
||||
}
|
||||
|
||||
default IOException getLastException() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default void resetLastException() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
default boolean hasErrored() {
|
||||
return getLastException() != null;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
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.Escaper;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
|
||||
// SonarLint: Constants should not be defined in interfaces (java:S1214)
|
||||
// DONE is an essential part of the interface
|
||||
@SuppressWarnings("squid:S1214")
|
||||
|
||||
public interface CharReader {
|
||||
|
||||
char DONE = '\uFFFF';
|
||||
|
||||
char current();
|
||||
|
||||
int getPosition();
|
||||
|
||||
int setPosition(int position);
|
||||
|
||||
default char next() {
|
||||
return advance(1);
|
||||
}
|
||||
|
||||
default char previous() {
|
||||
return rollBack(1);
|
||||
}
|
||||
|
||||
default char consume() {
|
||||
char c = current();
|
||||
advance(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
default char advance(int forward) {
|
||||
setPosition(getPosition() + forward);
|
||||
return current();
|
||||
}
|
||||
|
||||
default char rollBack(int backward) {
|
||||
return advance(-backward);
|
||||
}
|
||||
|
||||
default boolean isEnd() {
|
||||
return current() == DONE;
|
||||
}
|
||||
|
||||
default boolean has() {
|
||||
return current() != DONE;
|
||||
}
|
||||
|
||||
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) {
|
||||
return i;
|
||||
}
|
||||
next();
|
||||
}
|
||||
|
||||
return 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);
|
||||
if (from != length)
|
||||
Arrays.fill(result, from, length, DONE);
|
||||
return result;
|
||||
}
|
||||
|
||||
default char[] getChars() {
|
||||
return getChars(remaining());
|
||||
}
|
||||
|
||||
default String getString(int length) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length && !isEnd(); ++i)
|
||||
sb.append(consume());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
default String getString() {
|
||||
return getString(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
default boolean match(CharSequence seq) {
|
||||
for (int i = 0; i < seq.length(); ++i) {
|
||||
if (isEnd())
|
||||
return false;
|
||||
if (current() != seq.charAt(i))
|
||||
return false;
|
||||
next();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean matchOrReset(CharSequence seq) {
|
||||
mark();
|
||||
if (match(seq)) {
|
||||
forget();
|
||||
return true;
|
||||
} else {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
default boolean match(char[] array) {
|
||||
for (int i = 0; i < array.length; ++i) {
|
||||
if (isEnd())
|
||||
return false;
|
||||
if (current() != array[i])
|
||||
return false;
|
||||
next();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean matchOrReset(char[] array) {
|
||||
mark();
|
||||
if (match(array)) {
|
||||
forget();
|
||||
return true;
|
||||
} else {
|
||||
reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
default int skip(CharPredicate condition) {
|
||||
int i = 0;
|
||||
|
||||
while (has() && condition.test(current())) {
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
default int skipWhitespace() {
|
||||
return skip(Character::isWhitespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips to the end of the current line. Both <code>"\n"</code>,
|
||||
* <code>"\r"</code>
|
||||
* and <code>"\r\n"</code> are considered line separators.
|
||||
*
|
||||
* @return the amount of characters in the skipped line
|
||||
*/
|
||||
default int skipLine() {
|
||||
int i = 0;
|
||||
|
||||
while (!isEnd()) {
|
||||
if (current() == '\r') {
|
||||
if (next() == '\n') {
|
||||
next();
|
||||
}
|
||||
break;
|
||||
} else if (current() == '\n') {
|
||||
next();
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
default char[] readWhile(CharPredicate condition) {
|
||||
return readUntil(CharPredicate.negate(condition));
|
||||
}
|
||||
|
||||
default char[] readUntil(CharPredicate condition) {
|
||||
mark();
|
||||
int length = 0;
|
||||
while (!isEnd() && !condition.test(current())) {
|
||||
length++;
|
||||
next();
|
||||
}
|
||||
reset();
|
||||
|
||||
char[] result = new char[length];
|
||||
for (int i = 0; i < length; ++i)
|
||||
result[i] = consume();
|
||||
return result;
|
||||
}
|
||||
|
||||
default char[] readWord() {
|
||||
skipWhitespace();
|
||||
return readUntil(Character::isWhitespace);
|
||||
}
|
||||
|
||||
default char[] readWord(Escaper escaper, char quotes) throws EscapeException {
|
||||
skipWhitespace();
|
||||
|
||||
if (current() == quotes) {
|
||||
return escaper.unescape(this, quotes);
|
||||
} else {
|
||||
return readWord();
|
||||
}
|
||||
}
|
||||
|
||||
default char[] readLine() {
|
||||
mark();
|
||||
int length = skipLine();
|
||||
reset();
|
||||
|
||||
char[] result = new char[length];
|
||||
for (int i = 0; i < result.length; ++i)
|
||||
result[i] = consume();
|
||||
return result;
|
||||
}
|
||||
|
||||
default int remaining() {
|
||||
mark();
|
||||
int result = 0;
|
||||
|
||||
while (consume() != DONE)
|
||||
result++;
|
||||
|
||||
reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
int mark();
|
||||
|
||||
int forget();
|
||||
|
||||
default int reset() {
|
||||
return setPosition(forget());
|
||||
}
|
||||
|
||||
default IOException getLastException() {
|
||||
return null;
|
||||
}
|
||||
|
||||
default void resetLastException() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
default boolean hasErrored() {
|
||||
return getLastException() != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,112 +1,113 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
import ru.windcorp.jputil.chars.CharSupplier;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public class 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) {
|
||||
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) {
|
||||
return wrap(str, 0, str.length());
|
||||
}
|
||||
|
||||
public static CharReader wrap(CharSupplier supplier) {
|
||||
return new BufferedCharReader() {
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
try {
|
||||
return supplier.getAsChar();
|
||||
} catch (Exception e) {
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharReader wrap(IntSupplier supplier) {
|
||||
return new BufferedCharReader() {
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
try {
|
||||
int i = supplier.getAsInt();
|
||||
if (i < 0 || i > Character.MAX_VALUE) {
|
||||
return DONE;
|
||||
} else {
|
||||
return (char) i;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharReader wrap(CharacterIterator it) {
|
||||
return new BufferedCharReader() {
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
char result = it.current();
|
||||
it.next();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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 wrapDefaultCS(InputStream is) {
|
||||
return wrap(new InputStreamReader(is));
|
||||
}
|
||||
|
||||
public static CharReader wrapUTF8(InputStream is) {
|
||||
return wrap(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.CharacterIterator;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
import ru.windcorp.jputil.chars.CharSupplier;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public class 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) {
|
||||
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) {
|
||||
return wrap(str, 0, str.length());
|
||||
}
|
||||
|
||||
public static CharReader wrap(CharSupplier supplier) {
|
||||
return new BufferedCharReader() {
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
try {
|
||||
return supplier.getAsChar();
|
||||
} catch (Exception e) {
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharReader wrap(IntSupplier supplier) {
|
||||
return new BufferedCharReader() {
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
try {
|
||||
int i = supplier.getAsInt();
|
||||
if (i < 0 || i > Character.MAX_VALUE) {
|
||||
return DONE;
|
||||
} else {
|
||||
return (char) i;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static CharReader wrap(CharacterIterator it) {
|
||||
return new BufferedCharReader() {
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
char result = it.current();
|
||||
it.next();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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 wrapDefaultCS(InputStream is) {
|
||||
return wrap(new InputStreamReader(is));
|
||||
}
|
||||
|
||||
public static CharReader wrapUTF8(InputStream is) {
|
||||
return wrap(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,70 +1,71 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public class ReaderCharReader extends BufferedCharReader {
|
||||
|
||||
private final Reader src;
|
||||
private IOException lastException = null;
|
||||
|
||||
public ReaderCharReader(Reader src) {
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChar()
|
||||
*/
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
try {
|
||||
return (char) src.read(); // Handles DONE correctly
|
||||
} catch (IOException e) {
|
||||
lastException = e;
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChars(char[], int, int)
|
||||
*/
|
||||
@Override
|
||||
protected int pullChars(char[] buffer, int offset, int length) {
|
||||
try {
|
||||
return src.read(buffer, offset, length);
|
||||
} catch (IOException e) {
|
||||
lastException = e;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the exception
|
||||
*/
|
||||
@Override
|
||||
public IOException getLastException() {
|
||||
return lastException;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public class ReaderCharReader extends BufferedCharReader {
|
||||
|
||||
private final Reader src;
|
||||
private IOException lastException = null;
|
||||
|
||||
public ReaderCharReader(Reader src) {
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChar()
|
||||
*/
|
||||
@Override
|
||||
protected char pullChar() {
|
||||
try {
|
||||
return (char) src.read(); // Handles DONE correctly
|
||||
} catch (IOException e) {
|
||||
lastException = e;
|
||||
return DONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.BufferedCharReader#pullChars(char[],
|
||||
* int, int)
|
||||
*/
|
||||
@Override
|
||||
protected int pullChars(char[] buffer, int offset, int length) {
|
||||
try {
|
||||
return src.read(buffer, offset, length);
|
||||
} catch (IOException e) {
|
||||
lastException = e;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the exception
|
||||
*/
|
||||
@Override
|
||||
public IOException getLastException() {
|
||||
return lastException;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,65 +1,68 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public class StringCharReader extends AbstractCharReader {
|
||||
|
||||
private final String str;
|
||||
private final int offset;
|
||||
private final int length;
|
||||
|
||||
public StringCharReader(String str, int offset, int length) {
|
||||
this.str = Objects.requireNonNull(str, "str");
|
||||
|
||||
if (length < 0)
|
||||
length = str.length();
|
||||
|
||||
int end = offset + length;
|
||||
if (end > str.length() || offset < 0)
|
||||
throw new IllegalArgumentException("String contains [0; " + str.length() + "), requested [" + offset + "; " + end + ")");
|
||||
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#current()
|
||||
*/
|
||||
@Override
|
||||
public char current() {
|
||||
if (position >= length) 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() {
|
||||
return length - position;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.chars.reader;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public class StringCharReader extends AbstractCharReader {
|
||||
|
||||
private final String str;
|
||||
private final int offset;
|
||||
private final int length;
|
||||
|
||||
public StringCharReader(String str, int offset, int length) {
|
||||
this.str = Objects.requireNonNull(str, "str");
|
||||
|
||||
if (length < 0)
|
||||
length = str.length();
|
||||
|
||||
int end = offset + length;
|
||||
if (end > str.length() || offset < 0)
|
||||
throw new IllegalArgumentException(
|
||||
"String contains [0; " + str.length() + "), requested [" + offset + "; " + end + ")"
|
||||
);
|
||||
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ru.windcorp.jputil.chars.reader.CharReader#current()
|
||||
*/
|
||||
@Override
|
||||
public char current() {
|
||||
if (position >= length)
|
||||
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() {
|
||||
return length - position;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,26 @@
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FloatSupplier {
|
||||
|
||||
float getAsFloat();
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface FloatSupplier {
|
||||
|
||||
float getAsFloat();
|
||||
|
||||
}
|
||||
|
@ -1,72 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingBiConsumer<T, U, E extends Exception> {
|
||||
|
||||
@FunctionalInterface
|
||||
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;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default BiConsumer<T, U> withHandler(BiConsumerHandler<? super T, ? super U, ? super E> handler) {
|
||||
return (t, u) -> {
|
||||
try {
|
||||
accept(t, u);
|
||||
} catch (RuntimeException e) {
|
||||
throw 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,
|
||||
ThrowingBiConsumer<? super T, ? super U, ? extends E> second) {
|
||||
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) {
|
||||
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) -> {
|
||||
first.accept(t, u);
|
||||
second.accept(t, u);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingBiConsumer<T, U, E extends Exception> {
|
||||
|
||||
@FunctionalInterface
|
||||
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;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default BiConsumer<T, U> withHandler(BiConsumerHandler<? super T, ? super U, ? super E> handler) {
|
||||
return (t, u) -> {
|
||||
try {
|
||||
accept(t, u);
|
||||
} catch (RuntimeException e) {
|
||||
throw 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,
|
||||
ThrowingBiConsumer<? super T, ? super U, ? extends E> second
|
||||
) {
|
||||
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
|
||||
) {
|
||||
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) -> {
|
||||
first.accept(t, u);
|
||||
second.accept(t, u);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,62 +1,72 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingConsumer<T, E extends Exception> {
|
||||
|
||||
void accept(T t) throws E;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Consumer<T> withHandler(BiConsumer<? super T, ? super E> handler) {
|
||||
return t -> {
|
||||
try {
|
||||
accept(t);
|
||||
} catch (RuntimeException e) {
|
||||
throw 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 -> {
|
||||
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) {
|
||||
return t -> {
|
||||
first.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);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingConsumer<T, E extends Exception> {
|
||||
|
||||
void accept(T t) throws E;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Consumer<T> withHandler(BiConsumer<? super T, ? super E> handler) {
|
||||
return t -> {
|
||||
try {
|
||||
accept(t);
|
||||
} catch (RuntimeException e) {
|
||||
throw 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 -> {
|
||||
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
|
||||
) {
|
||||
return t -> {
|
||||
first.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);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,73 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingFunction<T, R, E extends Exception> {
|
||||
|
||||
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) {
|
||||
return t -> {
|
||||
try {
|
||||
return apply(t);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
if (handler != null) handler.accept(t, (E) e);
|
||||
return value == null ? null : value.apply(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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, R value) {
|
||||
return withHandler(handler, t -> value);
|
||||
}
|
||||
|
||||
default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler) {
|
||||
return withHandler(handler, (Function<T, R>) null);
|
||||
}
|
||||
|
||||
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
|
||||
ThrowingFunction<? super T, I, ? extends E> first,
|
||||
ThrowingFunction<? super I, ? extends R, ? extends E> second) {
|
||||
return t -> second.apply(first.apply(t));
|
||||
}
|
||||
|
||||
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
|
||||
Function<? super T, I> first,
|
||||
ThrowingFunction<? super I, ? extends R, E> second) {
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingFunction<T, R, E extends Exception> {
|
||||
|
||||
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
|
||||
) {
|
||||
return t -> {
|
||||
try {
|
||||
return apply(t);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
if (handler != null)
|
||||
handler.accept(t, (E) e);
|
||||
return value == null ? null : value.apply(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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, R value) {
|
||||
return withHandler(handler, t -> value);
|
||||
}
|
||||
|
||||
default Function<T, R> withHandler(BiConsumer<? super T, ? super E> handler) {
|
||||
return withHandler(handler, (Function<T, R>) null);
|
||||
}
|
||||
|
||||
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
|
||||
ThrowingFunction<? super T, I, ? extends E> first,
|
||||
ThrowingFunction<? super I, ? extends R, ? extends E> second
|
||||
) {
|
||||
return t -> second.apply(first.apply(t));
|
||||
}
|
||||
|
||||
public static <T, R, I, E extends Exception> ThrowingFunction<T, R, E> compose(
|
||||
Function<? super T, I> first,
|
||||
ThrowingFunction<? super I, ? extends R, E> second
|
||||
) {
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,64 +1,65 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingRunnable<E extends Exception> {
|
||||
|
||||
void run() throws E;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Runnable withHandler(Consumer<? super E> handler) {
|
||||
return () -> {
|
||||
try {
|
||||
run();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
handler.accept((E) e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <E extends Exception> ThrowingRunnable<E> concat(
|
||||
ThrowingRunnable<? extends E> first,
|
||||
ThrowingRunnable<? extends E> second
|
||||
) {
|
||||
return () -> {
|
||||
first.run();
|
||||
second.run();
|
||||
};
|
||||
}
|
||||
|
||||
public static <E extends Exception> ThrowingRunnable<E> concat(Runnable first, ThrowingRunnable<E> second) {
|
||||
return () -> {
|
||||
first.run();
|
||||
second.run();
|
||||
};
|
||||
}
|
||||
|
||||
public static <E extends Exception> ThrowingRunnable<E> concat(ThrowingRunnable<E> first, Runnable second) {
|
||||
return () -> {
|
||||
first.run();
|
||||
second.run();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingRunnable<E extends Exception> {
|
||||
|
||||
void run() throws E;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Runnable withHandler(Consumer<? super E> handler) {
|
||||
return () -> {
|
||||
try {
|
||||
run();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
handler.accept((E) e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <E extends Exception> ThrowingRunnable<E> concat(
|
||||
ThrowingRunnable<? extends E> first,
|
||||
ThrowingRunnable<? extends E> second
|
||||
) {
|
||||
return () -> {
|
||||
first.run();
|
||||
second.run();
|
||||
};
|
||||
}
|
||||
|
||||
public static <E extends Exception> ThrowingRunnable<E> concat(Runnable first, ThrowingRunnable<E> second) {
|
||||
return () -> {
|
||||
first.run();
|
||||
second.run();
|
||||
};
|
||||
}
|
||||
|
||||
public static <E extends Exception> ThrowingRunnable<E> concat(ThrowingRunnable<E> first, Runnable second) {
|
||||
return () -> {
|
||||
first.run();
|
||||
second.run();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,50 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingSupplier<T, E extends Exception> {
|
||||
|
||||
T get() throws E;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Supplier<T> withHandler(Consumer<? super E> handler, Supplier<? extends T> value) {
|
||||
return () -> {
|
||||
try {
|
||||
return get();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
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) {
|
||||
return withHandler(handler, (Supplier<T>) null);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.functions;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ThrowingSupplier<T, E extends Exception> {
|
||||
|
||||
T get() throws E;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default Supplier<T> withHandler(Consumer<? super E> handler, Supplier<? extends T> value) {
|
||||
return () -> {
|
||||
try {
|
||||
return get();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
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) {
|
||||
return withHandler(handler, (Supplier<T>) null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,47 +1,48 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class ArrayIterator<E> implements Iterator<E> {
|
||||
|
||||
private final E[] array;
|
||||
private int next;
|
||||
|
||||
@SafeVarargs
|
||||
public ArrayIterator(E... array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next < array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
try {
|
||||
return array[next++];
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class ArrayIterator<E> implements Iterator<E> {
|
||||
|
||||
private final E[] array;
|
||||
private int next;
|
||||
|
||||
@SafeVarargs
|
||||
public ArrayIterator(E... array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next < array.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
try {
|
||||
return array[next++];
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,61 +1,61 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*
|
||||
*/
|
||||
public class FunctionIterator<T, E> implements Iterator<E> {
|
||||
|
||||
private final Iterator<T> parent;
|
||||
private final Function<T, E> function;
|
||||
|
||||
public FunctionIterator(Iterator<T> parent, Function<T, E> function) {
|
||||
this.parent = parent;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return parent.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
@Override
|
||||
public E next() {
|
||||
return function.apply(parent.next());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
@Override
|
||||
public void remove() {
|
||||
parent.remove();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author Javapony
|
||||
*/
|
||||
public class FunctionIterator<T, E> implements Iterator<E> {
|
||||
|
||||
private final Iterator<T> parent;
|
||||
private final Function<T, E> function;
|
||||
|
||||
public FunctionIterator(Iterator<T> parent, Function<T, E> function) {
|
||||
this.parent = parent;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return parent.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
@Override
|
||||
public E next() {
|
||||
return function.apply(parent.next());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
@Override
|
||||
public void remove() {
|
||||
parent.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,60 +1,62 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class PeekingIterator<E> implements Iterator<E> {
|
||||
|
||||
private final Iterator<? extends E> source;
|
||||
private E next = null;
|
||||
|
||||
public PeekingIterator(Iterator<? extends E> source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != null || source.hasNext();
|
||||
}
|
||||
|
||||
public E peek() {
|
||||
if (next == null) {
|
||||
if (source.hasNext()) {
|
||||
next = source.next();
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
// SonarLint: "Iterator.next()" methods should throw "NoSuchElementException" (java:S2272)
|
||||
// peek() throws NoSuchElementException as expected
|
||||
@SuppressWarnings("squid:S2272")
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
E element = peek();
|
||||
next = null;
|
||||
return element;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class PeekingIterator<E> implements Iterator<E> {
|
||||
|
||||
private final Iterator<? extends E> source;
|
||||
private E next = null;
|
||||
|
||||
public PeekingIterator(Iterator<? extends E> source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next != null || source.hasNext();
|
||||
}
|
||||
|
||||
public E peek() {
|
||||
if (next == null) {
|
||||
if (source.hasNext()) {
|
||||
next = source.next();
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
// SonarLint: "Iterator.next()" methods should throw
|
||||
// "NoSuchElementException" (java:S2272)
|
||||
// peek() throws NoSuchElementException as expected
|
||||
@SuppressWarnings("squid:S2272")
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
E element = peek();
|
||||
next = null;
|
||||
return element;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,67 +1,70 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class RangeIterator<E> implements Iterator<E> {
|
||||
|
||||
private final Iterator<E> parent;
|
||||
private final int from;
|
||||
private final int amount;
|
||||
|
||||
private int nextIndex = 0;
|
||||
|
||||
public RangeIterator(Iterator<E> iterator, int from, int amount) {
|
||||
this.parent = iterator;
|
||||
this.from = from;
|
||||
this.amount = amount < 0 ? Integer.MAX_VALUE : amount;
|
||||
}
|
||||
|
||||
public RangeIterator(Iterator<E> iterator, int from) {
|
||||
this(iterator, from, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
update();
|
||||
return nextIndex < from + amount && parent.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
update();
|
||||
if (nextIndex >= from + amount) {
|
||||
throw new NoSuchElementException("RangeIterator about to retrieve element " + nextIndex
|
||||
+ " which exceeds upper boundary " + (from + amount));
|
||||
}
|
||||
|
||||
E result = parent.next();
|
||||
nextIndex++;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
while (nextIndex < from && parent.hasNext()) {
|
||||
parent.next();
|
||||
nextIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class RangeIterator<E> implements Iterator<E> {
|
||||
|
||||
private final Iterator<E> parent;
|
||||
private final int from;
|
||||
private final int amount;
|
||||
|
||||
private int nextIndex = 0;
|
||||
|
||||
public RangeIterator(Iterator<E> iterator, int from, int amount) {
|
||||
this.parent = iterator;
|
||||
this.from = from;
|
||||
this.amount = amount < 0 ? Integer.MAX_VALUE : amount;
|
||||
}
|
||||
|
||||
public RangeIterator(Iterator<E> iterator, int from) {
|
||||
this(iterator, from, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
update();
|
||||
return nextIndex < from + amount && parent.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
update();
|
||||
if (nextIndex >= from + amount) {
|
||||
throw new NoSuchElementException(
|
||||
"RangeIterator about to retrieve element " + nextIndex
|
||||
+ " which exceeds upper boundary " + (from + amount)
|
||||
);
|
||||
}
|
||||
|
||||
E result = parent.next();
|
||||
nextIndex++;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
while (nextIndex < from && parent.hasNext()) {
|
||||
parent.next();
|
||||
nextIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,70 +1,72 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class Reiterator<E> implements Iterable<E> {
|
||||
|
||||
private class ReiteratorIterator implements Iterator<E> {
|
||||
|
||||
int index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
synchronized (source) {
|
||||
if (index >= data.size()) {
|
||||
if (!source.hasNext()) {
|
||||
return false;
|
||||
} else {
|
||||
data.add(source.next());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
E result;
|
||||
synchronized (source) {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
result = data.get(index);
|
||||
}
|
||||
index++;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final Iterator<E> source;
|
||||
private final ArrayList<E> data = new ArrayList<>();
|
||||
|
||||
public Reiterator(Iterator<E> source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new ReiteratorIterator();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.iterators;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class Reiterator<E> implements Iterable<E> {
|
||||
|
||||
private class ReiteratorIterator implements Iterator<E> {
|
||||
|
||||
int index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
synchronized (source) {
|
||||
if (index >= data.size()) {
|
||||
if (!source.hasNext()) {
|
||||
return false;
|
||||
} else {
|
||||
data.add(source.next());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
E result;
|
||||
synchronized (source) {
|
||||
if (!hasNext())
|
||||
throw new NoSuchElementException();
|
||||
result = data.get(index);
|
||||
}
|
||||
index++;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final Iterator<E> source;
|
||||
private final ArrayList<E> data = new ArrayList<>();
|
||||
|
||||
public Reiterator(Iterator<E> source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new ReiteratorIterator();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,39 +1,40 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
public abstract class AbstractSelectorOperator implements SelectorOperator {
|
||||
|
||||
private final String[] names;
|
||||
|
||||
public AbstractSelectorOperator(String[] names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesName(String name) {
|
||||
for (String n : names) {
|
||||
if (n.equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
public abstract class AbstractSelectorOperator implements SelectorOperator {
|
||||
|
||||
private final String[] names;
|
||||
|
||||
public AbstractSelectorOperator(String[] names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesName(String name) {
|
||||
for (String n : names) {
|
||||
if (n.equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,57 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
import ru.windcorp.jputil.chars.StringUtil;
|
||||
|
||||
public abstract class NamedParameterizedSelector<T> extends NamedSelector<T> {
|
||||
|
||||
private final char separator;
|
||||
private String givenName;
|
||||
|
||||
public NamedParameterizedSelector(char separator, String... names) {
|
||||
super(names);
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Selector<T> derive(String name) throws SyntaxException {
|
||||
String[] parts = StringUtil.split(name, separator, 2);
|
||||
|
||||
if (parts[1] == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!matchesName(parts[0])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NamedParameterizedSelector<T> selector = deriveImpl(parts[1]);
|
||||
selector.givenName = name;
|
||||
return selector;
|
||||
}
|
||||
|
||||
protected abstract NamedParameterizedSelector<T> deriveImpl(String param) throws SyntaxException;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return givenName;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
import ru.windcorp.jputil.chars.StringUtil;
|
||||
|
||||
public abstract class NamedParameterizedSelector<T> extends NamedSelector<T> {
|
||||
|
||||
private final char separator;
|
||||
private String givenName;
|
||||
|
||||
public NamedParameterizedSelector(char separator, String... names) {
|
||||
super(names);
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Selector<T> derive(String name) throws SyntaxException {
|
||||
String[] parts = StringUtil.split(name, separator, 2);
|
||||
|
||||
if (parts[1] == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!matchesName(parts[0])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NamedParameterizedSelector<T> selector = deriveImpl(parts[1]);
|
||||
selector.givenName = name;
|
||||
return selector;
|
||||
}
|
||||
|
||||
protected abstract NamedParameterizedSelector<T> deriveImpl(String param) throws SyntaxException;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return givenName;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,50 +1,51 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
|
||||
public abstract class NamedSelector<T> implements Selector<T> {
|
||||
|
||||
private final String[] names;
|
||||
|
||||
public NamedSelector(String... names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
public boolean matchesName(String name) {
|
||||
for (String n : names) {
|
||||
if (n.equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Selector<T> derive(String name) throws SyntaxException {
|
||||
return matchesName(name) ? this : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return names[0];
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
|
||||
public abstract class NamedSelector<T> implements Selector<T> {
|
||||
|
||||
private final String[] names;
|
||||
|
||||
public NamedSelector(String... names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
public boolean matchesName(String name) {
|
||||
for (String n : names) {
|
||||
if (n.equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Selector<T> derive(String name) throws SyntaxException {
|
||||
return matchesName(name) ? this : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return names[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorAnd extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorAnd(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) && arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorAnd extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorAnd(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) && arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorExclude extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorExclude(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) && !arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorExclude extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorExclude(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) && !arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,34 +1,35 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorNot extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorNot(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
stack.push(stack.pop().negate());
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorNot extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorNot(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
stack.push(stack.pop().negate());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorOr extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorOr(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) || arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorOr extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorOr(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) || arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorXor extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorXor(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) != arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class OperatorXor extends AbstractSelectorOperator {
|
||||
|
||||
public OperatorXor(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void process(Deque<Predicate<T>> stack) {
|
||||
Predicate<T> arg2 = stack.pop();
|
||||
Predicate<T> arg1 = stack.pop();
|
||||
stack.push(obj -> arg1.test(obj) != arg2.test(obj));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class PredicateWrapper<T> extends NamedSelector<T> {
|
||||
|
||||
private final Predicate<? super T> predicate;
|
||||
|
||||
public PredicateWrapper(String name, Predicate<? super T> predicate) {
|
||||
super(name);
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(T obj) {
|
||||
return predicate.test(obj);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class PredicateWrapper<T> extends NamedSelector<T> {
|
||||
|
||||
private final Predicate<? super T> predicate;
|
||||
|
||||
public PredicateWrapper(String name, Predicate<? super T> predicate) {
|
||||
super(name);
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(T obj) {
|
||||
return predicate.test(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,28 +1,29 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
|
||||
public interface Selector<T> extends Predicate<T> {
|
||||
|
||||
public Selector<T> derive(String name) throws SyntaxException;
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
|
||||
public interface Selector<T> extends Predicate<T> {
|
||||
|
||||
public Selector<T> derive(String name) throws SyntaxException;
|
||||
|
||||
}
|
||||
|
@ -1,29 +1,30 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface SelectorOperator {
|
||||
|
||||
public <T> void process(Deque<Predicate<T>> stack);
|
||||
|
||||
public boolean matchesName(String name);
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface SelectorOperator {
|
||||
|
||||
public <T> void process(Deque<Predicate<T>> stack);
|
||||
|
||||
public boolean matchesName(String name);
|
||||
|
||||
}
|
||||
|
@ -1,176 +1,175 @@
|
||||
/*******************************************************************************
|
||||
* JPUtil
|
||||
* Copyright (C) 2019 Javapony/OLEGSHA
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
import ru.windcorp.jputil.iterators.PeekingIterator;
|
||||
|
||||
public class SelectorSystem<T> {
|
||||
|
||||
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<SelectorOperator> operators =
|
||||
Collections.synchronizedCollection(new ArrayList<SelectorOperator>());
|
||||
|
||||
private String stackPrefix = null;
|
||||
|
||||
public Collection<Selector<T>> getSelectors() {
|
||||
return this.selectors;
|
||||
}
|
||||
|
||||
public Collection<SelectorOperator> getSelectorOperators() {
|
||||
return this.operators;
|
||||
}
|
||||
|
||||
public String getStackPrefix() {
|
||||
return stackPrefix;
|
||||
}
|
||||
|
||||
public SelectorSystem<T> setStackPrefix(String stackPrefix) {
|
||||
this.stackPrefix = stackPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectorSystem<T> add(Selector<T> selector) {
|
||||
getSelectors().add(selector);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectorSystem<T> add(SelectorOperator operator) {
|
||||
getSelectorOperators().add(operator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Predicate<T> parse(Iterator<String> tokens) throws SyntaxException {
|
||||
PeekingIterator<String> peeker = new PeekingIterator<>(tokens);
|
||||
|
||||
if (getStackPrefix() != null && peeker.hasNext() && getStackPrefix().equals(peeker.peek())) {
|
||||
peeker.next();
|
||||
return parseStack(peeker);
|
||||
}
|
||||
|
||||
Deque<Predicate<T>> stack = new LinkedList<>();
|
||||
|
||||
synchronized (getSelectorOperators()) {
|
||||
synchronized (getSelectors()) {
|
||||
|
||||
while (peeker.hasNext()) {
|
||||
parseToken(stack, peeker);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return compress(stack);
|
||||
}
|
||||
|
||||
private void parseToken(Deque<Predicate<T>> stack, Iterator<String> tokens) throws SyntaxException {
|
||||
|
||||
if (!tokens.hasNext()) {
|
||||
throw new SyntaxException("Not enough tokens");
|
||||
}
|
||||
String token = tokens.next();
|
||||
|
||||
for (SelectorOperator operator : getSelectorOperators()) {
|
||||
if (operator.matchesName(token.toLowerCase())) {
|
||||
parseToken(stack, tokens);
|
||||
operator.process(stack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Selector<T> tmp;
|
||||
for (Selector<T> selector : getSelectors()) {
|
||||
if ((tmp = selector.derive(token)) != null) {
|
||||
stack.push(tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SyntaxException("Unknown token \"" + token + "\"");
|
||||
}
|
||||
|
||||
public Predicate<T> parseStack(Iterator<String> tokens) throws SyntaxException {
|
||||
Deque<Predicate<T>> stack = new LinkedList<>();
|
||||
|
||||
String token;
|
||||
|
||||
synchronized (getSelectorOperators()) {
|
||||
synchronized (getSelectors()) {
|
||||
|
||||
tokenCycle:
|
||||
while (tokens.hasNext()) {
|
||||
token = tokens.next();
|
||||
|
||||
for (SelectorOperator operator : getSelectorOperators()) {
|
||||
if (operator.matchesName(token.toLowerCase())) {
|
||||
operator.process(stack);
|
||||
continue tokenCycle;
|
||||
}
|
||||
}
|
||||
|
||||
for (Selector<T> selector : getSelectors()) {
|
||||
Selector<T> tmp;
|
||||
if ((tmp = selector.derive(token)) != null) {
|
||||
stack.push(tmp);
|
||||
continue tokenCycle;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SyntaxException("Unknown token \"" + token + "\"");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return compress(stack);
|
||||
}
|
||||
|
||||
private Predicate<T> compress(Deque<Predicate<T>> stack) throws SyntaxException {
|
||||
if (stack.isEmpty()) {
|
||||
throw new SyntaxException("Stack is empty");
|
||||
}
|
||||
|
||||
if (stack.size() == 1) {
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
return obj -> {
|
||||
for (Predicate<? super T> predicate : stack) {
|
||||
if (predicate.test(obj)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JPUtil
|
||||
* Copyright (C) 2019-2021 OLEGSHA/Javapony and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.jputil.selectors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.jputil.SyntaxException;
|
||||
import ru.windcorp.jputil.iterators.PeekingIterator;
|
||||
|
||||
public class SelectorSystem<T> {
|
||||
|
||||
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<SelectorOperator> operators = Collections
|
||||
.synchronizedCollection(new ArrayList<SelectorOperator>());
|
||||
|
||||
private String stackPrefix = null;
|
||||
|
||||
public Collection<Selector<T>> getSelectors() {
|
||||
return this.selectors;
|
||||
}
|
||||
|
||||
public Collection<SelectorOperator> getSelectorOperators() {
|
||||
return this.operators;
|
||||
}
|
||||
|
||||
public String getStackPrefix() {
|
||||
return stackPrefix;
|
||||
}
|
||||
|
||||
public SelectorSystem<T> setStackPrefix(String stackPrefix) {
|
||||
this.stackPrefix = stackPrefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectorSystem<T> add(Selector<T> selector) {
|
||||
getSelectors().add(selector);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectorSystem<T> add(SelectorOperator operator) {
|
||||
getSelectorOperators().add(operator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Predicate<T> parse(Iterator<String> tokens) throws SyntaxException {
|
||||
PeekingIterator<String> peeker = new PeekingIterator<>(tokens);
|
||||
|
||||
if (getStackPrefix() != null && peeker.hasNext() && getStackPrefix().equals(peeker.peek())) {
|
||||
peeker.next();
|
||||
return parseStack(peeker);
|
||||
}
|
||||
|
||||
Deque<Predicate<T>> stack = new LinkedList<>();
|
||||
|
||||
synchronized (getSelectorOperators()) {
|
||||
synchronized (getSelectors()) {
|
||||
|
||||
while (peeker.hasNext()) {
|
||||
parseToken(stack, peeker);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return compress(stack);
|
||||
}
|
||||
|
||||
private void parseToken(Deque<Predicate<T>> stack, Iterator<String> tokens) throws SyntaxException {
|
||||
|
||||
if (!tokens.hasNext()) {
|
||||
throw new SyntaxException("Not enough tokens");
|
||||
}
|
||||
String token = tokens.next();
|
||||
|
||||
for (SelectorOperator operator : getSelectorOperators()) {
|
||||
if (operator.matchesName(token.toLowerCase())) {
|
||||
parseToken(stack, tokens);
|
||||
operator.process(stack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Selector<T> tmp;
|
||||
for (Selector<T> selector : getSelectors()) {
|
||||
if ((tmp = selector.derive(token)) != null) {
|
||||
stack.push(tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SyntaxException("Unknown token \"" + token + "\"");
|
||||
}
|
||||
|
||||
public Predicate<T> parseStack(Iterator<String> tokens) throws SyntaxException {
|
||||
Deque<Predicate<T>> stack = new LinkedList<>();
|
||||
|
||||
String token;
|
||||
|
||||
synchronized (getSelectorOperators()) {
|
||||
synchronized (getSelectors()) {
|
||||
|
||||
tokenCycle: while (tokens.hasNext()) {
|
||||
token = tokens.next();
|
||||
|
||||
for (SelectorOperator operator : getSelectorOperators()) {
|
||||
if (operator.matchesName(token.toLowerCase())) {
|
||||
operator.process(stack);
|
||||
continue tokenCycle;
|
||||
}
|
||||
}
|
||||
|
||||
for (Selector<T> selector : getSelectors()) {
|
||||
Selector<T> tmp;
|
||||
if ((tmp = selector.derive(token)) != null) {
|
||||
stack.push(tmp);
|
||||
continue tokenCycle;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SyntaxException("Unknown token \"" + token + "\"");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return compress(stack);
|
||||
}
|
||||
|
||||
private Predicate<T> compress(Deque<Predicate<T>> stack) throws SyntaxException {
|
||||
if (stack.isEmpty()) {
|
||||
throw new SyntaxException("Stack is empty");
|
||||
}
|
||||
|
||||
if (stack.size() == 1) {
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
return obj -> {
|
||||
for (Predicate<? super T> predicate : stack) {
|
||||
if (predicate.test(obj)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,22 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
public class Progressia {
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class Progressia {
|
||||
|
||||
}
|
||||
|
@ -1,51 +1,52 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer;
|
||||
import ru.windcorp.progressia.common.util.crash.providers.*;
|
||||
|
||||
public class ProgressiaLauncher {
|
||||
|
||||
public static String[] arguments;
|
||||
|
||||
public static void launch(String[] args, Proxy proxy) {
|
||||
arguments = args.clone();
|
||||
setupCrashReports();
|
||||
proxy.initialize();
|
||||
}
|
||||
|
||||
private static void setupCrashReports() {
|
||||
// Context providers
|
||||
CrashReports.registerProvider(new OSContextProvider());
|
||||
CrashReports.registerProvider(new RAMContextProvider());
|
||||
CrashReports.registerProvider(new JavaVersionContextProvider());
|
||||
CrashReports.registerProvider(new OpenALContextProvider());
|
||||
CrashReports.registerProvider(new ArgsContextProvider());
|
||||
CrashReports.registerProvider(new LanguageContextProvider());
|
||||
CrashReports.registerProvider(new StackTraceProvider());
|
||||
// Analyzers
|
||||
CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer());
|
||||
|
||||
Thread.setDefaultUncaughtExceptionHandler((Thread thread, Throwable t)-> {
|
||||
CrashReports.crash(t, "Uncaught exception in thread %s", thread.getName());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer;
|
||||
import ru.windcorp.progressia.common.util.crash.providers.*;
|
||||
|
||||
public class ProgressiaLauncher {
|
||||
|
||||
public static String[] arguments;
|
||||
|
||||
public static void launch(String[] args, Proxy proxy) {
|
||||
arguments = args.clone();
|
||||
setupCrashReports();
|
||||
proxy.initialize();
|
||||
}
|
||||
|
||||
private static void setupCrashReports() {
|
||||
// Context providers
|
||||
CrashReports.registerProvider(new OSContextProvider());
|
||||
CrashReports.registerProvider(new RAMContextProvider());
|
||||
CrashReports.registerProvider(new JavaVersionContextProvider());
|
||||
CrashReports.registerProvider(new OpenALContextProvider());
|
||||
CrashReports.registerProvider(new ArgsContextProvider());
|
||||
CrashReports.registerProvider(new LanguageContextProvider());
|
||||
CrashReports.registerProvider(new ScreenContextProvider());
|
||||
// Analyzers
|
||||
CrashReports.registerAnalyzer(new OutOfMemoryAnalyzer());
|
||||
|
||||
Thread.setDefaultUncaughtExceptionHandler((Thread thread, Throwable t) -> {
|
||||
CrashReports.crash(t, "Uncaught exception in thread %s", thread.getName());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,24 +1,25 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
public interface Proxy {
|
||||
|
||||
void initialize();
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface Proxy {
|
||||
|
||||
void initialize();
|
||||
|
||||
}
|
||||
|
@ -1,59 +1,79 @@
|
||||
package ru.windcorp.progressia.client;
|
||||
|
||||
import ru.windcorp.progressia.client.comms.DefaultClientCommsListener;
|
||||
import ru.windcorp.progressia.client.comms.ServerCommsChannel;
|
||||
import ru.windcorp.progressia.client.graphics.world.Camera;
|
||||
import ru.windcorp.progressia.client.graphics.world.EntityAnchor;
|
||||
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
|
||||
import ru.windcorp.progressia.client.world.WorldRender;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||
|
||||
public class Client {
|
||||
|
||||
private final WorldRender world;
|
||||
private final LocalPlayer localPlayer = new LocalPlayer(this);
|
||||
|
||||
private final Camera camera = new Camera((float) Math.toRadians(70));
|
||||
|
||||
private final ServerCommsChannel comms;
|
||||
|
||||
public Client(WorldData world, ServerCommsChannel comms) {
|
||||
this.world = new WorldRender(world, this);
|
||||
this.comms = comms;
|
||||
|
||||
comms.addListener(new DefaultClientCommsListener(this));
|
||||
}
|
||||
|
||||
public WorldRender getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public LocalPlayer getLocalPlayer() {
|
||||
return localPlayer;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
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)
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.client.comms.DefaultClientCommsListener;
|
||||
import ru.windcorp.progressia.client.comms.ServerCommsChannel;
|
||||
import ru.windcorp.progressia.client.graphics.world.Camera;
|
||||
import ru.windcorp.progressia.client.graphics.world.EntityAnchor;
|
||||
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
|
||||
import ru.windcorp.progressia.client.world.WorldRender;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||
|
||||
public class Client {
|
||||
|
||||
private final WorldRender world;
|
||||
private final LocalPlayer localPlayer = new LocalPlayer(this);
|
||||
|
||||
private final Camera camera = new Camera((float) Math.toRadians(70));
|
||||
|
||||
private final ServerCommsChannel comms;
|
||||
|
||||
public Client(WorldData world, ServerCommsChannel comms) {
|
||||
this.world = new WorldRender(world, this);
|
||||
this.comms = comms;
|
||||
|
||||
comms.addListener(new DefaultClientCommsListener(this));
|
||||
}
|
||||
|
||||
public WorldRender getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public LocalPlayer getLocalPlayer() {
|
||||
return localPlayer;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
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)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,54 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.Proxy;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend;
|
||||
import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue;
|
||||
import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram;
|
||||
import ru.windcorp.progressia.client.graphics.font.GNUUnifontLoader;
|
||||
import ru.windcorp.progressia.client.graphics.font.Typefaces;
|
||||
import ru.windcorp.progressia.client.graphics.texture.Atlases;
|
||||
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.server.ServerState;
|
||||
import ru.windcorp.progressia.test.TestContent;
|
||||
|
||||
public class ClientProxy implements Proxy {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
GraphicsBackend.initialize();
|
||||
try {
|
||||
RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init);
|
||||
RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init);
|
||||
RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz"))));
|
||||
} catch (InterruptedException e) {
|
||||
throw CrashReports.report(e, "ClientProxy failed");
|
||||
}
|
||||
|
||||
TestContent.registerContent();
|
||||
|
||||
Atlases.loadAllAtlases();
|
||||
|
||||
ServerState.startServer();
|
||||
ClientState.connectToLocalServer();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.Proxy;
|
||||
import ru.windcorp.progressia.client.audio.AudioSystem;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend;
|
||||
import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue;
|
||||
import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram;
|
||||
import ru.windcorp.progressia.client.graphics.font.GNUUnifontLoader;
|
||||
import ru.windcorp.progressia.client.graphics.font.Typefaces;
|
||||
import ru.windcorp.progressia.client.graphics.texture.Atlases;
|
||||
import ru.windcorp.progressia.client.graphics.world.WorldRenderProgram;
|
||||
import ru.windcorp.progressia.client.localization.Localizer;
|
||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.server.ServerState;
|
||||
import ru.windcorp.progressia.test.TestContent;
|
||||
import ru.windcorp.progressia.test.TestMusicPlayer;
|
||||
|
||||
public class ClientProxy implements Proxy {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
GraphicsBackend.initialize();
|
||||
try {
|
||||
RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init);
|
||||
RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init);
|
||||
RenderTaskQueue.waitAndInvoke(
|
||||
() -> Typefaces
|
||||
.setDefault(GNUUnifontLoader.load(ResourceManager.getResource("assets/unifont-13.0.03.hex.gz")))
|
||||
);
|
||||
} catch (InterruptedException e) {
|
||||
throw CrashReports.report(e, "ClientProxy failed");
|
||||
}
|
||||
|
||||
Localizer.getInstance().setLanguage("en-US");
|
||||
|
||||
TestContent.registerContent();
|
||||
|
||||
Atlases.loadAllAtlases();
|
||||
|
||||
AudioSystem.initialize();
|
||||
|
||||
ServerState.startServer();
|
||||
ClientState.connectToLocalServer();
|
||||
|
||||
TestMusicPlayer.start();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,46 +1,65 @@
|
||||
package ru.windcorp.progressia.client;
|
||||
|
||||
import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.server.ServerState;
|
||||
import ru.windcorp.progressia.test.LayerTestGUI;
|
||||
import ru.windcorp.progressia.test.LayerTestUI;
|
||||
import ru.windcorp.progressia.test.TestContent;
|
||||
|
||||
public class ClientState {
|
||||
|
||||
private static Client instance;
|
||||
|
||||
public static Client getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void setInstance(Client instance) {
|
||||
ClientState.instance = instance;
|
||||
}
|
||||
|
||||
public static void connectToLocalServer() {
|
||||
|
||||
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 LayerTestGUI());
|
||||
|
||||
}
|
||||
|
||||
private ClientState() {}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.server.ServerState;
|
||||
import ru.windcorp.progressia.test.LayerAbout;
|
||||
import ru.windcorp.progressia.test.LayerTestUI;
|
||||
import ru.windcorp.progressia.test.TestContent;
|
||||
|
||||
public class ClientState {
|
||||
|
||||
private static Client instance;
|
||||
|
||||
public static Client getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void setInstance(Client instance) {
|
||||
ClientState.instance = instance;
|
||||
}
|
||||
|
||||
public static void connectToLocalServer() {
|
||||
|
||||
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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,28 +1,29 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.ProgressiaLauncher;
|
||||
|
||||
public class ProgressiaClientMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ProgressiaLauncher.launch(args, new ClientProxy());
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.ProgressiaLauncher;
|
||||
|
||||
public class ProgressiaClientMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ProgressiaLauncher.launch(args, new ClientProxy());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
public enum AudioFormat {
|
||||
MONO, STEREO
|
||||
MONO, STEREO
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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.SoundType;
|
||||
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.ALC10.*;
|
||||
@ -22,12 +41,11 @@ public class AudioManager {
|
||||
|
||||
private static List<Speaker> soundSpeakers = new ArrayList<>(SOUNDS_NUM);
|
||||
private static Speaker musicSpeaker;
|
||||
private static ArrayList<SoundType> soundsBuffer = new ArrayList<>();
|
||||
|
||||
public static void initAL() {
|
||||
String defaultDeviceName = alcGetString(
|
||||
0,
|
||||
ALC_DEFAULT_DEVICE_SPECIFIER
|
||||
0,
|
||||
ALC_DEFAULT_DEVICE_SPECIFIER
|
||||
);
|
||||
|
||||
device = alcOpenDevice(defaultDeviceName);
|
||||
@ -57,37 +75,27 @@ public class AudioManager {
|
||||
lastSoundIndex = 0;
|
||||
}
|
||||
speaker = soundSpeakers.get(lastSoundIndex);
|
||||
} while (speaker.getState()
|
||||
.equals(Speaker.State.PLAYING_LOOP));
|
||||
} while (
|
||||
speaker.getState()
|
||||
.equals(Speaker.State.PLAYING_LOOP)
|
||||
);
|
||||
return speaker;
|
||||
}
|
||||
|
||||
private static SoundType findSoundType(String soundID) throws Exception {
|
||||
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) {
|
||||
public static Speaker initSpeaker(SoundType st) {
|
||||
Speaker speaker = getLastSpeaker();
|
||||
try {
|
||||
findSoundType(soundID).initSpeaker(speaker);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
st.initSpeaker(speaker);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
return speaker;
|
||||
}
|
||||
|
||||
public static Speaker initMusicSpeaker(String soundID) {
|
||||
public static Speaker initMusicSpeaker(SoundType st) {
|
||||
try {
|
||||
findSoundType(soundID).initSpeaker(musicSpeaker);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
st.initSpeaker(musicSpeaker);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
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) {
|
||||
soundsBuffer.add(AudioReader.readAsMono(path, id));
|
||||
} else
|
||||
{
|
||||
soundsBuffer.add(AudioReader.readAsStereo(path, id));
|
||||
AudioRegistry.getInstance().register(AudioReader.readAsMono(resource, id));
|
||||
} else {
|
||||
AudioRegistry.getInstance().register(AudioReader.readAsStereo(resource, id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,8 +135,7 @@ public class AudioManager {
|
||||
return deviceCapabilities;
|
||||
}
|
||||
|
||||
public static void createBuffers()
|
||||
{
|
||||
public static void createBuffers() {
|
||||
for (int i = 0; i < SOUNDS_NUM; ++i) {
|
||||
soundSpeakers.add(new Speaker());
|
||||
}
|
||||
@ -141,4 +147,4 @@ public class AudioManager {
|
||||
return alGetString(AL11.AL_VERSION);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||
|
||||
public class AudioSystem {
|
||||
static public void initialize() {
|
||||
AudioManager.initAL();
|
||||
@ -9,8 +29,10 @@ public class AudioSystem {
|
||||
}
|
||||
|
||||
static void loadAudioData() {
|
||||
AudioManager.loadSound("assets/sounds/block_destroy_clap.ogg",
|
||||
"Progressia:BlockDestroy",
|
||||
AudioFormat.MONO);
|
||||
AudioManager.loadSound(
|
||||
ResourceManager.getResource("assets/sounds/block_destroy_clap.ogg"),
|
||||
"Progressia:BlockDestroy",
|
||||
AudioFormat.MONO
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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.common.util.namespaces.Namespaced;
|
||||
|
||||
public class Music extends Namespaced {
|
||||
private Vec3 position = new Vec3();
|
||||
private Vec3 velocity = new Vec3();
|
||||
private float pitch = 1.0f;
|
||||
private float gain = 1.0f;
|
||||
public class Music
|
||||
extends Sound {
|
||||
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
super(id);
|
||||
}
|
||||
public Music(String id, int timeLength, float pitch, float gain) {
|
||||
super(id, timeLength, new Vec3(), new Vec3(), pitch, gain);
|
||||
}
|
||||
|
||||
public Music(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 Music(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public void play(boolean loop)
|
||||
{
|
||||
Speaker speaker = AudioManager.initMusicSpeaker(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 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;
|
||||
}
|
||||
@Override
|
||||
protected Speaker initSpeaker() {
|
||||
return AudioManager.initMusicSpeaker(soundType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vec3 position) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
127
src/main/java/ru/windcorp/progressia/client/audio/Sound.java
Normal file
127
src/main/java/ru/windcorp/progressia/client/audio/Sound.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
@ -11,38 +29,41 @@ import static org.lwjgl.openal.AL10.*;
|
||||
|
||||
public class AudioReader {
|
||||
|
||||
private AudioReader() {}
|
||||
private AudioReader() {
|
||||
}
|
||||
|
||||
// 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 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, rawAudio, format,
|
||||
rateBuffer.get(0));
|
||||
return new SoundType(
|
||||
id,
|
||||
rawAudio,
|
||||
format,
|
||||
rateBuffer.get(0)
|
||||
);
|
||||
}
|
||||
|
||||
public static SoundType readAsMono(String path, String id) {
|
||||
return readAsSpecified(path, id, AL_FORMAT_MONO16);
|
||||
public static SoundType readAsMono(Resource resource, String id) {
|
||||
return readAsSpecified(resource, id, AL_FORMAT_MONO16);
|
||||
}
|
||||
|
||||
public static SoundType readAsStereo(String path,String id) {
|
||||
return readAsSpecified(path, id, AL_FORMAT_STEREO16);
|
||||
public static SoundType readAsStereo(Resource resource, String id) {
|
||||
return readAsSpecified(resource, id, AL_FORMAT_STEREO16);
|
||||
}
|
||||
|
||||
private static ShortBuffer decodeVorbis(
|
||||
Resource dataToDecode,
|
||||
IntBuffer channelsBuffer,
|
||||
IntBuffer rateBuffer
|
||||
Resource dataToDecode,
|
||||
IntBuffer channelsBuffer,
|
||||
IntBuffer rateBuffer
|
||||
) {
|
||||
return stb_vorbis_decode_memory(
|
||||
dataToDecode.readAsBytes(),
|
||||
channelsBuffer,
|
||||
rateBuffer
|
||||
dataToDecode.readAsBytes(),
|
||||
channelsBuffer,
|
||||
rateBuffer
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import glm.vec._3.Vec3;
|
||||
@ -12,7 +30,8 @@ public class Listener {
|
||||
|
||||
private static final Listener INSTANCE = new Listener();
|
||||
|
||||
private Listener() {}
|
||||
private Listener() {
|
||||
}
|
||||
|
||||
public static Listener getInstance() {
|
||||
return INSTANCE;
|
||||
@ -37,7 +56,7 @@ public class Listener {
|
||||
|
||||
if (wasInWorld) {
|
||||
velocity.set(camera.getLastAnchorPosition()).sub(position).div(
|
||||
(float) GraphicsInterface.getFrameLength()
|
||||
(float) GraphicsInterface.getFrameLength()
|
||||
);
|
||||
} else {
|
||||
// If !wasInWorld, previous position is nonsence. Assume 0.
|
||||
@ -72,9 +91,17 @@ public class Listener {
|
||||
private void applyParams() {
|
||||
alListener3f(AL_POSITION, position.x, position.y, position.z);
|
||||
alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z);
|
||||
alListenerfv(AL_ORIENTATION, new float[] {
|
||||
oriAt.x, oriAt.y, oriAt.z, oriUp.x, oriUp.y, oriUp.z
|
||||
});
|
||||
alListenerfv(
|
||||
AL_ORIENTATION,
|
||||
new float[] {
|
||||
oriAt.x,
|
||||
oriAt.y,
|
||||
oriAt.z,
|
||||
oriUp.x,
|
||||
oriUp.y,
|
||||
oriUp.z
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.lwjgl.openal.AL10;
|
||||
|
||||
import static org.lwjgl.openal.AL11.*;
|
||||
|
||||
public class SoundType extends Namespaced {
|
||||
@ -11,9 +32,14 @@ public class SoundType extends Namespaced {
|
||||
private int sampleRate;
|
||||
private int format;
|
||||
private int audioBuffer;
|
||||
private double duration;
|
||||
|
||||
public SoundType(String id, ShortBuffer rawAudio,
|
||||
int format, int sampleRate) {
|
||||
public SoundType(
|
||||
String id,
|
||||
ShortBuffer rawAudio,
|
||||
int format,
|
||||
int sampleRate
|
||||
) {
|
||||
super(id);
|
||||
this.rawAudio = rawAudio;
|
||||
this.sampleRate = sampleRate;
|
||||
@ -24,9 +50,14 @@ public class SoundType extends Namespaced {
|
||||
private void createAudioBuffer() {
|
||||
this.audioBuffer = alGenBuffers();
|
||||
alBufferData(audioBuffer, format, rawAudio, sampleRate);
|
||||
duration = rawAudio.limit() / (double) sampleRate / (format == AL10.AL_FORMAT_STEREO16 ? 2 : 1);
|
||||
}
|
||||
|
||||
public void initSpeaker(Speaker speaker) {
|
||||
speaker.setAudioData(audioBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public double getDuration() {
|
||||
return duration;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
import glm.vec._3.Vec3;
|
||||
@ -5,147 +23,146 @@ import static org.lwjgl.openal.AL11.*;
|
||||
|
||||
public class Speaker {
|
||||
|
||||
public enum State {
|
||||
NOT_PLAYING,
|
||||
PLAYING,
|
||||
PLAYING_LOOP
|
||||
}
|
||||
public enum State {
|
||||
NOT_PLAYING,
|
||||
PLAYING,
|
||||
PLAYING_LOOP
|
||||
}
|
||||
|
||||
// Buffers
|
||||
private int audioData;
|
||||
private int sourceData;
|
||||
// Buffers
|
||||
private int audioData;
|
||||
private int sourceData;
|
||||
|
||||
// Characteristics
|
||||
private Vec3 position = new Vec3();
|
||||
private Vec3 velocity = new Vec3();
|
||||
private float pitch = 1.0f;
|
||||
private float gain = 1.0f;
|
||||
private State state = State.NOT_PLAYING;
|
||||
// Characteristics
|
||||
private Vec3 position = new Vec3();
|
||||
private Vec3 velocity = new Vec3();
|
||||
private float pitch = 1.0f;
|
||||
private float gain = 1.0f;
|
||||
private State state = State.NOT_PLAYING;
|
||||
|
||||
public Speaker() {
|
||||
sourceData = alGenSources();
|
||||
}
|
||||
public Speaker() {
|
||||
sourceData = alGenSources();
|
||||
}
|
||||
|
||||
public Speaker(int audioData) {
|
||||
this();
|
||||
setAudioData(audioData);
|
||||
}
|
||||
public Speaker(int audioData) {
|
||||
this();
|
||||
setAudioData(audioData);
|
||||
}
|
||||
|
||||
public Speaker(
|
||||
int audioData,
|
||||
Vec3 position,
|
||||
Vec3 velocity,
|
||||
float pitch,
|
||||
float gain
|
||||
) {
|
||||
setAudioData(audioData);
|
||||
setPosition(position);
|
||||
setVelocity(velocity);
|
||||
setPitch(pitch);
|
||||
setGain(gain);
|
||||
}
|
||||
public Speaker(
|
||||
int audioData,
|
||||
Vec3 position,
|
||||
Vec3 velocity,
|
||||
float pitch,
|
||||
float gain
|
||||
) {
|
||||
setAudioData(audioData);
|
||||
setPosition(position);
|
||||
setVelocity(velocity);
|
||||
setPitch(pitch);
|
||||
setGain(gain);
|
||||
}
|
||||
|
||||
public Speaker(
|
||||
Vec3 position,
|
||||
Vec3 velocity,
|
||||
float pitch,
|
||||
float gain
|
||||
) {
|
||||
setPosition(position);
|
||||
setVelocity(velocity);
|
||||
setPitch(pitch);
|
||||
setGain(gain);
|
||||
}
|
||||
public Speaker(
|
||||
Vec3 position,
|
||||
Vec3 velocity,
|
||||
float pitch,
|
||||
float gain
|
||||
) {
|
||||
setPosition(position);
|
||||
setVelocity(velocity);
|
||||
setPitch(pitch);
|
||||
setGain(gain);
|
||||
}
|
||||
|
||||
public void play() {
|
||||
alSourcePlay(sourceData);
|
||||
state = State.PLAYING;
|
||||
}
|
||||
public void play() {
|
||||
alSourcePlay(sourceData);
|
||||
state = State.PLAYING;
|
||||
}
|
||||
|
||||
public void playLoop() {
|
||||
alSourcei(sourceData, AL_LOOPING, AL_TRUE);
|
||||
alSourcePlay(sourceData);
|
||||
state = State.PLAYING_LOOP;
|
||||
}
|
||||
public void playLoop() {
|
||||
alSourcei(sourceData, AL_LOOPING, AL_TRUE);
|
||||
alSourcePlay(sourceData);
|
||||
state = State.PLAYING_LOOP;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
alSourceStop(sourceData);
|
||||
if (state == State.PLAYING_LOOP) {
|
||||
alSourcei(sourceData, AL_LOOPING, AL_FALSE);
|
||||
}
|
||||
state = State.NOT_PLAYING;
|
||||
}
|
||||
public void stop() {
|
||||
alSourceStop(sourceData);
|
||||
if (state == State.PLAYING_LOOP) {
|
||||
alSourcei(sourceData, AL_LOOPING, AL_FALSE);
|
||||
}
|
||||
state = State.NOT_PLAYING;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
alSourcePause(sourceData);
|
||||
state = State.NOT_PLAYING;
|
||||
}
|
||||
public void pause() {
|
||||
alSourcePause(sourceData);
|
||||
state = State.NOT_PLAYING;
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
final int speakerState = alGetSourcei(sourceData, AL_SOURCE_STATE);
|
||||
if (speakerState == AL_PLAYING) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
state = State.NOT_PLAYING;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public boolean isPlaying() {
|
||||
final int speakerState = alGetSourcei(sourceData, AL_SOURCE_STATE);
|
||||
if (speakerState == AL_PLAYING) {
|
||||
return true;
|
||||
} else {
|
||||
state = State.NOT_PLAYING;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// GETTERS & SETTERS
|
||||
// GETTERS & SETTERS
|
||||
|
||||
public int getAudioData() {
|
||||
return audioData;
|
||||
}
|
||||
public int getAudioData() {
|
||||
return audioData;
|
||||
}
|
||||
|
||||
public int getSourceData() {
|
||||
return sourceData;
|
||||
}
|
||||
public int getSourceData() {
|
||||
return sourceData;
|
||||
}
|
||||
|
||||
public void setAudioData(int audioData) {
|
||||
this.audioData = audioData;
|
||||
alSourcei(this.sourceData, AL_BUFFER, audioData);
|
||||
}
|
||||
public void setAudioData(int audioData) {
|
||||
stop();
|
||||
this.audioData = audioData;
|
||||
alSourcei(this.sourceData, AL_BUFFER, audioData);
|
||||
}
|
||||
|
||||
public void setPosition(Vec3 position) {
|
||||
this.position = position;
|
||||
alSource3f(sourceData, AL_POSITION, position.x, position.y, position.z);
|
||||
}
|
||||
public void setPosition(Vec3 position) {
|
||||
this.position = position;
|
||||
alSource3f(sourceData, AL_POSITION, position.x, position.y, position.z);
|
||||
}
|
||||
|
||||
public Vec3 getPosition() {
|
||||
return position;
|
||||
}
|
||||
public Vec3 getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setVelocity(Vec3 velocity) {
|
||||
alSource3f(sourceData, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
|
||||
this.velocity = velocity;
|
||||
}
|
||||
public void setVelocity(Vec3 velocity) {
|
||||
alSource3f(sourceData, AL_VELOCITY, velocity.x, velocity.y, velocity.z);
|
||||
this.velocity = velocity;
|
||||
}
|
||||
|
||||
public Vec3 getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
public Vec3 getVelocity() {
|
||||
return velocity;
|
||||
}
|
||||
|
||||
public void setPitch(float pitch) {
|
||||
alSourcef(sourceData, AL_PITCH, pitch);
|
||||
this.pitch = pitch;
|
||||
}
|
||||
public void setPitch(float pitch) {
|
||||
alSourcef(sourceData, AL_PITCH, pitch);
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public void setGain(float gain) {
|
||||
alSourcef(sourceData, AL_GAIN, gain);
|
||||
this.gain = gain;
|
||||
}
|
||||
public void setGain(float gain) {
|
||||
alSourcef(sourceData, AL_GAIN, gain);
|
||||
this.gain = gain;
|
||||
}
|
||||
|
||||
public float getGain() {
|
||||
return gain;
|
||||
}
|
||||
public float getGain() {
|
||||
return gain;
|
||||
}
|
||||
|
||||
public State getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,46 +1,64 @@
|
||||
package ru.windcorp.progressia.client.comms;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.common.comms.CommsListener;
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.common.world.PacketSetLocalPlayer;
|
||||
import ru.windcorp.progressia.common.world.PacketAffectWorld;
|
||||
|
||||
// TODO refactor with no mercy
|
||||
public class DefaultClientCommsListener implements CommsListener {
|
||||
|
||||
private final Client client;
|
||||
|
||||
public DefaultClientCommsListener(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(Packet packet) {
|
||||
if (packet instanceof PacketAffectWorld) {
|
||||
((PacketAffectWorld) packet).apply(
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.common.comms.CommsListener;
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
import ru.windcorp.progressia.common.world.PacketSetLocalPlayer;
|
||||
import ru.windcorp.progressia.common.world.PacketAffectWorld;
|
||||
|
||||
// TODO refactor with no mercy
|
||||
public class DefaultClientCommsListener implements CommsListener {
|
||||
|
||||
private final Client client;
|
||||
|
||||
public DefaultClientCommsListener(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceived(Packet packet) {
|
||||
if (packet instanceof PacketAffectWorld) {
|
||||
((PacketAffectWorld) packet).apply(
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,25 @@
|
||||
package ru.windcorp.progressia.client.comms;
|
||||
|
||||
import ru.windcorp.progressia.common.comms.CommsChannel;
|
||||
|
||||
public abstract class ServerCommsChannel extends CommsChannel {
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import ru.windcorp.progressia.common.comms.CommsChannel;
|
||||
|
||||
public abstract class ServerCommsChannel extends CommsChannel {
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,29 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||
|
||||
public abstract class ControlTrigger extends Namespaced {
|
||||
|
||||
public ControlTrigger(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,14 +1,32 @@
|
||||
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);
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 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);
|
||||
|
||||
}
|
||||
|
@ -1,48 +1,67 @@
|
||||
package ru.windcorp.progressia.client.comms.controls;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlData;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry;
|
||||
import ru.windcorp.progressia.common.comms.controls.PacketControl;
|
||||
import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil;
|
||||
|
||||
public class ControlTriggerLambda extends ControlTriggerInputBased {
|
||||
|
||||
private final String packetId;
|
||||
private final Predicate<InputEvent> predicate;
|
||||
private final BiConsumer<InputEvent, ControlData> dataWriter;
|
||||
|
||||
public ControlTriggerLambda(
|
||||
String id,
|
||||
Predicate<InputEvent> predicate,
|
||||
BiConsumer<InputEvent, ControlData> dataWriter
|
||||
) {
|
||||
super(id);
|
||||
|
||||
this.packetId = NamespacedUtil.getId(
|
||||
NamespacedUtil.getNamespace(id),
|
||||
"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;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlData;
|
||||
import ru.windcorp.progressia.common.comms.controls.ControlDataRegistry;
|
||||
import ru.windcorp.progressia.common.comms.controls.PacketControl;
|
||||
import ru.windcorp.progressia.common.util.namespaces.NamespacedUtil;
|
||||
|
||||
public class ControlTriggerLambda extends ControlTriggerInputBased {
|
||||
|
||||
private final String packetId;
|
||||
private final Predicate<InputEvent> predicate;
|
||||
private final BiConsumer<InputEvent, ControlData> dataWriter;
|
||||
|
||||
public ControlTriggerLambda(
|
||||
String id,
|
||||
Predicate<InputEvent> predicate,
|
||||
BiConsumer<InputEvent, ControlData> dataWriter
|
||||
) {
|
||||
super(id);
|
||||
|
||||
this.packetId = NamespacedUtil.getId(
|
||||
NamespacedUtil.getNamespace(id),
|
||||
"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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,31 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
public class ControlTriggers {
|
||||
|
||||
|
||||
public static ControlTriggerInputBased of(
|
||||
String id,
|
||||
BiConsumer<InputEvent, ControlData> dataWriter,
|
||||
Predicate<InputEvent> predicate
|
||||
String id,
|
||||
BiConsumer<InputEvent, ControlData> dataWriter,
|
||||
Predicate<InputEvent> predicate
|
||||
) {
|
||||
return new ControlTriggerLambda(id, predicate, dataWriter);
|
||||
}
|
||||
|
||||
|
||||
public static ControlTriggerInputBased of(
|
||||
String id,
|
||||
Consumer<ControlData> dataWriter,
|
||||
Predicate<InputEvent> predicate
|
||||
String id,
|
||||
Consumer<ControlData> dataWriter,
|
||||
Predicate<InputEvent> predicate
|
||||
) {
|
||||
return of(
|
||||
id,
|
||||
(input, control) -> dataWriter.accept(control),
|
||||
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
|
||||
id,
|
||||
(input, control) -> dataWriter.accept(control),
|
||||
predicate
|
||||
);
|
||||
}
|
||||
|
||||
private static
|
||||
<I extends InputEvent>
|
||||
BiConsumer<InputEvent, ControlData>
|
||||
createCheckedDataWriter(
|
||||
Class<I> inputType,
|
||||
BiConsumer<I, ControlData> dataWriter
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
///
|
||||
///
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static
|
||||
<I extends InputEvent>
|
||||
Predicate<InputEvent>
|
||||
createCheckedCompoundPredicate(
|
||||
Class<I> inputType,
|
||||
Predicate<I>[] predicates
|
||||
private static <I extends InputEvent> Consumer<InputEvent> createCheckedAction(
|
||||
Class<I> inputType,
|
||||
Consumer<I> action
|
||||
) {
|
||||
return inputEvent -> action.accept(inputType.cast(inputEvent));
|
||||
}
|
||||
|
||||
private static <I extends InputEvent> Predicate<InputEvent> createCheckedCompoundPredicate(
|
||||
Class<I> inputType,
|
||||
Predicate<I>[] predicates
|
||||
) {
|
||||
return new CompoundCastPredicate<>(inputType, predicates);
|
||||
}
|
||||
|
||||
|
||||
private static class CompoundCastPredicate<I extends InputEvent> implements Predicate<InputEvent> {
|
||||
|
||||
|
||||
private final Class<I> inputType;
|
||||
private final Predicate<I>[] predicates;
|
||||
|
||||
|
||||
public CompoundCastPredicate(Class<I> inputType, Predicate<I>[] predicates) {
|
||||
this.inputType = inputType;
|
||||
this.predicates = predicates;
|
||||
@ -157,20 +269,21 @@ public class ControlTriggers {
|
||||
if (!inputType.isInstance(inputEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
I castEvent = inputType.cast(inputEvent);
|
||||
|
||||
|
||||
for (Predicate<I> predicate : predicates) {
|
||||
if (!predicate.test(castEvent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private ControlTriggers() {}
|
||||
private ControlTriggers() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,33 +1,51 @@
|
||||
package ru.windcorp.progressia.client.comms.controls;
|
||||
|
||||
import ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
|
||||
public class InputBasedControls {
|
||||
|
||||
private final Client client;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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 ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
|
||||
public class InputBasedControls {
|
||||
|
||||
private final Client client;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,41 +1,59 @@
|
||||
package ru.windcorp.progressia.client.comms.localhost;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
import ru.windcorp.progressia.server.comms.ClientPlayer;
|
||||
|
||||
public class LocalClient extends ClientPlayer {
|
||||
|
||||
private final LocalServerCommsChannel serverComms;
|
||||
|
||||
private final String login;
|
||||
|
||||
public LocalClient(int id, String login, LocalServerCommsChannel serverComms) {
|
||||
super(id);
|
||||
setState(State.CONNECTED);
|
||||
|
||||
this.serverComms = serverComms;
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Progressia
|
||||
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.progressia.client.comms.localhost;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
import ru.windcorp.progressia.server.comms.ClientPlayer;
|
||||
|
||||
public class LocalClient extends ClientPlayer {
|
||||
|
||||
private final LocalServerCommsChannel serverComms;
|
||||
|
||||
private final String login;
|
||||
|
||||
public LocalClient(int id, String login, LocalServerCommsChannel serverComms) {
|
||||
super(id);
|
||||
setState(State.CONNECTED);
|
||||
|
||||
this.serverComms = serverComms;
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,42 +1,60 @@
|
||||
package ru.windcorp.progressia.client.comms.localhost;
|
||||
|
||||
import ru.windcorp.progressia.client.comms.ServerCommsChannel;
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
|
||||
public class LocalServerCommsChannel extends ServerCommsChannel {
|
||||
|
||||
private LocalClient localClient;
|
||||
private final Server server;
|
||||
|
||||
public LocalServerCommsChannel(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void connect(String login) {
|
||||
setState(State.CONNECTED);
|
||||
|
||||
this.localClient = new LocalClient(
|
||||
server.getClientManager().grabClientId(),
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Progressia
|
||||
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package ru.windcorp.progressia.client.comms.localhost;
|
||||
|
||||
import ru.windcorp.progressia.client.comms.ServerCommsChannel;
|
||||
import ru.windcorp.progressia.common.comms.packets.Packet;
|
||||
import ru.windcorp.progressia.server.Server;
|
||||
|
||||
public class LocalServerCommsChannel extends ServerCommsChannel {
|
||||
|
||||
private LocalClient localClient;
|
||||
private final Server server;
|
||||
|
||||
public LocalServerCommsChannel(Server server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public void connect(String login) {
|
||||
setState(State.CONNECTED);
|
||||
|
||||
this.localClient = new LocalClient(
|
||||
server.getClientManager().grabClientId(),
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,61 +1,62 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import glm.vec._4.Vec4;
|
||||
|
||||
public class Colors {
|
||||
|
||||
public static final Vec4
|
||||
WHITE = toVector(0xFFFFFFFF),
|
||||
BLACK = toVector(0xFF000000),
|
||||
|
||||
GRAY_4 = toVector(0xFF444444),
|
||||
GRAY = toVector(0xFF888888),
|
||||
GRAY_A = toVector(0xFFAAAAAA),
|
||||
|
||||
DEBUG_RED = toVector(0xFFFF0000),
|
||||
DEBUG_GREEN = toVector(0xFF00FF00),
|
||||
DEBUG_BLUE = toVector(0xFF0000FF),
|
||||
DEBUG_CYAN = toVector(0xFF00FFFF),
|
||||
DEBUG_MAGENTA = toVector(0xFFFF00FF),
|
||||
DEBUG_YELLOW = toVector(0xFFFFFF00);
|
||||
|
||||
public static Vec4 toVector(int argb) {
|
||||
return toVector(argb, new Vec4());
|
||||
}
|
||||
|
||||
public static Vec4 multiplyRGB(Vec4 color, float multiplier) {
|
||||
return color.mul(multiplier, multiplier, multiplier, 1);
|
||||
}
|
||||
|
||||
public static Vec4 multiplyRGB(Vec4 color, float multiplier, Vec4 output) {
|
||||
if (output == null) 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
|
||||
output.x = ((argb & 0x00FF0000) >>> 16) / 256f; // Red
|
||||
output.y = ((argb & 0x0000FF00) >>> 8) / 256f; // Green
|
||||
output.z = ((argb & 0x000000FF) ) / 256f; // Blue
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import glm.vec._4.Vec4;
|
||||
|
||||
public class Colors {
|
||||
|
||||
public static final Vec4 WHITE = toVector(0xFFFFFFFF),
|
||||
BLACK = toVector(0xFF000000),
|
||||
|
||||
GRAY_4 = toVector(0xFF444444),
|
||||
GRAY = toVector(0xFF888888),
|
||||
GRAY_A = toVector(0xFFAAAAAA),
|
||||
|
||||
DEBUG_RED = toVector(0xFFFF0000),
|
||||
DEBUG_GREEN = toVector(0xFF00FF00),
|
||||
DEBUG_BLUE = toVector(0xFF0000FF),
|
||||
DEBUG_CYAN = toVector(0xFF00FFFF),
|
||||
DEBUG_MAGENTA = toVector(0xFFFF00FF),
|
||||
DEBUG_YELLOW = toVector(0xFFFFFF00);
|
||||
|
||||
public static Vec4 toVector(int argb) {
|
||||
return toVector(argb, new Vec4());
|
||||
}
|
||||
|
||||
public static Vec4 multiplyRGB(Vec4 color, float multiplier) {
|
||||
return color.mul(multiplier, multiplier, multiplier, 1);
|
||||
}
|
||||
|
||||
public static Vec4 multiplyRGB(Vec4 color, float multiplier, Vec4 output) {
|
||||
if (output == null)
|
||||
output = new Vec4();
|
||||
return color.mul(multiplier, multiplier, multiplier, 1, output);
|
||||
}
|
||||
|
||||
public static Vec4 toVector(int argb, Vec4 output) {
|
||||
output.w = ((argb & 0xFF000000) >>> 24) / (float) 0xFF; // Alpha
|
||||
output.x = ((argb & 0x00FF0000) >>> 16) / (float) 0xFF; // Red
|
||||
output.y = ((argb & 0x0000FF00) >>> 8) / (float) 0xFF; // Green
|
||||
output.z = ((argb & 0x000000FF)) / (float) 0xFF; // Blue
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,108 +1,133 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.CursorEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.WheelEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
|
||||
public class GUI {
|
||||
|
||||
private static final List<Layer> LAYERS = new ArrayList<>();
|
||||
|
||||
private static class ModifiableInput extends Input {
|
||||
@Override
|
||||
public void initialize(InputEvent event, Target target) {
|
||||
super.initialize(event, target);
|
||||
}
|
||||
}
|
||||
|
||||
private static final ModifiableInput THE_INPUT = new ModifiableInput();
|
||||
|
||||
private GUI() {}
|
||||
|
||||
public synchronized static void addBottomLayer(Layer layer) {
|
||||
LAYERS.add(layer);
|
||||
}
|
||||
|
||||
public synchronized static void addTopLayer(Layer layer) {
|
||||
LAYERS.add(0, layer);
|
||||
}
|
||||
|
||||
public synchronized static void removeLayer(Layer layer) {
|
||||
LAYERS.remove(layer);
|
||||
}
|
||||
|
||||
public synchronized static void render() {
|
||||
for (int i = LAYERS.size() - 1; i >= 0; --i) {
|
||||
LAYERS.get(i).render();
|
||||
}
|
||||
}
|
||||
|
||||
public static void invalidateEverything() {
|
||||
LAYERS.forEach(Layer::invalidate);
|
||||
}
|
||||
|
||||
private static void dispatchInputEvent(InputEvent event) {
|
||||
Input.Target target;
|
||||
|
||||
if (event instanceof KeyEvent) {
|
||||
if (((KeyEvent) event).isMouse()) {
|
||||
target = Input.Target.HOVERED;
|
||||
} else {
|
||||
target = Input.Target.FOCUSED;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.CursorEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.WheelEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
|
||||
public class GUI {
|
||||
|
||||
private static final List<Layer> LAYERS = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final List<Layer> UNMODIFIABLE_LAYERS = Collections.unmodifiableList(LAYERS);
|
||||
|
||||
@FunctionalInterface
|
||||
private interface LayerStackModification {
|
||||
void affect(List<Layer> layers);
|
||||
}
|
||||
|
||||
private static final List<LayerStackModification> MODIFICATION_QUEUE = Collections
|
||||
.synchronizedList(new ArrayList<>());
|
||||
|
||||
private static class ModifiableInput extends Input {
|
||||
@Override
|
||||
public void initialize(InputEvent event, Target target) {
|
||||
super.initialize(event, target);
|
||||
}
|
||||
}
|
||||
|
||||
private static final ModifiableInput THE_INPUT = new ModifiableInput();
|
||||
|
||||
private GUI() {
|
||||
}
|
||||
|
||||
public static void addBottomLayer(Layer layer) {
|
||||
modify(layers -> layers.add(layer));
|
||||
}
|
||||
|
||||
public static void addTopLayer(Layer layer) {
|
||||
modify(layers -> layers.add(0, layer));
|
||||
}
|
||||
|
||||
public static void removeLayer(Layer layer) {
|
||||
modify(layers -> layers.remove(layer));
|
||||
}
|
||||
|
||||
private static void modify(LayerStackModification mod) {
|
||||
MODIFICATION_QUEUE.add(mod);
|
||||
}
|
||||
|
||||
public static List<Layer> getLayers() {
|
||||
return UNMODIFIABLE_LAYERS;
|
||||
}
|
||||
|
||||
public static void render() {
|
||||
synchronized (LAYERS) {
|
||||
MODIFICATION_QUEUE.forEach(action -> action.affect(LAYERS));
|
||||
MODIFICATION_QUEUE.clear();
|
||||
|
||||
for (int i = LAYERS.size() - 1; i >= 0; --i) {
|
||||
LAYERS.get(i).render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void invalidateEverything() {
|
||||
LAYERS.forEach(Layer::invalidate);
|
||||
}
|
||||
|
||||
private static void dispatchInputEvent(InputEvent event) {
|
||||
Input.Target target;
|
||||
|
||||
if (event instanceof KeyEvent) {
|
||||
if (((KeyEvent) event).isMouse()) {
|
||||
target = Input.Target.HOVERED;
|
||||
} else {
|
||||
target = Input.Target.FOCUSED;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,81 +1,82 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
|
||||
public abstract class Layer {
|
||||
|
||||
private final String name;
|
||||
|
||||
private boolean hasInitialized = false;
|
||||
|
||||
private final AtomicBoolean isValid = new AtomicBoolean(false);
|
||||
|
||||
public Layer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Layer " + name;
|
||||
}
|
||||
|
||||
void render() {
|
||||
GraphicsInterface.startNextLayer();
|
||||
|
||||
validate();
|
||||
|
||||
if (!hasInitialized) {
|
||||
initialize();
|
||||
hasInitialized = true;
|
||||
}
|
||||
|
||||
doRender();
|
||||
}
|
||||
|
||||
void validate() {
|
||||
if (isValid.compareAndSet(false, true)) {
|
||||
doValidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
isValid.set(false);
|
||||
}
|
||||
|
||||
protected abstract void initialize();
|
||||
|
||||
protected abstract void doValidate();
|
||||
|
||||
protected abstract void doRender();
|
||||
|
||||
protected abstract void handleInput(Input input);
|
||||
|
||||
protected int getWidth() {
|
||||
return GraphicsInterface.getFrameWidth();
|
||||
}
|
||||
|
||||
protected int getHeight() {
|
||||
return GraphicsInterface.getFrameHeight();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
|
||||
public abstract class Layer {
|
||||
|
||||
private final String name;
|
||||
|
||||
private boolean hasInitialized = false;
|
||||
|
||||
private final AtomicBoolean isValid = new AtomicBoolean(false);
|
||||
|
||||
public Layer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Layer " + name;
|
||||
}
|
||||
|
||||
void render() {
|
||||
GraphicsInterface.startNextLayer();
|
||||
|
||||
validate();
|
||||
|
||||
if (!hasInitialized) {
|
||||
initialize();
|
||||
hasInitialized = true;
|
||||
}
|
||||
|
||||
doRender();
|
||||
}
|
||||
|
||||
void validate() {
|
||||
if (isValid.compareAndSet(false, true)) {
|
||||
doValidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
isValid.set(false);
|
||||
}
|
||||
|
||||
protected abstract void initialize();
|
||||
|
||||
protected abstract void doValidate();
|
||||
|
||||
protected abstract void doRender();
|
||||
|
||||
protected abstract void handleInput(Input input);
|
||||
|
||||
protected int getWidth() {
|
||||
return GraphicsInterface.getFrameWidth();
|
||||
}
|
||||
|
||||
protected int getHeight() {
|
||||
return GraphicsInterface.getFrameHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
public class FaceCulling {
|
||||
|
||||
|
||||
private static final Deque<Boolean> STACK = new ArrayDeque<>();
|
||||
|
||||
|
||||
public static void push(boolean useFaceCulling) {
|
||||
GraphicsBackend.setFaceCulling(useFaceCulling);
|
||||
STACK.push(Boolean.valueOf(useFaceCulling));
|
||||
}
|
||||
|
||||
|
||||
public static void pop() {
|
||||
STACK.pop();
|
||||
|
||||
|
||||
if (STACK.isEmpty()) {
|
||||
GraphicsBackend.setFaceCulling(false);
|
||||
} else {
|
||||
GraphicsBackend.setFaceCulling(STACK.getFirst());
|
||||
}
|
||||
}
|
||||
|
||||
private FaceCulling() {}
|
||||
|
||||
private FaceCulling() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,127 +1,195 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
|
||||
public class GraphicsBackend {
|
||||
|
||||
private static RenderThread renderThread;
|
||||
|
||||
private static long windowHandle;
|
||||
|
||||
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 frameStart = Double.NaN;
|
||||
|
||||
private static boolean faceCullingEnabled = false;
|
||||
|
||||
private GraphicsBackend() {}
|
||||
|
||||
public static void initialize() {
|
||||
startRenderThread();
|
||||
}
|
||||
|
||||
private static void startRenderThread() {
|
||||
renderThread = new RenderThread();
|
||||
renderThread.start();
|
||||
}
|
||||
|
||||
public static Thread getRenderThread() {
|
||||
return renderThread;
|
||||
}
|
||||
|
||||
static void setWindowHandle(long windowHandle) {
|
||||
GraphicsBackend.windowHandle = windowHandle;
|
||||
}
|
||||
|
||||
public static long getWindowHandle() {
|
||||
return windowHandle;
|
||||
}
|
||||
|
||||
public static int getFrameWidth() {
|
||||
return FRAME_SIZE.x;
|
||||
}
|
||||
|
||||
public static int getFrameHeight() {
|
||||
return FRAME_SIZE.y;
|
||||
}
|
||||
|
||||
public static Vec2i getFrameSize() {
|
||||
return FRAME_SIZE;
|
||||
}
|
||||
|
||||
static void onFrameResized(long window, int newWidth, int newHeight) {
|
||||
if (window != windowHandle) return;
|
||||
|
||||
InputHandler.handleFrameResize(newWidth, newHeight);
|
||||
FRAME_SIZE.set(newWidth, newHeight);
|
||||
|
||||
glViewport(0, 0, newWidth, newHeight);
|
||||
}
|
||||
|
||||
static void startFrame() {
|
||||
double now = glfwGetTime();
|
||||
|
||||
if (Double.isNaN(frameStart)) {
|
||||
frameStart = now;
|
||||
} else {
|
||||
frameLength = now - frameStart;
|
||||
frameStart = now;
|
||||
}
|
||||
}
|
||||
|
||||
static void endFrame() {
|
||||
framesRendered++;
|
||||
}
|
||||
|
||||
public static double getFrameStart() {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
import org.lwjgl.glfw.GLFWVidMode;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
public class GraphicsBackend {
|
||||
|
||||
private static RenderThread renderThread;
|
||||
|
||||
private static long windowHandle;
|
||||
|
||||
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 frameStart = Double.NaN;
|
||||
|
||||
private static boolean faceCullingEnabled = false;
|
||||
|
||||
private static boolean isFullscreen = false;
|
||||
private static boolean vSyncEnabled = false;
|
||||
private static boolean isGLFWInitialized = false;
|
||||
private static boolean isOpenGLInitialized = false;
|
||||
|
||||
private GraphicsBackend() {
|
||||
}
|
||||
|
||||
public static boolean isGLFWInitialized() {
|
||||
return isGLFWInitialized;
|
||||
}
|
||||
|
||||
static void setGLFWInitialized(boolean isGLFWInitialized) {
|
||||
GraphicsBackend.isGLFWInitialized = isGLFWInitialized;
|
||||
}
|
||||
|
||||
public static boolean isOpenGLInitialized() {
|
||||
return isOpenGLInitialized;
|
||||
}
|
||||
|
||||
static void setOpenGLInitialized(boolean isOpenGLInitialized) {
|
||||
GraphicsBackend.isOpenGLInitialized = isOpenGLInitialized;
|
||||
}
|
||||
|
||||
public static void initialize() {
|
||||
startRenderThread();
|
||||
}
|
||||
|
||||
private static void startRenderThread() {
|
||||
renderThread = new RenderThread();
|
||||
renderThread.start();
|
||||
}
|
||||
|
||||
public static Thread getRenderThread() {
|
||||
return renderThread;
|
||||
}
|
||||
|
||||
static void setWindowHandle(long windowHandle) {
|
||||
GraphicsBackend.windowHandle = windowHandle;
|
||||
}
|
||||
|
||||
public static long getWindowHandle() {
|
||||
return windowHandle;
|
||||
}
|
||||
|
||||
public static int getFrameWidth() {
|
||||
return FRAME_SIZE.x;
|
||||
}
|
||||
|
||||
public static int getFrameHeight() {
|
||||
return FRAME_SIZE.y;
|
||||
}
|
||||
|
||||
public static Vec2i getFrameSize() {
|
||||
return FRAME_SIZE;
|
||||
}
|
||||
|
||||
static void onFrameResized(long window, int newWidth, int newHeight) {
|
||||
if (window != windowHandle)
|
||||
return;
|
||||
|
||||
InputHandler.handleFrameResize(newWidth, newHeight);
|
||||
FRAME_SIZE.set(newWidth, newHeight);
|
||||
|
||||
glViewport(0, 0, newWidth, newHeight);
|
||||
}
|
||||
|
||||
static void startFrame() {
|
||||
double now = glfwGetTime();
|
||||
|
||||
if (Double.isNaN(frameStart)) {
|
||||
frameStart = now;
|
||||
} else {
|
||||
frameLength = now - frameStart;
|
||||
frameStart = now;
|
||||
}
|
||||
}
|
||||
|
||||
static void endFrame() {
|
||||
framesRendered++;
|
||||
}
|
||||
|
||||
public static double getFrameStart() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +1,85 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
|
||||
public class GraphicsInterface {
|
||||
|
||||
private GraphicsInterface() {}
|
||||
|
||||
public static Thread getRenderThread() {
|
||||
return GraphicsBackend.getRenderThread();
|
||||
}
|
||||
|
||||
public static boolean isRenderThread() {
|
||||
return Thread.currentThread() == getRenderThread();
|
||||
}
|
||||
|
||||
public static int getFrameWidth() {
|
||||
return GraphicsBackend.getFrameWidth();
|
||||
}
|
||||
|
||||
public static int getFrameHeight() {
|
||||
return GraphicsBackend.getFrameHeight();
|
||||
}
|
||||
|
||||
public static Vec2i getFrameSize() {
|
||||
return GraphicsBackend.getFrameSize();
|
||||
}
|
||||
|
||||
public static float getAspectRatio() {
|
||||
return ((float) getFrameWidth()) / getFrameHeight();
|
||||
}
|
||||
|
||||
public static double getTime() {
|
||||
return GraphicsBackend.getFrameStart();
|
||||
}
|
||||
|
||||
public static double getFrameLength() {
|
||||
return GraphicsBackend.getFrameLength();
|
||||
}
|
||||
|
||||
public static double getFPS() {
|
||||
return 1 / GraphicsBackend.getFrameLength();
|
||||
}
|
||||
|
||||
public static long getFramesRendered() {
|
||||
return GraphicsBackend.getFramesRendered();
|
||||
}
|
||||
|
||||
public static void subscribeToInputEvents(Object listener) {
|
||||
InputHandler.register(listener);
|
||||
}
|
||||
|
||||
public static void startNextLayer() {
|
||||
GraphicsBackend.startNextLayer();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
|
||||
public class GraphicsInterface {
|
||||
|
||||
private GraphicsInterface() {
|
||||
}
|
||||
|
||||
public static Thread getRenderThread() {
|
||||
return GraphicsBackend.getRenderThread();
|
||||
}
|
||||
|
||||
public static boolean isRenderThread() {
|
||||
return Thread.currentThread() == getRenderThread();
|
||||
}
|
||||
|
||||
public static int getFrameWidth() {
|
||||
return GraphicsBackend.getFrameWidth();
|
||||
}
|
||||
|
||||
public static int getFrameHeight() {
|
||||
return GraphicsBackend.getFrameHeight();
|
||||
}
|
||||
|
||||
public static Vec2i getFrameSize() {
|
||||
return GraphicsBackend.getFrameSize();
|
||||
}
|
||||
|
||||
public static float getAspectRatio() {
|
||||
return ((float) getFrameWidth()) / getFrameHeight();
|
||||
}
|
||||
|
||||
public static double getTime() {
|
||||
return GraphicsBackend.getFrameStart();
|
||||
}
|
||||
|
||||
public static double getFrameLength() {
|
||||
return GraphicsBackend.getFrameLength();
|
||||
}
|
||||
|
||||
public static double getFPS() {
|
||||
return 1 / GraphicsBackend.getFrameLength();
|
||||
}
|
||||
|
||||
public static long getFramesRendered() {
|
||||
return GraphicsBackend.getFramesRendered();
|
||||
}
|
||||
|
||||
public static void subscribeToInputEvents(Object listener) {
|
||||
InputHandler.register(listener);
|
||||
}
|
||||
|
||||
public static void startNextLayer() {
|
||||
GraphicsBackend.startNextLayer();
|
||||
}
|
||||
|
||||
public static void makeFullscreen(boolean state) {
|
||||
if (state) {
|
||||
GraphicsBackend.setFullscreen();
|
||||
} else {
|
||||
GraphicsBackend.setWindowed();
|
||||
}
|
||||
GraphicsBackend.setVSyncEnabled(GraphicsBackend.isVSyncEnabled());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,182 +1,183 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.*;
|
||||
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
||||
|
||||
public class InputHandler {
|
||||
|
||||
private static final EventBus INPUT_EVENT_BUS = ReportingEventBus.create("Input");
|
||||
|
||||
// KeyEvent
|
||||
|
||||
private static class ModifiableKeyEvent extends KeyEvent {
|
||||
|
||||
protected ModifiableKeyEvent() {
|
||||
super(0, 0, 0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
public void initialize(int key, int scancode, int action, int mods) {
|
||||
this.setTime(GraphicsInterface.getTime());
|
||||
this.key = key;
|
||||
this.scancode = scancode;
|
||||
this.action = action;
|
||||
this.mods = mods;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final ModifiableKeyEvent THE_KEY_EVENT =
|
||||
new ModifiableKeyEvent();
|
||||
|
||||
static void handleKeyInput(
|
||||
long window,
|
||||
int key,
|
||||
int scancode,
|
||||
int action,
|
||||
int mods
|
||||
) {
|
||||
if (GraphicsBackend.getWindowHandle() != window) return;
|
||||
THE_KEY_EVENT.initialize(key, scancode, action, mods);
|
||||
dispatch(THE_KEY_EVENT);
|
||||
|
||||
switch (action) {
|
||||
case GLFW.GLFW_PRESS:
|
||||
InputTracker.setKeyState(key, true);
|
||||
break;
|
||||
case GLFW.GLFW_RELEASE:
|
||||
InputTracker.setKeyState(key, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleMouseButtonInput(
|
||||
long window,
|
||||
int key,
|
||||
int action,
|
||||
int mods
|
||||
) {
|
||||
handleKeyInput(window, key, Integer.MAX_VALUE - key, action, mods);
|
||||
}
|
||||
|
||||
// CursorMoveEvent
|
||||
|
||||
private static class ModifiableCursorMoveEvent extends CursorMoveEvent {
|
||||
|
||||
protected ModifiableCursorMoveEvent() {
|
||||
super(0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
public void initialize(double x, double y) {
|
||||
this.setTime(GraphicsInterface.getTime());
|
||||
getNewPosition().set(x, y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final ModifiableCursorMoveEvent THE_CURSOR_MOVE_EVENT =
|
||||
new ModifiableCursorMoveEvent();
|
||||
|
||||
static void handleMouseMoveInput(
|
||||
long window,
|
||||
double x, double y
|
||||
) {
|
||||
if (GraphicsBackend.getWindowHandle() != window) return;
|
||||
y = GraphicsInterface.getFrameHeight() - y; // Flip y axis
|
||||
|
||||
InputTracker.initializeCursorPosition(x, y);
|
||||
|
||||
THE_CURSOR_MOVE_EVENT.initialize(x, y);
|
||||
dispatch(THE_CURSOR_MOVE_EVENT);
|
||||
|
||||
InputTracker.getCursorPosition().set(x, y);
|
||||
}
|
||||
|
||||
// ScrollEvent
|
||||
|
||||
private static class ModifiableWheelScrollEvent extends WheelScrollEvent {
|
||||
|
||||
public ModifiableWheelScrollEvent() {
|
||||
super(0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
static void handleWheelScroll(
|
||||
long window,
|
||||
double xoffset,
|
||||
double yoffset
|
||||
) {
|
||||
if (GraphicsBackend.getWindowHandle() != window) return;
|
||||
THE_WHEEL_SCROLL_EVENT.initialize(xoffset, yoffset);
|
||||
dispatch(THE_WHEEL_SCROLL_EVENT);
|
||||
}
|
||||
|
||||
// FrameResizeEvent
|
||||
|
||||
private static class ModifiableFrameResizeEvent extends FrameResizeEvent {
|
||||
|
||||
public ModifiableFrameResizeEvent() {
|
||||
super(0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
/*
|
||||
* NB: this is NOT a GLFW callback, the raw callback is in GraphicsBackend
|
||||
*/
|
||||
static void handleFrameResize(
|
||||
int width,
|
||||
int height
|
||||
) {
|
||||
THE_FRAME_RESIZE_EVENT.initialize(width, height);
|
||||
dispatch(THE_FRAME_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
// Misc
|
||||
|
||||
private static void dispatch(InputEvent event) {
|
||||
INPUT_EVENT_BUS.post(event);
|
||||
}
|
||||
|
||||
public static void register(Object listener) {
|
||||
INPUT_EVENT_BUS.register(listener);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.input.*;
|
||||
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
||||
|
||||
public class InputHandler {
|
||||
|
||||
private static final EventBus INPUT_EVENT_BUS = ReportingEventBus.create("Input");
|
||||
|
||||
// KeyEvent
|
||||
|
||||
private static class ModifiableKeyEvent extends KeyEvent {
|
||||
|
||||
protected ModifiableKeyEvent() {
|
||||
super(0, 0, 0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
public void initialize(int key, int scancode, int action, int mods) {
|
||||
this.setTime(GraphicsInterface.getTime());
|
||||
this.key = key;
|
||||
this.scancode = scancode;
|
||||
this.action = action;
|
||||
this.mods = mods;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final ModifiableKeyEvent THE_KEY_EVENT = new ModifiableKeyEvent();
|
||||
|
||||
static void handleKeyInput(
|
||||
long window,
|
||||
int key,
|
||||
int scancode,
|
||||
int action,
|
||||
int mods
|
||||
) {
|
||||
if (GraphicsBackend.getWindowHandle() != window)
|
||||
return;
|
||||
THE_KEY_EVENT.initialize(key, scancode, action, mods);
|
||||
dispatch(THE_KEY_EVENT);
|
||||
|
||||
switch (action) {
|
||||
case GLFW.GLFW_PRESS:
|
||||
InputTracker.setKeyState(key, true);
|
||||
break;
|
||||
case GLFW.GLFW_RELEASE:
|
||||
InputTracker.setKeyState(key, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handleMouseButtonInput(
|
||||
long window,
|
||||
int key,
|
||||
int action,
|
||||
int mods
|
||||
) {
|
||||
handleKeyInput(window, key, Integer.MAX_VALUE - key, action, mods);
|
||||
}
|
||||
|
||||
// CursorMoveEvent
|
||||
|
||||
private static class ModifiableCursorMoveEvent extends CursorMoveEvent {
|
||||
|
||||
protected ModifiableCursorMoveEvent() {
|
||||
super(0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
public void initialize(double x, double y) {
|
||||
this.setTime(GraphicsInterface.getTime());
|
||||
getNewPosition().set(x, y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final ModifiableCursorMoveEvent THE_CURSOR_MOVE_EVENT = new ModifiableCursorMoveEvent();
|
||||
|
||||
static void handleMouseMoveInput(
|
||||
long window,
|
||||
double x,
|
||||
double y
|
||||
) {
|
||||
if (GraphicsBackend.getWindowHandle() != window)
|
||||
return;
|
||||
y = GraphicsInterface.getFrameHeight() - y; // Flip y axis
|
||||
|
||||
InputTracker.initializeCursorPosition(x, y);
|
||||
|
||||
THE_CURSOR_MOVE_EVENT.initialize(x, y);
|
||||
dispatch(THE_CURSOR_MOVE_EVENT);
|
||||
|
||||
InputTracker.getCursorPosition().set(x, y);
|
||||
}
|
||||
|
||||
// ScrollEvent
|
||||
|
||||
private static class ModifiableWheelScrollEvent extends WheelScrollEvent {
|
||||
|
||||
public ModifiableWheelScrollEvent() {
|
||||
super(0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
static void handleWheelScroll(
|
||||
long window,
|
||||
double xoffset,
|
||||
double yoffset
|
||||
) {
|
||||
if (GraphicsBackend.getWindowHandle() != window)
|
||||
return;
|
||||
THE_WHEEL_SCROLL_EVENT.initialize(xoffset, yoffset);
|
||||
dispatch(THE_WHEEL_SCROLL_EVENT);
|
||||
}
|
||||
|
||||
// FrameResizeEvent
|
||||
|
||||
private static class ModifiableFrameResizeEvent extends FrameResizeEvent {
|
||||
|
||||
public ModifiableFrameResizeEvent() {
|
||||
super(0, 0, Double.NaN);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
/*
|
||||
* NB: this is NOT a GLFW callback, the raw callback is in GraphicsBackend
|
||||
*/
|
||||
static void handleFrameResize(
|
||||
int width,
|
||||
int height
|
||||
) {
|
||||
THE_FRAME_RESIZE_EVENT.initialize(width, height);
|
||||
dispatch(THE_FRAME_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
// Misc
|
||||
|
||||
private static void dispatch(InputEvent event) {
|
||||
INPUT_EVENT_BUS.post(event);
|
||||
}
|
||||
|
||||
public static void register(Object listener) {
|
||||
INPUT_EVENT_BUS.register(listener);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,72 +1,75 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* 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;
|
||||
|
||||
import glm.vec._2.d.Vec2d;
|
||||
import gnu.trove.set.TIntSet;
|
||||
import gnu.trove.set.hash.TIntHashSet;
|
||||
|
||||
public class InputTracker {
|
||||
|
||||
private static final Vec2d CURSOR_POSITION = new Vec2d(
|
||||
Double.NaN, Double.NaN
|
||||
);
|
||||
|
||||
private static final TIntSet PRESSED_KEYS = new TIntHashSet(256);
|
||||
|
||||
private InputTracker() {}
|
||||
|
||||
public static double getCursorX() {
|
||||
return CURSOR_POSITION.x;
|
||||
}
|
||||
|
||||
public static double getCursorY() {
|
||||
return CURSOR_POSITION.y;
|
||||
}
|
||||
|
||||
public static Vec2d getCursorPosition() {
|
||||
return CURSOR_POSITION;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void setKeyState(int glfwCode, boolean isPressed) {
|
||||
if (isPressed) {
|
||||
PRESSED_KEYS.add(glfwCode);
|
||||
} else {
|
||||
PRESSED_KEYS.remove(glfwCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static TIntSet getPressedKeys() {
|
||||
return PRESSED_KEYS;
|
||||
}
|
||||
|
||||
static void releaseEverything() {
|
||||
PRESSED_KEYS.clear();
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import glm.vec._2.d.Vec2d;
|
||||
import gnu.trove.set.TIntSet;
|
||||
import gnu.trove.set.hash.TIntHashSet;
|
||||
|
||||
public class InputTracker {
|
||||
|
||||
private static final Vec2d CURSOR_POSITION = new Vec2d(
|
||||
Double.NaN,
|
||||
Double.NaN
|
||||
);
|
||||
|
||||
private static final TIntSet PRESSED_KEYS = new TIntHashSet(256);
|
||||
|
||||
private InputTracker() {
|
||||
}
|
||||
|
||||
public static double getCursorX() {
|
||||
return CURSOR_POSITION.x;
|
||||
}
|
||||
|
||||
public static double getCursorY() {
|
||||
return CURSOR_POSITION.y;
|
||||
}
|
||||
|
||||
public static Vec2d getCursorPosition() {
|
||||
return CURSOR_POSITION;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void setKeyState(int glfwCode, boolean isPressed) {
|
||||
if (isPressed) {
|
||||
PRESSED_KEYS.add(glfwCode);
|
||||
} else {
|
||||
PRESSED_KEYS.remove(glfwCode);
|
||||
}
|
||||
}
|
||||
|
||||
public static TIntSet getPressedKeys() {
|
||||
return PRESSED_KEYS;
|
||||
}
|
||||
|
||||
static void releaseEverything() {
|
||||
PRESSED_KEYS.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user