2014-07-02 01:32:03 +02:00
/ *
* opsu ! - an open - source osu ! client
2015-01-16 18:05:44 +01:00
* Copyright ( C ) 2014 , 2015 Jeffrey Han
2014-07-02 01:32:03 +02:00
*
* opsu ! is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* opsu ! is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with opsu ! . If not , see < http : //www.gnu.org/licenses/>.
* /
package itdelatrisu.opsu ;
2017-01-17 23:18:12 +01:00
import itdelatrisu.opsu.audio.MusicController ;
2015-08-29 04:29:21 +02:00
import itdelatrisu.opsu.audio.SoundController ;
import itdelatrisu.opsu.audio.SoundEffect ;
import itdelatrisu.opsu.beatmap.HitObject ;
import itdelatrisu.opsu.downloads.Download ;
import itdelatrisu.opsu.downloads.DownloadNode ;
import itdelatrisu.opsu.replay.PlaybackSpeed ;
import itdelatrisu.opsu.ui.Fonts ;
import itdelatrisu.opsu.ui.UI ;
2015-01-20 06:54:12 +01:00
import java.awt.image.BufferedImage ;
2015-03-16 04:05:27 +01:00
import java.io.BufferedInputStream ;
2015-03-07 10:17:19 +01:00
import java.io.BufferedReader ;
2014-07-02 01:32:03 +02:00
import java.io.File ;
2015-03-16 04:05:27 +01:00
import java.io.FileInputStream ;
2015-09-01 00:54:32 +02:00
import java.io.FileReader ;
2015-02-12 08:27:33 +01:00
import java.io.IOException ;
2015-03-07 10:17:19 +01:00
import java.io.InputStream ;
import java.io.InputStreamReader ;
import java.net.HttpURLConnection ;
import java.net.SocketTimeoutException ;
2015-05-07 19:28:40 +02:00
import java.net.URISyntaxException ;
2015-03-07 10:17:19 +01:00
import java.net.URL ;
2015-01-20 06:54:12 +01:00
import java.nio.ByteBuffer ;
2016-12-23 01:54:05 +01:00
import java.nio.file.Paths ;
2015-03-16 04:05:27 +01:00
import java.security.MessageDigest ;
import java.security.NoSuchAlgorithmException ;
2016-10-13 07:17:59 +02:00
import java.security.cert.X509Certificate ;
2014-07-02 01:32:03 +02:00
import java.text.SimpleDateFormat ;
2015-02-02 06:15:16 +01:00
import java.util.Arrays ;
2014-07-02 01:32:03 +02:00
import java.util.Date ;
2015-03-09 23:32:43 +01:00
import java.util.Scanner ;
2015-08-27 21:14:04 +02:00
import java.util.jar.JarFile ;
2014-07-02 01:32:03 +02:00
2015-01-20 06:54:12 +01:00
import javax.imageio.ImageIO ;
2016-10-13 07:17:59 +02:00
import javax.net.ssl.HttpsURLConnection ;
import javax.net.ssl.SSLContext ;
import javax.net.ssl.TrustManager ;
import javax.net.ssl.X509TrustManager ;
2015-01-20 06:54:12 +01:00
2015-05-17 07:58:54 +02:00
import org.json.JSONArray ;
2015-05-08 05:58:04 +02:00
import org.json.JSONException ;
import org.json.JSONObject ;
2014-07-02 01:32:03 +02:00
import org.lwjgl.BufferUtils ;
2015-01-20 06:54:12 +01:00
import org.lwjgl.opengl.Display ;
import org.lwjgl.opengl.GL11 ;
2014-07-02 01:32:03 +02:00
import org.newdawn.slick.Animation ;
2016-09-29 22:41:56 +02:00
import org.newdawn.slick.Color ;
2014-07-02 01:32:03 +02:00
import org.newdawn.slick.GameContainer ;
import org.newdawn.slick.Input ;
import org.newdawn.slick.state.StateBasedGame ;
import org.newdawn.slick.util.Log ;
2015-02-12 08:27:33 +01:00
import com.sun.jna.platform.FileUtils ;
2017-01-17 23:18:12 +01:00
import yugecin.opsudance.core.DisplayContainer ;
2017-01-21 01:16:27 +01:00
import yugecin.opsudance.core.errorhandling.ErrorHandler ;
import yugecin.opsudance.core.events.EventBus ;
import yugecin.opsudance.events.BubbleNotificationEvent ;
2015-02-12 08:27:33 +01:00
2014-07-02 01:32:03 +02:00
/ * *
* Contains miscellaneous utilities .
* /
public class Utils {
2015-02-02 06:15:16 +01:00
/ * *
* List of illegal filename characters .
* @see # cleanFileName ( String , char )
* /
private final static int [ ] illegalChars = {
34 , 60 , 62 , 124 , 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ,
11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 ,
24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 58 , 42 , 63 , 92 , 47
} ;
static {
2015-08-26 00:00:34 +02:00
Arrays . sort ( illegalChars ) ;
2015-02-02 06:15:16 +01:00
}
2014-07-02 01:32:03 +02:00
// This class should not be instantiated.
private Utils ( ) { }
/ * *
* Initializes game settings and class data .
* /
2017-01-17 23:18:12 +01:00
public static void init ( DisplayContainer displayContainer ) {
// TODO clean this up
2014-07-02 01:32:03 +02:00
// game settings
2017-01-17 23:18:12 +01:00
displayContainer . setFPS ( Options . getTargetFPS ( ) ) ; // TODO move this elsewhere
MusicController . setMusicVolume ( Options . getMusicVolume ( ) * Options . getMasterVolume ( ) ) ;
2014-07-02 01:32:03 +02:00
2015-05-24 05:48:28 +02:00
// load skin
Options . loadSkin ( ) ;
2015-01-15 05:10:19 +01:00
// initialize game images
2015-01-18 23:01:13 +01:00
for ( GameImage img : GameImage . values ( ) ) {
if ( img . isPreload ( ) )
img . setDefaultImage ( ) ;
}
2014-07-19 02:33:41 +02:00
// initialize game mods
2017-01-17 23:18:12 +01:00
GameMod . init ( displayContainer . width , displayContainer . height ) ;
2014-07-02 01:32:03 +02:00
2015-04-03 14:01:18 +02:00
// initialize playback buttons
2017-01-17 23:18:12 +01:00
PlaybackSpeed . init ( displayContainer . width , displayContainer . height ) ;
2015-04-03 14:01:18 +02:00
2015-01-21 01:01:18 +01:00
// initialize hit objects
2017-01-17 23:18:12 +01:00
HitObject . init ( displayContainer . width , displayContainer . height ) ;
2015-01-21 01:01:18 +01:00
2015-02-01 08:10:17 +01:00
// initialize download nodes
2017-01-17 23:18:12 +01:00
DownloadNode . init ( displayContainer . width , displayContainer . height ) ;
2015-02-01 08:10:17 +01:00
2015-03-05 19:27:45 +01:00
// initialize UI components
2017-01-17 23:18:12 +01:00
UI . init ( displayContainer ) ;
2015-01-11 04:49:23 +01:00
}
2014-07-02 01:32:03 +02:00
/ * *
* Draws an animation based on its center .
* @param anim the animation to draw
* @param x the center x coordinate
* @param y the center y coordinate
* /
public static void drawCentered ( Animation anim , float x , float y ) {
anim . draw ( x - ( anim . getWidth ( ) / 2f ) , y - ( anim . getHeight ( ) / 2f ) ) ;
}
2016-12-19 22:33:20 +01:00
/ * *
* Returns the luminance of a color .
* @param c the color
* /
public static float getLuminance ( Color c ) {
return 0 . 299f * c . r + 0 . 587f * c . g + 0 . 114f * c . b ;
}
2015-08-06 05:28:14 +02:00
/ * *
* Clamps a value between a lower and upper bound .
* @param val the value to clamp
* @param low the lower bound
* @param high the upper bound
* @return the clamped value
* @author fluddokt
* /
public static int clamp ( int val , int low , int high ) {
if ( val < low )
return low ;
if ( val > high )
return high ;
return val ;
}
2015-02-15 07:40:01 +01:00
/ * *
* Clamps a value between a lower and upper bound .
* @param val the value to clamp
* @param low the lower bound
* @param high the upper bound
* @return the clamped value
* @author fluddokt
* /
2015-03-06 05:33:40 +01:00
public static float clamp ( float val , float low , float high ) {
2015-02-15 07:40:01 +01:00
if ( val < low )
return low ;
if ( val > high )
return high ;
return val ;
}
2016-12-10 19:30:21 +01:00
/ * *
* Clamps a value between a lower and upper bound .
* @param val the value to clamp
* @param low the lower bound
* @param high the upper bound
* @return the clamped value
* @author fluddokt
* /
public static double clamp ( double val , double low , double high ) {
if ( val < low )
return low ;
if ( val > high )
return high ;
return val ;
}
2015-02-15 07:40:01 +01:00
2015-03-28 13:11:43 +01:00
/ * *
2015-03-31 05:06:52 +02:00
* Returns the distance between two points .
* @param x1 the x - component of the first point
* @param y1 the y - component of the first point
* @param x2 the x - component of the second point
* @param y2 the y - component of the second point
* @return the Euclidean distance between points ( x1 , y1 ) and ( x2 , y2 )
2015-03-28 13:11:43 +01:00
* /
public static float distance ( float x1 , float y1 , float x2 , float y2 ) {
2016-09-27 18:44:02 +02:00
float v1 = x1 - x2 ;
float v2 = y1 - y2 ;
return ( float ) Math . sqrt ( v1 * v1 + v2 * v2 ) ;
}
public static double distance ( double x1 , double y1 , double x2 , double y2 ) {
double dx = x1 - x2 ;
double dy = y1 - y2 ;
return Math . sqrt ( dx * dx + dy * dy ) ;
2015-03-28 13:11:43 +01:00
}
2015-08-31 00:56:05 +02:00
/ * *
* Linear interpolation of a and b at t .
* /
public static float lerp ( float a , float b , float t ) {
return a * ( 1 - t ) + b * t ;
}
2014-07-18 05:58:37 +02:00
/ * *
* Returns true if a game input key is pressed ( mouse / keyboard left / right ) .
* @return true if pressed
* /
public static boolean isGameKeyPressed ( ) {
2017-01-17 23:18:12 +01:00
/ *
2015-03-03 04:12:57 +01:00
boolean mouseDown = ! Options . isMouseDisabled ( ) & & (
input . isMouseButtonDown ( Input . MOUSE_LEFT_BUTTON ) | |
input . isMouseButtonDown ( Input . MOUSE_RIGHT_BUTTON ) ) ;
return ( mouseDown | |
2014-07-18 05:58:37 +02:00
input . isKeyDown ( Options . getGameKeyLeft ( ) ) | |
input . isKeyDown ( Options . getGameKeyRight ( ) ) ) ;
2017-01-17 23:18:12 +01:00
* /
return true ;
2014-07-18 05:58:37 +02:00
}
2014-07-02 01:32:03 +02:00
/ * *
* Takes a screenshot .
2015-01-20 06:54:12 +01:00
* @author http : //wiki.lwjgl.org/index.php?title=Taking_Screen_Shots
2014-07-02 01:32:03 +02:00
* /
2015-01-20 06:54:12 +01:00
public static void takeScreenShot ( ) {
// create the screenshot directory
File dir = Options . getScreenshotDir ( ) ;
2015-07-11 17:51:52 +02:00
if ( ! dir . isDirectory ( ) & & ! dir . mkdir ( ) ) {
2017-01-21 01:16:27 +01:00
EventBus . instance . post ( new BubbleNotificationEvent ( String . format ( " Failed to create screenshot directory at '%s'. " , dir . getAbsolutePath ( ) ) , BubbleNotificationEvent . COMMONCOLOR_RED ) ) ;
2015-07-11 17:51:52 +02:00
return ;
2014-07-02 01:32:03 +02:00
}
2015-01-20 06:54:12 +01:00
// create file name
SimpleDateFormat date = new SimpleDateFormat ( " yyyyMMdd_HHmmss " ) ;
2017-01-21 01:16:27 +01:00
final String fileName = String . format ( " screenshot_%s.%s " , date . format ( new Date ( ) ) , Options . getScreenshotFormat ( ) ) ;
final File file = new File ( dir , fileName ) ;
2015-01-20 06:54:12 +01:00
SoundController . playSound ( SoundEffect . SHUTTER ) ;
// copy the screen to file
final int width = Display . getWidth ( ) ;
final int height = Display . getHeight ( ) ;
final int bpp = 3 ; // assuming a 32-bit display with a byte each for red, green, blue, and alpha
final ByteBuffer buffer = BufferUtils . createByteBuffer ( width * height * bpp ) ;
GL11 . glReadBuffer ( GL11 . GL_FRONT ) ;
GL11 . glPixelStorei ( GL11 . GL_PACK_ALIGNMENT , 1 ) ;
GL11 . glReadPixels ( 0 , 0 , width , height , GL11 . GL_RGB , GL11 . GL_UNSIGNED_BYTE , buffer ) ;
new Thread ( ) {
@Override
public void run ( ) {
try {
BufferedImage image = new BufferedImage ( width , height , BufferedImage . TYPE_INT_RGB ) ;
for ( int x = 0 ; x < width ; x + + ) {
for ( int y = 0 ; y < height ; y + + ) {
int i = ( x + ( width * y ) ) * bpp ;
int r = buffer . get ( i ) & 0xFF ;
int g = buffer . get ( i + 1 ) & 0xFF ;
int b = buffer . get ( i + 2 ) & 0xFF ;
image . setRGB ( x , height - ( y + 1 ) , ( 0xFF < < 24 ) | ( r < < 16 ) | ( g < < 8 ) | b ) ;
}
}
ImageIO . write ( image , Options . getScreenshotFormat ( ) , file ) ;
2017-01-21 01:16:27 +01:00
EventBus . instance . post ( new BubbleNotificationEvent ( " Created " + fileName , BubbleNotificationEvent . COMMONCOLOR_PURPLE ) ) ;
2015-01-20 06:54:12 +01:00
} catch ( Exception e ) {
2017-01-21 01:16:27 +01:00
ErrorHandler . error ( " Failed to take a screenshot. " , e ) . show ( ) ;
2015-01-20 06:54:12 +01:00
}
}
} . start ( ) ;
2014-07-02 01:32:03 +02:00
}
2014-08-25 05:48:52 +02:00
2015-02-01 08:10:17 +01:00
/ * *
* Returns a human - readable representation of a given number of bytes .
* @param bytes the number of bytes
* @return the string representation
* @author aioobe ( http : //stackoverflow.com/a/3758880)
* /
public static String bytesToString ( long bytes ) {
if ( bytes < 1024 )
return bytes + " B " ;
int exp = ( int ) ( Math . log ( bytes ) / Math . log ( 1024 ) ) ;
char pre = " KMGTPE " . charAt ( exp - 1 ) ;
return String . format ( " %.1f %cB " , bytes / Math . pow ( 1024 , exp ) , pre ) ;
}
2015-02-02 06:15:16 +01:00
/ * *
* Cleans a file name .
* @param badFileName the original name string
* @param replace the character to replace illegal characters with ( or 0 if none )
* @return the cleaned file name
* @author Sarel Botha ( http : //stackoverflow.com/a/5626340)
* /
public static String cleanFileName ( String badFileName , char replace ) {
2015-03-07 10:17:19 +01:00
if ( badFileName = = null )
return null ;
2015-02-02 06:15:16 +01:00
boolean doReplace = ( replace > 0 & & Arrays . binarySearch ( illegalChars , replace ) < 0 ) ;
2015-08-26 00:00:34 +02:00
StringBuilder cleanName = new StringBuilder ( ) ;
for ( int i = 0 , n = badFileName . length ( ) ; i < n ; i + + ) {
int c = badFileName . charAt ( i ) ;
if ( Arrays . binarySearch ( illegalChars , c ) < 0 )
cleanName . append ( ( char ) c ) ;
else if ( doReplace )
cleanName . append ( replace ) ;
}
return cleanName . toString ( ) ;
2015-02-02 06:15:16 +01:00
}
2015-02-12 08:27:33 +01:00
/ * *
* Deletes a file or directory . If a system trash directory is available ,
* the file or directory will be moved there instead .
* @param file the file or directory to delete
* @return true if moved to trash , and false if deleted
* @throws IOException if given file does not exist
* /
public static boolean deleteToTrash ( File file ) throws IOException {
if ( file = = null )
throw new IOException ( " File cannot be null. " ) ;
if ( ! file . exists ( ) )
throw new IOException ( String . format ( " File '%s' does not exist. " , file . getAbsolutePath ( ) ) ) ;
// move to system trash, if possible
FileUtils fileUtils = FileUtils . getInstance ( ) ;
if ( fileUtils . hasTrash ( ) ) {
try {
fileUtils . moveToTrash ( new File [ ] { file } ) ;
return true ;
} catch ( IOException e ) {
Log . warn ( String . format ( " Failed to move file '%s' to trash. " , file . getAbsolutePath ( ) ) , e ) ;
}
}
// delete otherwise
if ( file . isDirectory ( ) )
deleteDirectory ( file ) ;
else
file . delete ( ) ;
return false ;
}
/ * *
* Recursively deletes all files and folders in a directory , then
* deletes the directory itself .
* @param dir the directory to delete
* /
2016-10-13 10:20:03 +02:00
public static void deleteDirectory ( File dir ) {
2015-02-12 08:27:33 +01:00
if ( dir = = null | | ! dir . isDirectory ( ) )
return ;
// recursively delete contents of directory
File [ ] files = dir . listFiles ( ) ;
if ( files ! = null & & files . length > 0 ) {
for ( File file : files ) {
if ( file . isDirectory ( ) )
deleteDirectory ( file ) ;
else
file . delete ( ) ;
}
}
// delete the directory
dir . delete ( ) ;
}
2015-02-13 08:43:34 +01:00
2015-03-07 10:17:19 +01:00
/ * *
* Returns a the contents of a URL as a string .
* @param url the remote URL
* @return the contents as a string , or null if any error occurred
2015-05-17 07:58:54 +02:00
* @author Roland Illig ( http : //stackoverflow.com/a/4308662)
2015-09-10 05:51:16 +02:00
* @throws IOException if an I / O exception occurs
2015-03-07 10:17:19 +01:00
* /
public static String readDataFromUrl ( URL url ) throws IOException {
// open connection
HttpURLConnection conn = ( HttpURLConnection ) url . openConnection ( ) ;
conn . setConnectTimeout ( Download . CONNECTION_TIMEOUT ) ;
conn . setReadTimeout ( Download . READ_TIMEOUT ) ;
conn . setUseCaches ( false ) ;
try {
conn . connect ( ) ;
} catch ( SocketTimeoutException e ) {
Log . warn ( " Connection to server timed out. " , e ) ;
throw e ;
}
if ( Thread . interrupted ( ) )
return null ;
// read contents
try ( InputStream in = conn . getInputStream ( ) ) {
BufferedReader rd = new BufferedReader ( new InputStreamReader ( in ) ) ;
StringBuilder sb = new StringBuilder ( ) ;
int c ;
while ( ( c = rd . read ( ) ) ! = - 1 )
sb . append ( ( char ) c ) ;
return sb . toString ( ) ;
} catch ( SocketTimeoutException e ) {
Log . warn ( " Connection to server timed out. " , e ) ;
throw e ;
}
}
2015-03-09 23:32:43 +01:00
2015-05-08 05:58:04 +02:00
/ * *
* Returns a JSON object from a URL .
* @param url the remote URL
2015-05-17 07:58:54 +02:00
* @return the JSON object , or null if an error occurred
2015-09-10 05:51:16 +02:00
* @throws IOException if an I / O exception occurs
2015-05-08 05:58:04 +02:00
* /
2015-05-17 07:58:54 +02:00
public static JSONObject readJsonObjectFromUrl ( URL url ) throws IOException {
2015-05-08 05:58:04 +02:00
String s = Utils . readDataFromUrl ( url ) ;
JSONObject json = null ;
if ( s ! = null ) {
try {
json = new JSONObject ( s ) ;
} catch ( JSONException e ) {
2017-01-21 01:16:27 +01:00
ErrorHandler . error ( " Failed to create JSON object. " , e ) . show ( ) ;
2015-05-08 05:58:04 +02:00
}
}
return json ;
}
2015-05-17 07:58:54 +02:00
/ * *
* Returns a JSON array from a URL .
* @param url the remote URL
* @return the JSON array , or null if an error occurred
2015-09-10 05:51:16 +02:00
* @throws IOException if an I / O exception occurs
2015-05-17 07:58:54 +02:00
* /
public static JSONArray readJsonArrayFromUrl ( URL url ) throws IOException {
String s = Utils . readDataFromUrl ( url ) ;
JSONArray json = null ;
if ( s ! = null ) {
try {
json = new JSONArray ( s ) ;
} catch ( JSONException e ) {
2017-01-21 01:16:27 +01:00
ErrorHandler . error ( " Failed to create JSON array. " , e ) . show ( ) ;
2015-05-17 07:58:54 +02:00
}
}
return json ;
}
2015-03-09 23:32:43 +01:00
/ * *
* Converts an input stream to a string .
* @param is the input stream
* @author Pavel Repin , earcam ( http : //stackoverflow.com/a/5445161)
* /
public static String convertStreamToString ( InputStream is ) {
try ( Scanner s = new Scanner ( is ) ) {
return s . useDelimiter ( " \\ A " ) . hasNext ( ) ? s . next ( ) : " " ;
}
}
2015-03-16 04:05:27 +01:00
/ * *
* Returns the md5 hash of a file in hex form .
2015-03-19 08:04:35 +01:00
* @param file the file to hash
2015-03-16 04:05:27 +01:00
* @return the md5 hash
* /
2015-03-19 08:04:35 +01:00
public static String getMD5 ( File file ) {
2015-03-16 04:05:27 +01:00
try {
InputStream in = new BufferedInputStream ( new FileInputStream ( file ) ) ;
MessageDigest md = MessageDigest . getInstance ( " MD5 " ) ;
byte [ ] buf = new byte [ 4096 ] ;
2015-03-19 08:04:35 +01:00
while ( true ) {
2015-03-16 04:05:27 +01:00
int len = in . read ( buf ) ;
if ( len < 0 )
break ;
md . update ( buf , 0 , len ) ;
}
in . close ( ) ;
2015-03-19 08:04:35 +01:00
2015-03-16 04:05:27 +01:00
byte [ ] md5byte = md . digest ( ) ;
StringBuilder result = new StringBuilder ( ) ;
2015-03-19 08:04:35 +01:00
for ( byte b : md5byte )
2015-03-16 04:05:27 +01:00
result . append ( String . format ( " %02x " , b ) ) ;
return result . toString ( ) ;
} catch ( NoSuchAlgorithmException | IOException e ) {
2017-01-21 01:16:27 +01:00
ErrorHandler . error ( " Failed to calculate MD5 hash. " , e ) . show ( ) ;
2015-03-16 04:05:27 +01:00
}
return null ;
}
2015-03-20 03:10:38 +01:00
/ * *
* Returns a formatted time string for a given number of seconds .
* @param seconds the number of seconds
* @return the time as a readable string
* /
public static String getTimeString ( int seconds ) {
if ( seconds < 60 )
return ( seconds = = 1 ) ? " 1 second " : String . format ( " %d seconds " , seconds ) ;
else if ( seconds < 3600 )
return String . format ( " %02d:%02d " , seconds / 60 , seconds % 60 ) ;
else
return String . format ( " %02d:%02d:%02d " , seconds / 3600 , ( seconds / 60 ) % 60 , seconds % 60 ) ;
}
2015-04-07 07:24:09 +02:00
2015-05-07 19:28:40 +02:00
/ * *
* Returns whether or not the application is running within a JAR .
* @return true if JAR , false if file
* /
public static boolean isJarRunning ( ) {
2017-01-21 01:16:27 +01:00
return Utils . class . getResource ( String . format ( " %s.class " , Utils . class . getSimpleName ( ) ) ) . toString ( ) . startsWith ( " jar: " ) ;
2015-05-07 19:28:40 +02:00
}
2015-08-27 21:14:04 +02:00
/ * *
* Returns the JarFile for the application .
* @return the JAR file , or null if it could not be determined
* /
public static JarFile getJarFile ( ) {
if ( ! isJarRunning ( ) )
return null ;
try {
2017-01-21 01:16:27 +01:00
return new JarFile ( new File ( Utils . class . getProtectionDomain ( ) . getCodeSource ( ) . getLocation ( ) . toURI ( ) ) , false ) ;
2015-08-27 21:14:04 +02:00
} catch ( URISyntaxException | IOException e ) {
Log . error ( " Could not determine the JAR file. " , e ) ;
return null ;
}
}
2015-05-07 19:28:40 +02:00
/ * *
* Returns the directory where the application is being run .
2015-08-27 21:14:04 +02:00
* @return the directory , or null if it could not be determined
2015-05-07 19:28:40 +02:00
* /
public static File getRunningDirectory ( ) {
try {
2017-01-21 01:16:27 +01:00
return new File ( Utils . class . getProtectionDomain ( ) . getCodeSource ( ) . getLocation ( ) . toURI ( ) . getPath ( ) ) ;
2015-05-07 19:28:40 +02:00
} catch ( URISyntaxException e ) {
Log . error ( " Could not get the running directory. " , e ) ;
return null ;
}
}
2015-05-23 20:52:03 +02:00
2016-12-23 01:54:05 +01:00
/ * *
* Returns the current working directory .
* @return the directory
* /
public static File getWorkingDirectory ( ) {
return Paths . get ( " . " ) . toAbsolutePath ( ) . normalize ( ) . toFile ( ) ;
}
2015-05-23 20:52:03 +02:00
/ * *
* Parses the integer string argument as a boolean :
* { @code 1 } is { @code true } , and all other values are { @code false } .
* @param s the { @code String } containing the boolean representation to be parsed
* @return the boolean represented by the string argument
* /
public static boolean parseBoolean ( String s ) {
return ( Integer . parseInt ( s ) = = 1 ) ;
}
2015-09-01 00:54:32 +02:00
/ * *
* Returns the git hash of the remote - tracking branch ' origin / master ' from the
* most recent update to the working directory ( e . g . fetch or successful push ) .
* @return the 40 - character SHA - 1 hash , or null if it could not be determined
* /
public static String getGitHash ( ) {
if ( isJarRunning ( ) )
return null ;
File f = new File ( " .git/refs/remotes/origin/master " ) ;
2017-01-11 20:41:13 +01:00
if ( ! f . isFile ( ) )
f = new File ( " ../.git/refs/remotes/origin/master " ) ;
2015-09-01 00:54:32 +02:00
if ( ! f . isFile ( ) )
return null ;
try ( BufferedReader in = new BufferedReader ( new FileReader ( f ) ) ) {
char [ ] sha = new char [ 40 ] ;
if ( in . read ( sha , 0 , sha . length ) < sha . length )
return null ;
for ( int i = 0 ; i < sha . length ; i + + ) {
if ( Character . digit ( sha [ i ] , 16 ) = = - 1 )
return null ;
}
return String . valueOf ( sha ) ;
} catch ( IOException e ) {
return null ;
}
}
2016-09-27 18:36:09 +02:00
2016-10-13 07:17:59 +02:00
/ * *
* Switches validation of SSL certificates on or off by installing a default
* all - trusting { @link TrustManager } .
* @param enabled whether to validate SSL certificates
* @author neu242 ( http : //stackoverflow.com/a/876785)
* /
public static void setSSLCertValidation ( boolean enabled ) {
// create a trust manager that does not validate certificate chains
TrustManager [ ] trustAllCerts = new TrustManager [ ] {
new X509TrustManager ( ) {
@Override public X509Certificate [ ] getAcceptedIssuers ( ) { return new X509Certificate [ 0 ] ; }
@Override public void checkClientTrusted ( X509Certificate [ ] certs , String authType ) { }
@Override public void checkServerTrusted ( X509Certificate [ ] certs , String authType ) { }
}
} ;
// install the all-trusting trust manager
try {
SSLContext sc = SSLContext . getInstance ( " SSL " ) ;
sc . init ( null , enabled ? null : trustAllCerts , null ) ;
HttpsURLConnection . setDefaultSSLSocketFactory ( sc . getSocketFactory ( ) ) ;
} catch ( Exception e ) { }
}
2016-12-10 01:19:31 +01:00
2016-09-27 18:36:09 +02:00
public static int getQuadrant ( double x , double y ) {
2016-09-27 20:52:52 +02:00
if ( x < Options . width / 2d ) {
return y < Options . height / 2d ? 2 : 3 ;
2016-09-27 18:36:09 +02:00
}
2016-09-27 20:52:52 +02:00
return y < Options . height / 2d ? 1 : 4 ;
2016-09-27 18:36:09 +02:00
}
2016-09-30 19:05:53 +02:00
/ *
2016-09-29 22:41:56 +02:00
public static Color shiftHue ( Color color , double H ) {
double U = Math . cos ( H * Math . PI / 180d ) ;
double W = Math . sin ( H * Math . PI / 180d ) ;
Color n = new Color ( 0 , 0 , 0 ) ;
n . r = ( float ) ( ( 0 . 299d + 0 . 701d * U + 0 . 168d * W ) * color . r + ( 0 . 587d - 0 . 587d * U + 0 . 330d * W ) * color . g + ( 0 . 114d - 0 . 114d * U - 0 . 497 * W ) * color . b ) ;
n . g = ( float ) ( ( 0 . 299 + 0 . 299 * U - 0 . 328 * W ) * color . r + ( 0 . 587d - 0 . 413 * U + 0 . 035 * W ) * color . g + ( 0 . 114d - 0 . 114d * U - 0 . 292 * W ) * color . b ) ;
n . b = ( float ) ( ( 0 . 299d + 0 . 300d * U + 1 . 250d * W ) * color . r + ( 0 . 587d - 0 . 585d * U + 1 . 050d * W ) * color . g + ( 0 . 114 - 0 . 886 * U - 0 . 203 * W ) * color . b ) ;
return n ;
2016-09-30 09:12:54 +02:00
}
2016-09-30 19:05:53 +02:00
* /
2016-09-29 22:41:56 +02:00
2016-09-30 23:56:07 +02:00
public static float [ ] mirrorPoint ( float x , float y ) {
double dx = x - Options . width / 2d ;
double dy = y - Options . height / 2d ;
double ang = Math . atan2 ( dy , dx ) ;
double d = - Math . sqrt ( dx * dx + dy * dy ) ;
return new float [ ] {
( float ) ( Options . width / 2d + Math . cos ( ang ) * d ) ,
( float ) ( Options . height / 2d + Math . sin ( ang ) * d )
} ;
}
2016-12-25 17:30:09 +01:00
public static float [ ] mirrorPoint ( float x , float y , float degrees ) {
double dx = x - Options . width / 2d ;
double dy = y - Options . height / 2d ;
double ang = Math . atan2 ( dy , dx ) + ( degrees * Math . PI / 180d ) ;
double d = Math . sqrt ( dx * dx + dy * dy ) ;
return new float [ ] {
( float ) ( Options . width / 2d + Math . cos ( ang ) * d ) ,
( float ) ( Options . height / 2d + Math . sin ( ang ) * d )
} ;
}
2015-02-18 04:49:19 +01:00
}