Formatted source, added/updated copyright headers
- Also added formatting settings for Eclipse IDE
This commit is contained in:
		@@ -1,5 +1,23 @@
 | 
			
		||||
#!/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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -100,6 +100,18 @@ Alternatively, specify another location outside of the project's root directory.
 | 
			
		||||
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
 | 
			
		||||
@@ -110,4 +122,4 @@ searches for Java installations in system path regardless and may fail independe
 | 
			
		||||
 | 
			
		||||
__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.
 | 
			
		||||
Java installation directory (specifically its `bin` folder) to the system `PATH` variable.
 | 
			
		||||
 
 | 
			
		||||
@@ -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,50 +1,51 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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());
 | 
			
		||||
		// 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());
 | 
			
		||||
		// 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,60 +1,64 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.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;
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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.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() {}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.*;
 | 
			
		||||
@@ -26,8 +44,8 @@ public class AudioManager {
 | 
			
		||||
 | 
			
		||||
	public static void initAL() {
 | 
			
		||||
		String defaultDeviceName = alcGetString(
 | 
			
		||||
				0,
 | 
			
		||||
				ALC_DEFAULT_DEVICE_SPECIFIER
 | 
			
		||||
			0,
 | 
			
		||||
			ALC_DEFAULT_DEVICE_SPECIFIER
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		device = alcOpenDevice(defaultDeviceName);
 | 
			
		||||
@@ -57,27 +75,30 @@ 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 {
 | 
			
		||||
	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");
 | 
			
		||||
		throw new Exception(
 | 
			
		||||
			"ERROR: The selected sound is not loaded or" +
 | 
			
		||||
				" not exists"
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static Speaker initSpeaker(String soundID) {
 | 
			
		||||
		Speaker speaker = getLastSpeaker();
 | 
			
		||||
		try {
 | 
			
		||||
			findSoundType(soundID).initSpeaker(speaker);
 | 
			
		||||
		} catch (Exception ex)
 | 
			
		||||
		{
 | 
			
		||||
		} catch (Exception ex) {
 | 
			
		||||
			throw new RuntimeException();
 | 
			
		||||
		}
 | 
			
		||||
		return speaker;
 | 
			
		||||
@@ -86,8 +107,7 @@ public class AudioManager {
 | 
			
		||||
	public static Speaker initMusicSpeaker(String soundID) {
 | 
			
		||||
		try {
 | 
			
		||||
			findSoundType(soundID).initSpeaker(musicSpeaker);
 | 
			
		||||
		} catch (Exception ex)
 | 
			
		||||
		{
 | 
			
		||||
		} catch (Exception ex) {
 | 
			
		||||
			throw new RuntimeException();
 | 
			
		||||
		}
 | 
			
		||||
		return musicSpeaker;
 | 
			
		||||
@@ -103,8 +123,7 @@ public class AudioManager {
 | 
			
		||||
	public static void loadSound(String path, String id, AudioFormat format) {
 | 
			
		||||
		if (format == AudioFormat.MONO) {
 | 
			
		||||
			soundsBuffer.add(AudioReader.readAsMono(path, id));
 | 
			
		||||
		} else
 | 
			
		||||
		{
 | 
			
		||||
		} else {
 | 
			
		||||
			soundsBuffer.add(AudioReader.readAsStereo(path, id));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -128,8 +147,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 +159,4 @@ public class AudioManager {
 | 
			
		||||
		return alGetString(AL11.AL_VERSION);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
public class AudioSystem {
 | 
			
		||||
@@ -9,8 +27,10 @@ public class AudioSystem {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static void loadAudioData() {
 | 
			
		||||
		AudioManager.loadSound("assets/sounds/block_destroy_clap.ogg",
 | 
			
		||||
				"Progressia:BlockDestroy",
 | 
			
		||||
				AudioFormat.MONO);
 | 
			
		||||
		AudioManager.loadSound(
 | 
			
		||||
			"assets/sounds/block_destroy_clap.ogg",
 | 
			
		||||
			"Progressia:BlockDestroy",
 | 
			
		||||
			AudioFormat.MONO
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 glm.vec._3.Vec3;
 | 
			
		||||
@@ -5,66 +23,68 @@ 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;
 | 
			
		||||
	private Vec3 position = new Vec3();
 | 
			
		||||
	private Vec3 velocity = new Vec3();
 | 
			
		||||
	private float pitch = 1.0f;
 | 
			
		||||
	private float gain = 1.0f;
 | 
			
		||||
 | 
			
		||||
	public Music(String id) {
 | 
			
		||||
		super(id);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public Music(String id)
 | 
			
		||||
    {
 | 
			
		||||
        super(id);
 | 
			
		||||
    }
 | 
			
		||||
	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,
 | 
			
		||||
                 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.initMusicSpeaker(this.getId());
 | 
			
		||||
		speaker.setGain(gain);
 | 
			
		||||
		speaker.setPitch(pitch);
 | 
			
		||||
		speaker.setPosition(position);
 | 
			
		||||
		speaker.setVelocity(velocity);
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (loop) {
 | 
			
		||||
            speaker.playLoop();
 | 
			
		||||
        } else {
 | 
			
		||||
            speaker.play();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
	public void setGain(float gain) {
 | 
			
		||||
		this.gain = gain;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void setGain(float gain) {
 | 
			
		||||
        this.gain = gain;
 | 
			
		||||
    }
 | 
			
		||||
	public void setPitch(float pitch) {
 | 
			
		||||
		this.pitch = pitch;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void setPitch(float pitch) { this.pitch = pitch; }
 | 
			
		||||
	public void setVelocity(Vec3 velocity) {
 | 
			
		||||
		this.velocity = velocity;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void setVelocity(Vec3 velocity) {
 | 
			
		||||
        this.velocity = velocity;
 | 
			
		||||
    }
 | 
			
		||||
	public Vec3 getPosition() {
 | 
			
		||||
		return position;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public Vec3 getPosition() { return position; }
 | 
			
		||||
	public float getGain() {
 | 
			
		||||
		return gain;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public float getGain() {
 | 
			
		||||
        return gain;
 | 
			
		||||
    }
 | 
			
		||||
	public Vec3 getVelocity() {
 | 
			
		||||
		return velocity;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public Vec3 getVelocity() {
 | 
			
		||||
        return velocity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public float getPitch() {
 | 
			
		||||
        return pitch;
 | 
			
		||||
    }
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
import glm.vec._3.Vec3;
 | 
			
		||||
@@ -5,74 +23,74 @@ import ru.windcorp.progressia.client.audio.backend.Speaker;
 | 
			
		||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
 | 
			
		||||
 | 
			
		||||
public class SoundEffect
 | 
			
		||||
        extends Namespaced {
 | 
			
		||||
	extends Namespaced {
 | 
			
		||||
 | 
			
		||||
    private Vec3 position = new Vec3();
 | 
			
		||||
    private Vec3 velocity = new Vec3();
 | 
			
		||||
    private float pitch = 1.0f;
 | 
			
		||||
    private float gain = 1.0f;
 | 
			
		||||
	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)
 | 
			
		||||
    {
 | 
			
		||||
        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 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);
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if (loop) {
 | 
			
		||||
            speaker.playLoop();
 | 
			
		||||
        } else {
 | 
			
		||||
            speaker.play();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
	public void setGain(float gain) {
 | 
			
		||||
		this.gain = gain;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void setGain(float gain) {
 | 
			
		||||
        this.gain = gain;
 | 
			
		||||
    }
 | 
			
		||||
	public void setPitch(float pitch) {
 | 
			
		||||
		this.pitch = pitch;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void setPitch(float pitch) { this.pitch = pitch; }
 | 
			
		||||
	public void setPosition(Vec3 position) {
 | 
			
		||||
		this.position = position;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void setPosition(Vec3 position) {
 | 
			
		||||
        this.position = position;
 | 
			
		||||
    }
 | 
			
		||||
	public void setVelocity(Vec3 velocity) {
 | 
			
		||||
		this.velocity = velocity;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void setVelocity(Vec3 velocity) {
 | 
			
		||||
        this.velocity = velocity;
 | 
			
		||||
    }
 | 
			
		||||
	public Vec3 getPosition() {
 | 
			
		||||
		return position;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public Vec3 getPosition() {
 | 
			
		||||
        return position;
 | 
			
		||||
    }
 | 
			
		||||
	public float getGain() {
 | 
			
		||||
		return gain;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public float getGain() {
 | 
			
		||||
        return gain;
 | 
			
		||||
    }
 | 
			
		||||
	public Vec3 getVelocity() {
 | 
			
		||||
		return velocity;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public Vec3 getVelocity() {
 | 
			
		||||
        return velocity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public float getPitch() {
 | 
			
		||||
        return pitch;
 | 
			
		||||
    }
 | 
			
		||||
	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,7 +29,8 @@ 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) {
 | 
			
		||||
@@ -22,27 +41,31 @@ public class AudioReader {
 | 
			
		||||
 | 
			
		||||
		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 readAsStereo(String path,String id) {
 | 
			
		||||
	public static SoundType readAsStereo(String path, String id) {
 | 
			
		||||
		return readAsSpecified(path, 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,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 ru.windcorp.progressia.common.util.namespaces.Namespaced;
 | 
			
		||||
@@ -12,8 +30,12 @@ public class SoundType extends Namespaced {
 | 
			
		||||
	private int format;
 | 
			
		||||
	private int audioBuffer;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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,145 @@ 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) {
 | 
			
		||||
		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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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,142 @@ 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
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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> 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 +172,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) / (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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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,130 +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.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);
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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,131 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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 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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,74 +1,76 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,107 +1,113 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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 static org.lwjgl.glfw.GLFW.*;
 | 
			
		||||
import static org.lwjgl.system.MemoryUtil.*;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.GUI;
 | 
			
		||||
 | 
			
		||||
class LWJGLInitializer {
 | 
			
		||||
	
 | 
			
		||||
	private LWJGLInitializer() {}
 | 
			
		||||
 | 
			
		||||
	public static void initialize() {
 | 
			
		||||
		checkEnvironment();
 | 
			
		||||
		initializeGLFW();
 | 
			
		||||
		createWindow();
 | 
			
		||||
		positionWindow();
 | 
			
		||||
		createWindowIcons();
 | 
			
		||||
		initializeOpenGL();
 | 
			
		||||
		setupWindowCallbacks();
 | 
			
		||||
		
 | 
			
		||||
		glfwShowWindow(GraphicsBackend.getWindowHandle());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void checkEnvironment() {
 | 
			
		||||
		// TODO Auto-generated method stub
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void initializeGLFW() {
 | 
			
		||||
		// TODO Do GLFW error handling: check glfwInit, setup error callback
 | 
			
		||||
		glfwInit();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void createWindow() {
 | 
			
		||||
		glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
 | 
			
		||||
		glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
 | 
			
		||||
		glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
 | 
			
		||||
		glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
 | 
			
		||||
		
 | 
			
		||||
		long handle = glfwCreateWindow(900, 900, "ProgressiaTest", NULL, NULL);
 | 
			
		||||
		
 | 
			
		||||
		// TODO Check that handle != NULL
 | 
			
		||||
 | 
			
		||||
		GraphicsBackend.setWindowHandle(handle);
 | 
			
		||||
		
 | 
			
		||||
		glfwSetInputMode(handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
 | 
			
		||||
		
 | 
			
		||||
		glfwMakeContextCurrent(handle);
 | 
			
		||||
		glfwSwapInterval(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void positionWindow() {
 | 
			
		||||
		// TODO Auto-generated method stub
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void createWindowIcons() {
 | 
			
		||||
		// TODO Auto-generated method stub
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void initializeOpenGL() {
 | 
			
		||||
		GL.createCapabilities();
 | 
			
		||||
		glEnable(GL_DEPTH_TEST);
 | 
			
		||||
		glEnable(GL_BLEND);
 | 
			
		||||
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
 | 
			
		||||
		RenderTaskQueue.schedule(OpenGLObjectTracker::deleteEnqueuedObjects);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void setupWindowCallbacks() {
 | 
			
		||||
		long handle = GraphicsBackend.getWindowHandle();
 | 
			
		||||
 | 
			
		||||
		glfwSetFramebufferSizeCallback(handle,
 | 
			
		||||
				GraphicsBackend::onFrameResized);
 | 
			
		||||
		
 | 
			
		||||
		glfwSetKeyCallback(handle, InputHandler::handleKeyInput);
 | 
			
		||||
		glfwSetMouseButtonCallback(handle,
 | 
			
		||||
				InputHandler::handleMouseButtonInput);
 | 
			
		||||
		
 | 
			
		||||
		glfwSetCursorPosCallback(handle, InputHandler::handleMouseMoveInput);
 | 
			
		||||
 | 
			
		||||
		glfwSetScrollCallback(handle, InputHandler::handleWheelScroll);
 | 
			
		||||
		
 | 
			
		||||
		GraphicsInterface.subscribeToInputEvents(GUI.getEventSubscriber());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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 static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
import static org.lwjgl.glfw.GLFW.*;
 | 
			
		||||
import static org.lwjgl.system.MemoryUtil.*;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.GUI;
 | 
			
		||||
 | 
			
		||||
class LWJGLInitializer {
 | 
			
		||||
 | 
			
		||||
	private LWJGLInitializer() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void initialize() {
 | 
			
		||||
		checkEnvironment();
 | 
			
		||||
		initializeGLFW();
 | 
			
		||||
		createWindow();
 | 
			
		||||
		positionWindow();
 | 
			
		||||
		createWindowIcons();
 | 
			
		||||
		initializeOpenGL();
 | 
			
		||||
		setupWindowCallbacks();
 | 
			
		||||
 | 
			
		||||
		glfwShowWindow(GraphicsBackend.getWindowHandle());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void checkEnvironment() {
 | 
			
		||||
		// TODO Auto-generated method stub
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void initializeGLFW() {
 | 
			
		||||
		// TODO Do GLFW error handling: check glfwInit, setup error callback
 | 
			
		||||
		glfwInit();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void createWindow() {
 | 
			
		||||
		glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
 | 
			
		||||
		glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
 | 
			
		||||
		glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
 | 
			
		||||
		glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
 | 
			
		||||
 | 
			
		||||
		long handle = glfwCreateWindow(900, 900, "ProgressiaTest", NULL, NULL);
 | 
			
		||||
 | 
			
		||||
		// TODO Check that handle != NULL
 | 
			
		||||
 | 
			
		||||
		GraphicsBackend.setWindowHandle(handle);
 | 
			
		||||
 | 
			
		||||
		glfwSetInputMode(handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
 | 
			
		||||
 | 
			
		||||
		glfwMakeContextCurrent(handle);
 | 
			
		||||
		glfwSwapInterval(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void positionWindow() {
 | 
			
		||||
		// TODO Auto-generated method stub
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void createWindowIcons() {
 | 
			
		||||
		// TODO Auto-generated method stub
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void initializeOpenGL() {
 | 
			
		||||
		GL.createCapabilities();
 | 
			
		||||
		glEnable(GL_DEPTH_TEST);
 | 
			
		||||
		glEnable(GL_BLEND);
 | 
			
		||||
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
 | 
			
		||||
		RenderTaskQueue.schedule(OpenGLObjectTracker::deleteEnqueuedObjects);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void setupWindowCallbacks() {
 | 
			
		||||
		long handle = GraphicsBackend.getWindowHandle();
 | 
			
		||||
 | 
			
		||||
		glfwSetFramebufferSizeCallback(
 | 
			
		||||
			handle,
 | 
			
		||||
			GraphicsBackend::onFrameResized
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		glfwSetKeyCallback(handle, InputHandler::handleKeyInput);
 | 
			
		||||
		glfwSetMouseButtonCallback(
 | 
			
		||||
			handle,
 | 
			
		||||
			InputHandler::handleMouseButtonInput
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		glfwSetCursorPosCallback(handle, InputHandler::handleMouseMoveInput);
 | 
			
		||||
 | 
			
		||||
		glfwSetScrollCallback(handle, InputHandler::handleWheelScroll);
 | 
			
		||||
 | 
			
		||||
		GraphicsInterface.subscribeToInputEvents(GUI.getEventSubscriber());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,92 +1,101 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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 java.lang.ref.PhantomReference;
 | 
			
		||||
import java.lang.ref.ReferenceQueue;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.function.IntConsumer;
 | 
			
		||||
 | 
			
		||||
public class OpenGLObjectTracker {
 | 
			
		||||
 | 
			
		||||
	public interface OpenGLDeletable {
 | 
			
		||||
		int getHandle();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static final Collection<GLPhantomReference<OpenGLDeletable>> TO_DELETE = new ArrayList<>();
 | 
			
		||||
	private static final ReferenceQueue<OpenGLDeletable> DELETE_QUEUE = new ReferenceQueue<>();
 | 
			
		||||
	
 | 
			
		||||
	public synchronized static void register(OpenGLDeletable object, IntConsumer glDeleter) {
 | 
			
		||||
		GLPhantomReference<OpenGLDeletable> glRef =
 | 
			
		||||
				new GLPhantomReference<>(object, DELETE_QUEUE, object.getHandle(), glDeleter);
 | 
			
		||||
		TO_DELETE.add(glRef);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void deleteAllObjects() {
 | 
			
		||||
		for (GLPhantomReference<OpenGLDeletable> glRef
 | 
			
		||||
				: TO_DELETE
 | 
			
		||||
			 ) {
 | 
			
		||||
			glRef.clear();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void deleteEnqueuedObjects() {
 | 
			
		||||
		while (true) {
 | 
			
		||||
			GLPhantomReference<?> glRef;
 | 
			
		||||
			glRef = (GLPhantomReference<?>) DELETE_QUEUE.poll();
 | 
			
		||||
			if (glRef == null) {
 | 
			
		||||
				break;
 | 
			
		||||
			} else {
 | 
			
		||||
				glRef.delete();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class GLPhantomReference<T> extends PhantomReference<T> {
 | 
			
		||||
 | 
			
		||||
		private final int referentGLhandle;
 | 
			
		||||
		private final IntConsumer GLDeleter;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Creates a new phantom reference that refers to the given object and
 | 
			
		||||
		 * is registered with the given queue.
 | 
			
		||||
		 *
 | 
			
		||||
		 * <p> It is possible to create a phantom reference with a {@code null}
 | 
			
		||||
		 * queue, but such a reference is completely useless: Its {@code get}
 | 
			
		||||
		 * method will always return {@code null} and, since it does not have a queue,
 | 
			
		||||
		 * it will never be enqueued.
 | 
			
		||||
		 *
 | 
			
		||||
		 * @param referent the object the new phantom reference will refer to
 | 
			
		||||
		 * @param q        the queue with which the reference is to be registered,
 | 
			
		||||
		 *                 or {@code null} if registration is not required
 | 
			
		||||
		 */
 | 
			
		||||
		public GLPhantomReference(T referent,
 | 
			
		||||
								  ReferenceQueue<? super T> q,
 | 
			
		||||
								  int referentGLhandle,
 | 
			
		||||
								  IntConsumer GLDeleter) {
 | 
			
		||||
			super(referent, q);
 | 
			
		||||
			this.referentGLhandle = referentGLhandle;
 | 
			
		||||
			this.GLDeleter = GLDeleter;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void delete() {
 | 
			
		||||
			GLDeleter.accept(referentGLhandle);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.lang.ref.PhantomReference;
 | 
			
		||||
import java.lang.ref.ReferenceQueue;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.function.IntConsumer;
 | 
			
		||||
 | 
			
		||||
public class OpenGLObjectTracker {
 | 
			
		||||
 | 
			
		||||
	public interface OpenGLDeletable {
 | 
			
		||||
		int getHandle();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static final Collection<GLPhantomReference<OpenGLDeletable>> TO_DELETE = new ArrayList<>();
 | 
			
		||||
	private static final ReferenceQueue<OpenGLDeletable> DELETE_QUEUE = new ReferenceQueue<>();
 | 
			
		||||
 | 
			
		||||
	public synchronized static void register(OpenGLDeletable object, IntConsumer glDeleter) {
 | 
			
		||||
		GLPhantomReference<OpenGLDeletable> glRef = new GLPhantomReference<>(
 | 
			
		||||
			object,
 | 
			
		||||
			DELETE_QUEUE,
 | 
			
		||||
			object.getHandle(),
 | 
			
		||||
			glDeleter
 | 
			
		||||
		);
 | 
			
		||||
		TO_DELETE.add(glRef);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void deleteAllObjects() {
 | 
			
		||||
		for (
 | 
			
		||||
			GLPhantomReference<OpenGLDeletable> glRef : TO_DELETE
 | 
			
		||||
		) {
 | 
			
		||||
			glRef.clear();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void deleteEnqueuedObjects() {
 | 
			
		||||
		while (true) {
 | 
			
		||||
			GLPhantomReference<?> glRef;
 | 
			
		||||
			glRef = (GLPhantomReference<?>) DELETE_QUEUE.poll();
 | 
			
		||||
			if (glRef == null) {
 | 
			
		||||
				break;
 | 
			
		||||
			} else {
 | 
			
		||||
				glRef.delete();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static class GLPhantomReference<T> extends PhantomReference<T> {
 | 
			
		||||
 | 
			
		||||
		private final int referentGLhandle;
 | 
			
		||||
		private final IntConsumer GLDeleter;
 | 
			
		||||
 | 
			
		||||
		/**
 | 
			
		||||
		 * Creates a new phantom reference that refers to the given object and
 | 
			
		||||
		 * is registered with the given queue.
 | 
			
		||||
		 * <p>
 | 
			
		||||
		 * It is possible to create a phantom reference with a {@code null}
 | 
			
		||||
		 * queue, but such a reference is completely useless: Its {@code get}
 | 
			
		||||
		 * method will always return {@code null} and, since it does not have a
 | 
			
		||||
		 * queue,
 | 
			
		||||
		 * it will never be enqueued.
 | 
			
		||||
		 *
 | 
			
		||||
		 * @param referent the object the new phantom reference will refer to
 | 
			
		||||
		 * @param q        the queue with which the reference is to be
 | 
			
		||||
		 *                 registered,
 | 
			
		||||
		 *                 or {@code null} if registration is not required
 | 
			
		||||
		 */
 | 
			
		||||
		public GLPhantomReference(
 | 
			
		||||
			T referent,
 | 
			
		||||
			ReferenceQueue<? super T> q,
 | 
			
		||||
			int referentGLhandle,
 | 
			
		||||
			IntConsumer GLDeleter
 | 
			
		||||
		) {
 | 
			
		||||
			super(referent, q);
 | 
			
		||||
			this.referentGLhandle = referentGLhandle;
 | 
			
		||||
			this.GLDeleter = GLDeleter;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void delete() {
 | 
			
		||||
			GLDeleter.accept(referentGLhandle);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,54 +1,56 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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 ru.windcorp.jputil.functions.ThrowingRunnable;
 | 
			
		||||
import ru.windcorp.progressia.common.util.TaskQueue;
 | 
			
		||||
 | 
			
		||||
public class RenderTaskQueue {
 | 
			
		||||
	
 | 
			
		||||
	private static final TaskQueue HANDLER =
 | 
			
		||||
			new TaskQueue(GraphicsInterface::isRenderThread);
 | 
			
		||||
	
 | 
			
		||||
	public static void schedule(Runnable task) {
 | 
			
		||||
		HANDLER.schedule(task);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static void removeScheduled(Runnable task) {
 | 
			
		||||
		HANDLER.removeScheduled(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void invokeLater(Runnable task) {
 | 
			
		||||
		HANDLER.invokeLater(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void invokeNow(Runnable task) {
 | 
			
		||||
		HANDLER.invokeNow(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static <E extends Exception> void waitAndInvoke(
 | 
			
		||||
			ThrowingRunnable<E> task
 | 
			
		||||
	) throws InterruptedException, E {
 | 
			
		||||
		HANDLER.waitAndInvoke(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void runTasks() {
 | 
			
		||||
		HANDLER.runTasks();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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 ru.windcorp.jputil.functions.ThrowingRunnable;
 | 
			
		||||
import ru.windcorp.progressia.common.util.TaskQueue;
 | 
			
		||||
 | 
			
		||||
public class RenderTaskQueue {
 | 
			
		||||
 | 
			
		||||
	private static final TaskQueue HANDLER = new TaskQueue(GraphicsInterface::isRenderThread);
 | 
			
		||||
 | 
			
		||||
	public static void schedule(Runnable task) {
 | 
			
		||||
		HANDLER.schedule(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void removeScheduled(Runnable task) {
 | 
			
		||||
		HANDLER.removeScheduled(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void invokeLater(Runnable task) {
 | 
			
		||||
		HANDLER.invokeLater(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void invokeNow(Runnable task) {
 | 
			
		||||
		HANDLER.invokeNow(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static <E extends Exception> void waitAndInvoke(
 | 
			
		||||
		ThrowingRunnable<E> task
 | 
			
		||||
	)
 | 
			
		||||
		throws InterruptedException,
 | 
			
		||||
		E {
 | 
			
		||||
		HANDLER.waitAndInvoke(task);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void runTasks() {
 | 
			
		||||
		HANDLER.runTasks();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,79 +1,80 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.glfw.GLFW.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.audio.AudioManager;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.GUI;
 | 
			
		||||
 | 
			
		||||
class RenderThread extends Thread {
 | 
			
		||||
	
 | 
			
		||||
	public RenderThread() {
 | 
			
		||||
		super("Render");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public void run() {
 | 
			
		||||
		LWJGLInitializer.initialize();
 | 
			
		||||
		mainLoop();
 | 
			
		||||
		freeResources();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void mainLoop() {
 | 
			
		||||
		while (shouldRun()) {
 | 
			
		||||
			GraphicsBackend.startFrame();
 | 
			
		||||
			RenderTaskQueue.runTasks();
 | 
			
		||||
			render();
 | 
			
		||||
			waitForFrame();
 | 
			
		||||
			GraphicsBackend.endFrame();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		System.exit(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void render() {
 | 
			
		||||
		clear();
 | 
			
		||||
		doRender();
 | 
			
		||||
		glfwPollEvents();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void clear() {
 | 
			
		||||
		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 | 
			
		||||
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void doRender() {
 | 
			
		||||
		GUI.render();
 | 
			
		||||
		AudioManager.update();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void waitForFrame() {
 | 
			
		||||
		glfwSwapBuffers(GraphicsBackend.getWindowHandle());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void freeResources() {
 | 
			
		||||
		OpenGLObjectTracker.deleteAllObjects();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private boolean shouldRun() {
 | 
			
		||||
		return !glfwWindowShouldClose(GraphicsBackend.getWindowHandle());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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 static org.lwjgl.glfw.GLFW.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.audio.AudioManager;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.GUI;
 | 
			
		||||
 | 
			
		||||
class RenderThread extends Thread {
 | 
			
		||||
 | 
			
		||||
	public RenderThread() {
 | 
			
		||||
		super("Render");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public void run() {
 | 
			
		||||
		LWJGLInitializer.initialize();
 | 
			
		||||
		mainLoop();
 | 
			
		||||
		freeResources();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void mainLoop() {
 | 
			
		||||
		while (shouldRun()) {
 | 
			
		||||
			GraphicsBackend.startFrame();
 | 
			
		||||
			RenderTaskQueue.runTasks();
 | 
			
		||||
			render();
 | 
			
		||||
			waitForFrame();
 | 
			
		||||
			GraphicsBackend.endFrame();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		System.exit(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void render() {
 | 
			
		||||
		clear();
 | 
			
		||||
		doRender();
 | 
			
		||||
		glfwPollEvents();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void clear() {
 | 
			
		||||
		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 | 
			
		||||
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void doRender() {
 | 
			
		||||
		GUI.render();
 | 
			
		||||
		AudioManager.update();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void waitForFrame() {
 | 
			
		||||
		glfwSwapBuffers(GraphicsBackend.getWindowHandle());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void freeResources() {
 | 
			
		||||
		OpenGLObjectTracker.deleteAllObjects();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private boolean shouldRun() {
 | 
			
		||||
		return !glfwWindowShouldClose(GraphicsBackend.getWindowHandle());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,38 +1,39 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.GL15.GL_DYNAMIC_DRAW;
 | 
			
		||||
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
 | 
			
		||||
import static org.lwjgl.opengl.GL15.GL_STREAM_DRAW;
 | 
			
		||||
 | 
			
		||||
public enum Usage { // TODO add _COPY and _READ, pref. as another enum
 | 
			
		||||
	STATIC(GL_STATIC_DRAW),
 | 
			
		||||
	DYNAMIC(GL_DYNAMIC_DRAW),
 | 
			
		||||
	STREAM(GL_STREAM_DRAW);
 | 
			
		||||
	
 | 
			
		||||
	private final int glCode;
 | 
			
		||||
	
 | 
			
		||||
	private Usage(int glCode) {
 | 
			
		||||
		this.glCode = glCode;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public int getGlCode() {
 | 
			
		||||
		return glCode;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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 static org.lwjgl.opengl.GL15.GL_DYNAMIC_DRAW;
 | 
			
		||||
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
 | 
			
		||||
import static org.lwjgl.opengl.GL15.GL_STREAM_DRAW;
 | 
			
		||||
 | 
			
		||||
public enum Usage { // TODO add _COPY and _READ, pref. as another enum
 | 
			
		||||
	STATIC(GL_STATIC_DRAW),
 | 
			
		||||
	DYNAMIC(GL_DYNAMIC_DRAW),
 | 
			
		||||
	STREAM(GL_STREAM_DRAW);
 | 
			
		||||
 | 
			
		||||
	private final int glCode;
 | 
			
		||||
 | 
			
		||||
	private Usage(int glCode) {
 | 
			
		||||
		this.glCode = glCode;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int getGlCode() {
 | 
			
		||||
		return glCode;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,199 +1,200 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.GL20.*;
 | 
			
		||||
 | 
			
		||||
import java.nio.*;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL20;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
 | 
			
		||||
 | 
			
		||||
public class VertexBufferObject implements OpenGLDeletable {
 | 
			
		||||
	
 | 
			
		||||
	public static enum BindTarget {
 | 
			
		||||
		ARRAY(GL_ARRAY_BUFFER),
 | 
			
		||||
		ELEMENT_ARRAY(GL_ELEMENT_ARRAY_BUFFER);
 | 
			
		||||
		
 | 
			
		||||
		private final int glCode;
 | 
			
		||||
		
 | 
			
		||||
		private BindTarget(int glCode) {
 | 
			
		||||
			this.glCode = glCode;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		public int getGlCode() {
 | 
			
		||||
			return glCode;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private final int handle;
 | 
			
		||||
	
 | 
			
		||||
	private long length = 0;
 | 
			
		||||
	private final Usage usage;
 | 
			
		||||
	
 | 
			
		||||
	public VertexBufferObject(Usage usage) {
 | 
			
		||||
		handle = glGenBuffers();
 | 
			
		||||
		OpenGLObjectTracker.register(this, GL20::glDeleteBuffers);
 | 
			
		||||
 | 
			
		||||
		this.usage = usage;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(ByteBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(double[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Double.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(DoubleBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Double.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(float[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Float.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(FloatBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Float.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Integer.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(IntBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Integer.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(long[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Long.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(LongBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Long.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(short[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Short.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(ShortBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Short.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void initData(long length) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, length, usage.getGlCode());
 | 
			
		||||
		this.length = length;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, ByteBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, double[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, DoubleBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, float[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, FloatBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, int[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, IntBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, long[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, LongBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, short[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void setData(int offset, ShortBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void bind(BindTarget target) {
 | 
			
		||||
		glBindBuffer(target.getGlCode(), handle);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public long getLength() {
 | 
			
		||||
		return length;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public Usage getUsage() {
 | 
			
		||||
		return usage;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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 static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
 | 
			
		||||
import java.nio.*;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL20;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
 | 
			
		||||
 | 
			
		||||
public class VertexBufferObject implements OpenGLDeletable {
 | 
			
		||||
 | 
			
		||||
	public static enum BindTarget {
 | 
			
		||||
		ARRAY(GL_ARRAY_BUFFER),
 | 
			
		||||
		ELEMENT_ARRAY(GL_ELEMENT_ARRAY_BUFFER);
 | 
			
		||||
 | 
			
		||||
		private final int glCode;
 | 
			
		||||
 | 
			
		||||
		private BindTarget(int glCode) {
 | 
			
		||||
			this.glCode = glCode;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int getGlCode() {
 | 
			
		||||
			return glCode;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private final int handle;
 | 
			
		||||
 | 
			
		||||
	private long length = 0;
 | 
			
		||||
	private final Usage usage;
 | 
			
		||||
 | 
			
		||||
	public VertexBufferObject(Usage usage) {
 | 
			
		||||
		handle = glGenBuffers();
 | 
			
		||||
		OpenGLObjectTracker.register(this, GL20::glDeleteBuffers);
 | 
			
		||||
 | 
			
		||||
		this.usage = usage;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(ByteBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(double[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Double.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(DoubleBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Double.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(float[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Float.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(FloatBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Float.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Integer.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(IntBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Integer.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(long[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Long.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(LongBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Long.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(short[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.length * Short.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(ShortBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, data, usage.getGlCode());
 | 
			
		||||
		length = data.remaining() * Short.BYTES;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void initData(long length) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferData(GL_ARRAY_BUFFER, length, usage.getGlCode());
 | 
			
		||||
		this.length = length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, ByteBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, double[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, DoubleBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, float[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, FloatBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, int[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, IntBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, long[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, LongBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, short[] data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void setData(int offset, ShortBuffer data) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, handle);
 | 
			
		||||
		glBufferSubData(GL_ARRAY_BUFFER, offset, data);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void bind(BindTarget target) {
 | 
			
		||||
		glBindBuffer(target.getGlCode(), handle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public long getLength() {
 | 
			
		||||
		return length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Usage getUsage() {
 | 
			
		||||
		return usage;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,93 +1,95 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.common.resource.Resource;
 | 
			
		||||
 | 
			
		||||
public class CombinedShader extends Shader {
 | 
			
		||||
	
 | 
			
		||||
	public CombinedShader(String... resources) {
 | 
			
		||||
		super(getTypeOf(resources), combine(resources));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static ShaderType getTypeOf(String[] resources) {
 | 
			
		||||
		ShaderType first = ShaderType.guessByResourceName(resources[0]);
 | 
			
		||||
		
 | 
			
		||||
		for (int i = 1; i < resources.length; ++i) {
 | 
			
		||||
			if (ShaderType.guessByResourceName(resources[i]) != first) {
 | 
			
		||||
				throw new IllegalArgumentException(
 | 
			
		||||
						"Deduced shader types of "
 | 
			
		||||
								+ resources[0]
 | 
			
		||||
								+ " and "
 | 
			
		||||
								+ resources[i]
 | 
			
		||||
								+ " differ"
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return first;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static String combine(String[] resources) {
 | 
			
		||||
		StringBuilder accumulator = new StringBuilder("#version 120\n");
 | 
			
		||||
		
 | 
			
		||||
		for (String resourceName : resources) {
 | 
			
		||||
			Resource resource = getShaderResource(resourceName);
 | 
			
		||||
			
 | 
			
		||||
			accumulator.append("\n// START " + resourceName);
 | 
			
		||||
			accumulator.append(stripVersionAnnotations(resource));
 | 
			
		||||
			accumulator.append('\n');
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return accumulator.toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static String stripVersionAnnotations(Resource resource) {
 | 
			
		||||
		String contents = resource.readAsString();
 | 
			
		||||
		
 | 
			
		||||
		int versionIndex;
 | 
			
		||||
		for (versionIndex = 0; versionIndex < contents.length(); ++versionIndex)
 | 
			
		||||
		{
 | 
			
		||||
			if (!Character.isWhitespace(contents.codePointAt(versionIndex)))
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (versionIndex < contents.length()) {
 | 
			
		||||
			if (contents.codePointAt(versionIndex) == '#') {
 | 
			
		||||
				final String versionAnnotation = "#version ";
 | 
			
		||||
				
 | 
			
		||||
				if (contents.regionMatches(
 | 
			
		||||
						versionIndex,
 | 
			
		||||
						versionAnnotation,
 | 
			
		||||
						0,
 | 
			
		||||
						versionAnnotation.length()
 | 
			
		||||
				)) {
 | 
			
		||||
					contents = contents.substring(
 | 
			
		||||
							versionIndex
 | 
			
		||||
							+ versionAnnotation.length()
 | 
			
		||||
							+ "120".length()
 | 
			
		||||
					);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return contents;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.common.resource.Resource;
 | 
			
		||||
 | 
			
		||||
public class CombinedShader extends Shader {
 | 
			
		||||
 | 
			
		||||
	public CombinedShader(String... resources) {
 | 
			
		||||
		super(getTypeOf(resources), combine(resources));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static ShaderType getTypeOf(String[] resources) {
 | 
			
		||||
		ShaderType first = ShaderType.guessByResourceName(resources[0]);
 | 
			
		||||
 | 
			
		||||
		for (int i = 1; i < resources.length; ++i) {
 | 
			
		||||
			if (ShaderType.guessByResourceName(resources[i]) != first) {
 | 
			
		||||
				throw new IllegalArgumentException(
 | 
			
		||||
					"Deduced shader types of "
 | 
			
		||||
						+ resources[0]
 | 
			
		||||
						+ " and "
 | 
			
		||||
						+ resources[i]
 | 
			
		||||
						+ " differ"
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return first;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static String combine(String[] resources) {
 | 
			
		||||
		StringBuilder accumulator = new StringBuilder("#version 120\n");
 | 
			
		||||
 | 
			
		||||
		for (String resourceName : resources) {
 | 
			
		||||
			Resource resource = getShaderResource(resourceName);
 | 
			
		||||
 | 
			
		||||
			accumulator.append("\n// START " + resourceName);
 | 
			
		||||
			accumulator.append(stripVersionAnnotations(resource));
 | 
			
		||||
			accumulator.append('\n');
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return accumulator.toString();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static String stripVersionAnnotations(Resource resource) {
 | 
			
		||||
		String contents = resource.readAsString();
 | 
			
		||||
 | 
			
		||||
		int versionIndex;
 | 
			
		||||
		for (versionIndex = 0; versionIndex < contents.length(); ++versionIndex) {
 | 
			
		||||
			if (!Character.isWhitespace(contents.codePointAt(versionIndex)))
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (versionIndex < contents.length()) {
 | 
			
		||||
			if (contents.codePointAt(versionIndex) == '#') {
 | 
			
		||||
				final String versionAnnotation = "#version ";
 | 
			
		||||
 | 
			
		||||
				if (
 | 
			
		||||
					contents.regionMatches(
 | 
			
		||||
						versionIndex,
 | 
			
		||||
						versionAnnotation,
 | 
			
		||||
						0,
 | 
			
		||||
						versionAnnotation.length()
 | 
			
		||||
					)
 | 
			
		||||
				) {
 | 
			
		||||
					contents = contents.substring(
 | 
			
		||||
						versionIndex
 | 
			
		||||
							+ versionAnnotation.length()
 | 
			
		||||
							+ "120".length()
 | 
			
		||||
					);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return contents;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,63 +1,66 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL20;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.Attribute;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.Uniform;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Program implements OpenGLDeletable {
 | 
			
		||||
 | 
			
		||||
	private int handle;
 | 
			
		||||
 | 
			
		||||
	public Program(Shader vertexShader, Shader fragmentShader) {
 | 
			
		||||
		handle = glCreateProgram();
 | 
			
		||||
		OpenGLObjectTracker.register(this, GL20::glDeleteProgram);
 | 
			
		||||
 | 
			
		||||
		glAttachShader(handle, vertexShader.getHandle());
 | 
			
		||||
		glAttachShader(handle, fragmentShader.getHandle());
 | 
			
		||||
 | 
			
		||||
		glLinkProgram(handle);
 | 
			
		||||
 | 
			
		||||
		if (glGetProgrami(handle, GL_LINK_STATUS) == GL_FALSE) {
 | 
			
		||||
			throw CrashReports.report(null, "Bad program:\n%s", glGetProgramInfoLog(handle));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Attribute getAttribute(String name) {
 | 
			
		||||
		return new Attribute(glGetAttribLocation(handle, name), this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform getUniform(String name) {
 | 
			
		||||
		return new Uniform(glGetUniformLocation(handle, name), this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void use() {
 | 
			
		||||
		glUseProgram(handle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public int getHandle() { return handle; }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL20;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.attributes.Attribute;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.uniforms.Uniform;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Program implements OpenGLDeletable {
 | 
			
		||||
 | 
			
		||||
	private int handle;
 | 
			
		||||
 | 
			
		||||
	public Program(Shader vertexShader, Shader fragmentShader) {
 | 
			
		||||
		handle = glCreateProgram();
 | 
			
		||||
		OpenGLObjectTracker.register(this, GL20::glDeleteProgram);
 | 
			
		||||
 | 
			
		||||
		glAttachShader(handle, vertexShader.getHandle());
 | 
			
		||||
		glAttachShader(handle, fragmentShader.getHandle());
 | 
			
		||||
 | 
			
		||||
		glLinkProgram(handle);
 | 
			
		||||
 | 
			
		||||
		if (glGetProgrami(handle, GL_LINK_STATUS) == GL_FALSE) {
 | 
			
		||||
			throw CrashReports.report(null, "Bad program:\n%s", glGetProgramInfoLog(handle));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Attribute getAttribute(String name) {
 | 
			
		||||
		return new Attribute(glGetAttribLocation(handle, name), this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform getUniform(String name) {
 | 
			
		||||
		return new Uniform(glGetUniformLocation(handle, name), this);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void use() {
 | 
			
		||||
		glUseProgram(handle);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,103 +1,108 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL20;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
 | 
			
		||||
import ru.windcorp.progressia.common.resource.Resource;
 | 
			
		||||
import ru.windcorp.progressia.common.resource.ResourceManager;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Shader implements OpenGLDeletable {
 | 
			
		||||
 | 
			
		||||
	public static enum ShaderType {
 | 
			
		||||
		VERTEX(GL_VERTEX_SHADER), FRAGMENT(GL_FRAGMENT_SHADER);
 | 
			
		||||
 | 
			
		||||
		private final int glCode;
 | 
			
		||||
 | 
			
		||||
		private ShaderType(int glCode) {
 | 
			
		||||
			this.glCode = glCode;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int getGlCode() {
 | 
			
		||||
			return glCode;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static ShaderType guessByResourceName(String resource) {
 | 
			
		||||
			resource = resource.toLowerCase(Locale.ENGLISH);
 | 
			
		||||
 | 
			
		||||
			if (resource.contains("vertex")) return VERTEX;
 | 
			
		||||
			if (resource.contains("fragment")) return FRAGMENT;
 | 
			
		||||
			if (resource.contains("vsh")) return VERTEX;
 | 
			
		||||
			if (resource.contains("fsh")) return FRAGMENT;
 | 
			
		||||
			
 | 
			
		||||
			throw new IllegalArgumentException(
 | 
			
		||||
					"Cannot deduce shader type from resource name \"" +
 | 
			
		||||
					resource + "\""
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static final String SHADER_ASSETS_PREFIX = "assets/shaders/";
 | 
			
		||||
 | 
			
		||||
	protected static Resource getShaderResource(String name) {
 | 
			
		||||
		return ResourceManager.getResource(SHADER_ASSETS_PREFIX + name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private final int handle;
 | 
			
		||||
	private final ShaderType type;
 | 
			
		||||
 | 
			
		||||
	public Shader(ShaderType type, String source) {
 | 
			
		||||
		handle = glCreateShader(type.getGlCode());
 | 
			
		||||
		OpenGLObjectTracker.register(this, GL20::glDeleteShader);
 | 
			
		||||
 | 
			
		||||
		this.type = type;
 | 
			
		||||
 | 
			
		||||
		glShaderSource(handle, source);
 | 
			
		||||
		glCompileShader(handle);
 | 
			
		||||
 | 
			
		||||
		if (glGetShaderi(handle, GL_COMPILE_STATUS) == GL_FALSE) {
 | 
			
		||||
			System.out.println("***************** ERROR ******************");
 | 
			
		||||
			System.out.println(source);
 | 
			
		||||
			throw CrashReports.report(null, "Bad shader:\n %s", glGetShaderInfoLog(handle));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Shader(String resource) {
 | 
			
		||||
		this(
 | 
			
		||||
				ShaderType.guessByResourceName(resource),
 | 
			
		||||
				getShaderResource(resource).readAsString()
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public ShaderType getType() {
 | 
			
		||||
		return type;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
 | 
			
		||||
import org.lwjgl.opengl.GL20;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.OpenGLObjectTracker.OpenGLDeletable;
 | 
			
		||||
import ru.windcorp.progressia.common.resource.Resource;
 | 
			
		||||
import ru.windcorp.progressia.common.resource.ResourceManager;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Shader implements OpenGLDeletable {
 | 
			
		||||
 | 
			
		||||
	public static enum ShaderType {
 | 
			
		||||
		VERTEX(GL_VERTEX_SHADER), FRAGMENT(GL_FRAGMENT_SHADER);
 | 
			
		||||
 | 
			
		||||
		private final int glCode;
 | 
			
		||||
 | 
			
		||||
		private ShaderType(int glCode) {
 | 
			
		||||
			this.glCode = glCode;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public int getGlCode() {
 | 
			
		||||
			return glCode;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static ShaderType guessByResourceName(String resource) {
 | 
			
		||||
			resource = resource.toLowerCase(Locale.ENGLISH);
 | 
			
		||||
 | 
			
		||||
			if (resource.contains("vertex"))
 | 
			
		||||
				return VERTEX;
 | 
			
		||||
			if (resource.contains("fragment"))
 | 
			
		||||
				return FRAGMENT;
 | 
			
		||||
			if (resource.contains("vsh"))
 | 
			
		||||
				return VERTEX;
 | 
			
		||||
			if (resource.contains("fsh"))
 | 
			
		||||
				return FRAGMENT;
 | 
			
		||||
 | 
			
		||||
			throw new IllegalArgumentException(
 | 
			
		||||
				"Cannot deduce shader type from resource name \"" +
 | 
			
		||||
					resource + "\""
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static final String SHADER_ASSETS_PREFIX = "assets/shaders/";
 | 
			
		||||
 | 
			
		||||
	protected static Resource getShaderResource(String name) {
 | 
			
		||||
		return ResourceManager.getResource(SHADER_ASSETS_PREFIX + name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private final int handle;
 | 
			
		||||
	private final ShaderType type;
 | 
			
		||||
 | 
			
		||||
	public Shader(ShaderType type, String source) {
 | 
			
		||||
		handle = glCreateShader(type.getGlCode());
 | 
			
		||||
		OpenGLObjectTracker.register(this, GL20::glDeleteShader);
 | 
			
		||||
 | 
			
		||||
		this.type = type;
 | 
			
		||||
 | 
			
		||||
		glShaderSource(handle, source);
 | 
			
		||||
		glCompileShader(handle);
 | 
			
		||||
 | 
			
		||||
		if (glGetShaderi(handle, GL_COMPILE_STATUS) == GL_FALSE) {
 | 
			
		||||
			System.out.println("***************** ERROR ******************");
 | 
			
		||||
			System.out.println(source);
 | 
			
		||||
			throw CrashReports.report(null, "Bad shader:\n %s", glGetShaderInfoLog(handle));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Shader(String resource) {
 | 
			
		||||
		this(
 | 
			
		||||
			ShaderType.guessByResourceName(resource),
 | 
			
		||||
			getShaderResource(resource).readAsString()
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public ShaderType getType() {
 | 
			
		||||
		return type;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,49 +1,50 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders.attributes;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Attribute {
 | 
			
		||||
 | 
			
		||||
	protected final int handle;
 | 
			
		||||
	private final Program program;
 | 
			
		||||
 | 
			
		||||
	public Attribute(int handle, Program program) {
 | 
			
		||||
		if (handle < 0) {
 | 
			
		||||
			throw CrashReports.report(null, "Bad handle: %d", handle);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.handle = handle;
 | 
			
		||||
		this.program = program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Program getProgram() {
 | 
			
		||||
		return program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public AttributeVertexArray asVertexArray() {
 | 
			
		||||
		return new AttributeVertexArray(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders.attributes;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Attribute {
 | 
			
		||||
 | 
			
		||||
	protected final int handle;
 | 
			
		||||
	private final Program program;
 | 
			
		||||
 | 
			
		||||
	public Attribute(int handle, Program program) {
 | 
			
		||||
		if (handle < 0) {
 | 
			
		||||
			throw CrashReports.report(null, "Bad handle: %d", handle);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.handle = handle;
 | 
			
		||||
		this.program = program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Program getProgram() {
 | 
			
		||||
		return program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public AttributeVertexArray asVertexArray() {
 | 
			
		||||
		return new AttributeVertexArray(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,114 +1,154 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders.attributes;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
 | 
			
		||||
import java.nio.ByteBuffer;
 | 
			
		||||
import java.nio.FloatBuffer;
 | 
			
		||||
import java.nio.IntBuffer;
 | 
			
		||||
import java.nio.ShortBuffer;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.VertexBufferObject;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class AttributeVertexArray extends Attribute {
 | 
			
		||||
	
 | 
			
		||||
	private boolean isEnabled = false;
 | 
			
		||||
 | 
			
		||||
	public AttributeVertexArray(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void enable() {
 | 
			
		||||
		if (!isEnabled) {
 | 
			
		||||
			glEnableVertexAttribArray(handle);
 | 
			
		||||
			isEnabled = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void disable() {
 | 
			
		||||
		if (isEnabled) {
 | 
			
		||||
			glDisableVertexAttribArray(handle);
 | 
			
		||||
			isEnabled = false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(
 | 
			
		||||
			int size, boolean normalized, int stride,
 | 
			
		||||
			ByteBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
				handle,
 | 
			
		||||
				size, GL_BYTE, normalized, stride, pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(
 | 
			
		||||
			int size, boolean normalized, int stride,
 | 
			
		||||
			FloatBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
				handle,
 | 
			
		||||
				size, GL_FLOAT, normalized, stride, pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(
 | 
			
		||||
			int size, boolean normalized, int stride,
 | 
			
		||||
			IntBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
				handle,
 | 
			
		||||
				size, GL_INT, normalized, stride, pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(
 | 
			
		||||
			int size, boolean normalized, int stride,
 | 
			
		||||
			ShortBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
				handle,
 | 
			
		||||
				size, GL_SHORT, normalized, stride, pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(
 | 
			
		||||
			int size, int type, boolean normalized, int stride,
 | 
			
		||||
			long pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
				handle,
 | 
			
		||||
				size, type, normalized, stride, pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(
 | 
			
		||||
			int size, int type, boolean normalized, int stride,
 | 
			
		||||
			VertexBufferObject vbo, long offset
 | 
			
		||||
	) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, vbo.getHandle());
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
				handle,
 | 
			
		||||
				size, type, normalized, stride, offset
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders.attributes;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL11.*;
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
 | 
			
		||||
import java.nio.ByteBuffer;
 | 
			
		||||
import java.nio.FloatBuffer;
 | 
			
		||||
import java.nio.IntBuffer;
 | 
			
		||||
import java.nio.ShortBuffer;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.VertexBufferObject;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class AttributeVertexArray extends Attribute {
 | 
			
		||||
 | 
			
		||||
	private boolean isEnabled = false;
 | 
			
		||||
 | 
			
		||||
	public AttributeVertexArray(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void enable() {
 | 
			
		||||
		if (!isEnabled) {
 | 
			
		||||
			glEnableVertexAttribArray(handle);
 | 
			
		||||
			isEnabled = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void disable() {
 | 
			
		||||
		if (isEnabled) {
 | 
			
		||||
			glDisableVertexAttribArray(handle);
 | 
			
		||||
			isEnabled = false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(
 | 
			
		||||
		int size,
 | 
			
		||||
		boolean normalized,
 | 
			
		||||
		int stride,
 | 
			
		||||
		ByteBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
			handle,
 | 
			
		||||
			size,
 | 
			
		||||
			GL_BYTE,
 | 
			
		||||
			normalized,
 | 
			
		||||
			stride,
 | 
			
		||||
			pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(
 | 
			
		||||
		int size,
 | 
			
		||||
		boolean normalized,
 | 
			
		||||
		int stride,
 | 
			
		||||
		FloatBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
			handle,
 | 
			
		||||
			size,
 | 
			
		||||
			GL_FLOAT,
 | 
			
		||||
			normalized,
 | 
			
		||||
			stride,
 | 
			
		||||
			pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(
 | 
			
		||||
		int size,
 | 
			
		||||
		boolean normalized,
 | 
			
		||||
		int stride,
 | 
			
		||||
		IntBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
			handle,
 | 
			
		||||
			size,
 | 
			
		||||
			GL_INT,
 | 
			
		||||
			normalized,
 | 
			
		||||
			stride,
 | 
			
		||||
			pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(
 | 
			
		||||
		int size,
 | 
			
		||||
		boolean normalized,
 | 
			
		||||
		int stride,
 | 
			
		||||
		ShortBuffer pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
			handle,
 | 
			
		||||
			size,
 | 
			
		||||
			GL_SHORT,
 | 
			
		||||
			normalized,
 | 
			
		||||
			stride,
 | 
			
		||||
			pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(
 | 
			
		||||
		int size,
 | 
			
		||||
		int type,
 | 
			
		||||
		boolean normalized,
 | 
			
		||||
		int stride,
 | 
			
		||||
		long pointer
 | 
			
		||||
	) {
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
			handle,
 | 
			
		||||
			size,
 | 
			
		||||
			type,
 | 
			
		||||
			normalized,
 | 
			
		||||
			stride,
 | 
			
		||||
			pointer
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(
 | 
			
		||||
		int size,
 | 
			
		||||
		int type,
 | 
			
		||||
		boolean normalized,
 | 
			
		||||
		int stride,
 | 
			
		||||
		VertexBufferObject vbo,
 | 
			
		||||
		long offset
 | 
			
		||||
	) {
 | 
			
		||||
		glBindBuffer(GL_ARRAY_BUFFER, vbo.getHandle());
 | 
			
		||||
		glVertexAttribPointer(
 | 
			
		||||
			handle,
 | 
			
		||||
			size,
 | 
			
		||||
			type,
 | 
			
		||||
			normalized,
 | 
			
		||||
			stride,
 | 
			
		||||
			offset
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,89 +1,90 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Uniform {
 | 
			
		||||
 | 
			
		||||
	protected final int handle;
 | 
			
		||||
	private final Program program;
 | 
			
		||||
 | 
			
		||||
	public Uniform(int handle, Program program) {
 | 
			
		||||
		if (handle < 0) {
 | 
			
		||||
			throw CrashReports.report(null, "Bad handle: %d", handle);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.handle = handle;
 | 
			
		||||
		this.program = program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Program getProgram() {
 | 
			
		||||
		return program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform1Float as1Float() {
 | 
			
		||||
		return new Uniform1Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform1Int as1Int() {
 | 
			
		||||
		return new Uniform1Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform2Float as2Float() {
 | 
			
		||||
		return new Uniform2Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform2Int as2Int() {
 | 
			
		||||
		return new Uniform2Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform3Float as3Float() {
 | 
			
		||||
		return new Uniform3Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform3Int as3Int() {
 | 
			
		||||
		return new Uniform3Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform4Float as4Float() {
 | 
			
		||||
		return new Uniform4Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform4Int as4Int() {
 | 
			
		||||
		return new Uniform4Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform2Matrix as2Matrix() {
 | 
			
		||||
		return new Uniform2Matrix(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform3Matrix as3Matrix() {
 | 
			
		||||
		return new Uniform3Matrix(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform4Matrix as4Matrix() {
 | 
			
		||||
		return new Uniform4Matrix(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
 | 
			
		||||
 | 
			
		||||
public class Uniform {
 | 
			
		||||
 | 
			
		||||
	protected final int handle;
 | 
			
		||||
	private final Program program;
 | 
			
		||||
 | 
			
		||||
	public Uniform(int handle, Program program) {
 | 
			
		||||
		if (handle < 0) {
 | 
			
		||||
			throw CrashReports.report(null, "Bad handle: %d", handle);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.handle = handle;
 | 
			
		||||
		this.program = program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int getHandle() {
 | 
			
		||||
		return handle;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Program getProgram() {
 | 
			
		||||
		return program;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform1Float as1Float() {
 | 
			
		||||
		return new Uniform1Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform1Int as1Int() {
 | 
			
		||||
		return new Uniform1Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform2Float as2Float() {
 | 
			
		||||
		return new Uniform2Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform2Int as2Int() {
 | 
			
		||||
		return new Uniform2Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform3Float as3Float() {
 | 
			
		||||
		return new Uniform3Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform3Int as3Int() {
 | 
			
		||||
		return new Uniform3Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform4Float as4Float() {
 | 
			
		||||
		return new Uniform4Float(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform4Int as4Int() {
 | 
			
		||||
		return new Uniform4Int(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform2Matrix as2Matrix() {
 | 
			
		||||
		return new Uniform2Matrix(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform3Matrix as3Matrix() {
 | 
			
		||||
		return new Uniform3Matrix(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public Uniform4Matrix as4Matrix() {
 | 
			
		||||
		return new Uniform4Matrix(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +1,44 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.FloatBuffer;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform1Float extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform1Float(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(float value) {
 | 
			
		||||
		glUniform1f(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(float[] value) {
 | 
			
		||||
		glUniform1fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(FloatBuffer value) {
 | 
			
		||||
		glUniform1fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.FloatBuffer;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform1Float extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform1Float(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(float value) {
 | 
			
		||||
		glUniform1f(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(float[] value) {
 | 
			
		||||
		glUniform1fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(FloatBuffer value) {
 | 
			
		||||
		glUniform1fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +1,44 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.IntBuffer;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform1Int extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform1Int(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(int value) {
 | 
			
		||||
		glUniform1i(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(int[] value) {
 | 
			
		||||
		glUniform1iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(IntBuffer value) {
 | 
			
		||||
		glUniform1iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.IntBuffer;
 | 
			
		||||
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform1Int extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform1Int(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(int value) {
 | 
			
		||||
		glUniform1i(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(int[] value) {
 | 
			
		||||
		glUniform1iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(IntBuffer value) {
 | 
			
		||||
		glUniform1iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,48 +1,49 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.FloatBuffer;
 | 
			
		||||
 | 
			
		||||
import glm.vec._2.Vec2;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform2Float extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform2Float(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(float x, float y) {
 | 
			
		||||
		glUniform2f(handle, x, y);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(float[] value) {
 | 
			
		||||
		glUniform2fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(FloatBuffer value) {
 | 
			
		||||
		glUniform2fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(Vec2 value) {
 | 
			
		||||
		glUniform2f(handle, value.x, value.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.FloatBuffer;
 | 
			
		||||
 | 
			
		||||
import glm.vec._2.Vec2;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform2Float extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform2Float(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(float x, float y) {
 | 
			
		||||
		glUniform2f(handle, x, y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(float[] value) {
 | 
			
		||||
		glUniform2fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(FloatBuffer value) {
 | 
			
		||||
		glUniform2fv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(Vec2 value) {
 | 
			
		||||
		glUniform2f(handle, value.x, value.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,48 +1,49 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.IntBuffer;
 | 
			
		||||
 | 
			
		||||
import glm.vec._2.i.Vec2i;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform2Int extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform2Int(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(int x, int y) {
 | 
			
		||||
		glUniform2i(handle, x, y);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(int[] value) {
 | 
			
		||||
		glUniform2iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(IntBuffer value) {
 | 
			
		||||
		glUniform2iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void set(Vec2i value) {
 | 
			
		||||
		glUniform2i(handle, value.x, value.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * 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.shaders.uniforms;
 | 
			
		||||
 | 
			
		||||
import static org.lwjgl.opengl.GL20.*;
 | 
			
		||||
import java.nio.IntBuffer;
 | 
			
		||||
 | 
			
		||||
import glm.vec._2.i.Vec2i;
 | 
			
		||||
import ru.windcorp.progressia.client.graphics.backend.shaders.Program;
 | 
			
		||||
 | 
			
		||||
public class Uniform2Int extends Uniform {
 | 
			
		||||
 | 
			
		||||
	public Uniform2Int(int handle, Program program) {
 | 
			
		||||
		super(handle, program);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(int x, int y) {
 | 
			
		||||
		glUniform2i(handle, x, y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(int[] value) {
 | 
			
		||||
		glUniform2iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(IntBuffer value) {
 | 
			
		||||
		glUniform2iv(handle, value);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public void set(Vec2i value) {
 | 
			
		||||
		glUniform2i(handle, value.x, value.y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user