Clean up
This commit is contained in:
parent
e02b195b71
commit
c48008d2a3
|
@ -97,7 +97,6 @@ public class GameData {
|
||||||
return menuImage;
|
return menuImage;
|
||||||
|
|
||||||
Image img = getSmallImage();
|
Image img = getSmallImage();
|
||||||
//img = img.getScaledCopy((GameImage.MENU_BUTTON_BG.getImage().getHeight() * 0.45f) / img.getHeight());
|
|
||||||
if (!small.hasSkinImage()) // save default image only
|
if (!small.hasSkinImage()) // save default image only
|
||||||
this.menuImage = img;
|
this.menuImage = img;
|
||||||
return img;
|
return img;
|
||||||
|
@ -463,6 +462,7 @@ public class GameData {
|
||||||
* @param x the starting x coordinate
|
* @param x the starting x coordinate
|
||||||
* @param y the y coordinate
|
* @param y the y coordinate
|
||||||
* @param scale the scale to apply
|
* @param scale the scale to apply
|
||||||
|
* @param fixedsize the width to use for all symbols
|
||||||
* @param rightAlign align right (true) or left (false)
|
* @param rightAlign align right (true) or left (false)
|
||||||
*/
|
*/
|
||||||
private void drawFixedSizeSymbolString(String str, int x, int y, float scale, float fixedsize, boolean rightAlign) {
|
private void drawFixedSizeSymbolString(String str, int x, int y, float scale, float fixedsize, boolean rightAlign) {
|
||||||
|
@ -557,7 +557,6 @@ public class GameData {
|
||||||
|
|
||||||
if (!breakPeriod) {
|
if (!breakPeriod) {
|
||||||
// scorebar
|
// scorebar
|
||||||
// TODO: these might need to be scaled by cropping the empty (transparent) space around the images...
|
|
||||||
float healthRatio = healthDisplay / 100f;
|
float healthRatio = healthDisplay / 100f;
|
||||||
if (firstObject) { // gradually move ki before map begins
|
if (firstObject) { // gradually move ki before map begins
|
||||||
if (firstObjectTime >= 1500 && trackPosition < firstObjectTime - 500)
|
if (firstObjectTime >= 1500 && trackPosition < firstObjectTime - 500)
|
||||||
|
@ -566,13 +565,13 @@ public class GameData {
|
||||||
Image scorebar = GameImage.SCOREBAR_BG.getImage();
|
Image scorebar = GameImage.SCOREBAR_BG.getImage();
|
||||||
Image colour;
|
Image colour;
|
||||||
if (scorebarColour != null){
|
if (scorebarColour != null){
|
||||||
scorebarColour.updateNoDraw(); //TODO
|
scorebarColour.updateNoDraw(); //TODO deprecated method
|
||||||
colour = scorebarColour.getCurrentFrame();
|
colour = scorebarColour.getCurrentFrame();
|
||||||
} else {
|
} else {
|
||||||
colour = GameImage.SCOREBAR_COLOUR.getImage();
|
colour = GameImage.SCOREBAR_COLOUR.getImage();
|
||||||
}
|
}
|
||||||
float colourX = 4 * GameImage.uiscale, colourY = 15 * GameImage.uiscale;
|
float colourX = 4 * GameImage.uiscale, colourY = 15 * GameImage.uiscale;
|
||||||
Image colourCropped = colour.getSubImage(0, 0, (int) (648 * GameImage.uiscale * healthRatio), colour.getHeight());
|
Image colourCropped = colour.getSubImage(0, 0, (int) (645 * GameImage.uiscale * healthRatio), colour.getHeight());
|
||||||
|
|
||||||
scorebar.setAlpha(1f);
|
scorebar.setAlpha(1f);
|
||||||
scorebar.draw(0, 0);
|
scorebar.draw(0, 0);
|
||||||
|
@ -585,7 +584,7 @@ public class GameData {
|
||||||
ki = GameImage.SCOREBAR_KI_DANGER.getImage();
|
ki = GameImage.SCOREBAR_KI_DANGER.getImage();
|
||||||
else
|
else
|
||||||
ki = GameImage.SCOREBAR_KI_DANGER2.getImage();
|
ki = GameImage.SCOREBAR_KI_DANGER2.getImage();
|
||||||
ki.drawCentered(colourX + colourCropped.getWidth(), colourY);//ki.getHeight() / 2f);
|
ki.drawCentered(colourX + colourCropped.getWidth(), colourY);
|
||||||
|
|
||||||
// combo burst
|
// combo burst
|
||||||
if (comboBurstIndex != -1 && comboBurstAlpha > 0f) {
|
if (comboBurstIndex != -1 && comboBurstAlpha > 0f) {
|
||||||
|
@ -662,30 +661,24 @@ public class GameData {
|
||||||
Image rankingTitle = GameImage.RANKING_TITLE.getImage();
|
Image rankingTitle = GameImage.RANKING_TITLE.getImage();
|
||||||
// ranking panel
|
// ranking panel
|
||||||
Image rankingPanel = GameImage.RANKING_PANEL.getImage();
|
Image rankingPanel = GameImage.RANKING_PANEL.getImage();
|
||||||
int rankingPanelWidth = rankingPanel.getWidth();
|
|
||||||
int rankingPanelHeight = rankingPanel.getHeight();
|
|
||||||
|
|
||||||
|
|
||||||
//Version 2 skins are a little lower
|
//TODO Version 2 skins
|
||||||
//default is version 2
|
float rankingHeight = 75;
|
||||||
//has an ini with no version 2 is higher
|
|
||||||
float rankingHeight = 75;//height/2 -rankingPanelHeight/2 - 0;//(rankingTitle.getHeight() * 0.75f) + 3;
|
|
||||||
//if(Skin.version==2)
|
|
||||||
|
|
||||||
|
rankingPanel.draw(0, (int) (rankingHeight * GameImage.uiscale));
|
||||||
rankingPanel.draw(0, (int)((rankingHeight
|
|
||||||
//+ ((Skin.version==2)? 20:)
|
|
||||||
)* GameImage.uiscale));//(height -rankingTitle.getHeight()+rankingPanelHeight)/2 - rankingPanelHeight);//rankingHeight - (rankingHeight / 10f));
|
|
||||||
//System.err.println(rankingPanelHeight);
|
|
||||||
|
|
||||||
float scoreTextScale = 1.0f;
|
float scoreTextScale = 1.0f;
|
||||||
float symbolTextScale = 1.15f;
|
float symbolTextScale = 1.15f;
|
||||||
float rankResultScale = 0.5f;// * GameImage.uiscale;
|
float rankResultScale = 0.5f;
|
||||||
|
|
||||||
// score
|
// score
|
||||||
drawFixedSizeSymbolString((score < 100000000) ? String.format("%08d", score) : Long.toString(score),
|
drawFixedSizeSymbolString(
|
||||||
(int) (210 * GameImage.uiscale), (int) ((rankingHeight+50)* GameImage.uiscale),
|
(score < 100000000) ? String.format("%08d", score) : Long.toString(score),
|
||||||
scoreTextScale, getScoreSymbolImage('0').getWidth()*scoreTextScale-2, false);
|
(int) (210 * GameImage.uiscale),
|
||||||
|
(int) ((rankingHeight + 50) * GameImage.uiscale),
|
||||||
|
scoreTextScale,
|
||||||
|
getScoreSymbolImage('0').getWidth() * scoreTextScale - 2, false);
|
||||||
|
|
||||||
// result counts
|
// result counts
|
||||||
float resultInitialX = 130;
|
float resultInitialX = 130;
|
||||||
|
@ -724,18 +717,21 @@ public class GameData {
|
||||||
// combo and accuracy
|
// combo and accuracy
|
||||||
Image rankingMaxCombo = GameImage.RANKING_MAXCOMBO.getImage();
|
Image rankingMaxCombo = GameImage.RANKING_MAXCOMBO.getImage();
|
||||||
Image rankingAccuracy = GameImage.RANKING_ACCURACY.getImage();
|
Image rankingAccuracy = GameImage.RANKING_ACCURACY.getImage();
|
||||||
float offsetX = 295;
|
float accuracyX = 295;
|
||||||
float textY = rankingHeight + 425;
|
float textY = rankingHeight + 425;
|
||||||
float numbersX = rankingMaxCombo.getWidth() * .07f;
|
|
||||||
float numbersY = textY + 30;
|
float numbersY = textY + 30;
|
||||||
drawSymbolString(String.format("%dx", comboMax),
|
drawSymbolString(String.format("%dx", comboMax),
|
||||||
(int)(25 * GameImage.uiscale),(int) (numbersY * GameImage.uiscale),
|
(int) (25 * GameImage.uiscale),
|
||||||
symbolTextScale, false);
|
|
||||||
drawSymbolString(String.format("%02.2f%%", getScorePercent()),
|
|
||||||
(int) ((offsetX+20) * GameImage.uiscale),
|
|
||||||
(int) (numbersY * GameImage.uiscale), symbolTextScale, false);
|
(int) (numbersY * GameImage.uiscale), symbolTextScale, false);
|
||||||
rankingMaxCombo.draw((int)(10 * GameImage.uiscale), (int)(textY * GameImage.uiscale));
|
drawSymbolString(String.format("%02.2f%%", getScorePercent()),
|
||||||
rankingAccuracy.draw((int)(offsetX * GameImage.uiscale), (int)(textY * GameImage.uiscale));
|
(int) ((accuracyX + 20) * GameImage.uiscale),
|
||||||
|
(int) (numbersY * GameImage.uiscale), symbolTextScale, false);
|
||||||
|
rankingMaxCombo.draw(
|
||||||
|
(int) (10 * GameImage.uiscale),
|
||||||
|
(int) (textY * GameImage.uiscale));
|
||||||
|
rankingAccuracy.draw(
|
||||||
|
(int) (accuracyX * GameImage.uiscale),
|
||||||
|
(int) (textY * GameImage.uiscale));
|
||||||
|
|
||||||
|
|
||||||
// full combo
|
// full combo
|
||||||
|
@ -748,11 +744,11 @@ public class GameData {
|
||||||
// grade
|
// grade
|
||||||
Grade grade = getGrade();
|
Grade grade = getGrade();
|
||||||
if (grade != Grade.NULL)
|
if (grade != Grade.NULL)
|
||||||
grade.getLargeImage().draw(width-grade.getLargeImage().getWidth(), 30);
|
grade.getLargeImage().draw(width-grade.getLargeImage().getWidth(), rankingHeight);
|
||||||
|
|
||||||
//Header
|
//Header
|
||||||
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
g.setColor(Utils.COLOR_BLACK_ALPHA);
|
||||||
g.fillRect(0, 0, width, rankingHeight);
|
g.fillRect(0, 0, width, 100 * GameImage.uiscale);
|
||||||
rankingTitle.draw((width * 0.97f) - rankingTitle.getWidth(), 0);
|
rankingTitle.draw((width * 0.97f) - rankingTitle.getWidth(), 0);
|
||||||
Utils.FONT_LARGE.drawString(marginX, marginY,
|
Utils.FONT_LARGE.drawString(marginX, marginY,
|
||||||
String.format("%s - %s [%s]", osu.getArtist(), osu.getTitle(), osu.version), Color.white);
|
String.format("%s - %s [%s]", osu.getArtist(), osu.getTitle(), osu.version), Color.white);
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
package itdelatrisu.opsu;
|
package itdelatrisu.opsu;
|
||||||
|
|
||||||
import itdelatrisu.opsu.states.SongMenu;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -42,12 +40,7 @@ public enum GameImage {
|
||||||
SECTION_PASS ("section-pass", "png"),
|
SECTION_PASS ("section-pass", "png"),
|
||||||
SECTION_FAIL ("section-fail", "png"),
|
SECTION_FAIL ("section-fail", "png"),
|
||||||
WARNINGARROW ("play-warningarrow", "png"),
|
WARNINGARROW ("play-warningarrow", "png"),
|
||||||
SKIP ("play-skip", "png") {
|
SKIP ("play-skip", "png"),
|
||||||
@Override
|
|
||||||
protected Image process_sub(Image img, int w, int h) {
|
|
||||||
return img.getScaledCopy((h * 0.1f) / img.getHeight());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
COUNTDOWN_READY ("ready", "png") {
|
COUNTDOWN_READY ("ready", "png") {
|
||||||
@Override
|
@Override
|
||||||
protected Image process_sub(Image img, int w, int h) {
|
protected Image process_sub(Image img, int w, int h) {
|
||||||
|
@ -276,6 +269,7 @@ public enum GameImage {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MENU_BACK ("menu-back", "png", false, false),
|
MENU_BACK ("menu-back", "png", false, false),
|
||||||
|
//MENU_BACK ("menu-back", "menu-back-%d","png") //TODO menu-back animation
|
||||||
MENU_BUTTON_BG ("menu-button-background", "png", false, false),
|
MENU_BUTTON_BG ("menu-button-background", "png", false, false),
|
||||||
MENU_TAB ("selection-tab", "png", false, false) {
|
MENU_TAB ("selection-tab", "png", false, false) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -434,6 +428,7 @@ public enum GameImage {
|
||||||
/** Container dimensions. */
|
/** Container dimensions. */
|
||||||
private static int containerWidth, containerHeight;
|
private static int containerWidth, containerHeight;
|
||||||
|
|
||||||
|
/** value ui should be scaled by */
|
||||||
public static float uiscale;
|
public static float uiscale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -102,11 +102,6 @@ public class Opsu extends StateBasedGame {
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Log.error(e);
|
Log.error(e);
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
System.setOut(new PrintStream(new FileOutputStream("jnlog.txt", false)));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
Log.error(e);
|
|
||||||
}
|
|
||||||
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void uncaughtException(Thread t, Throwable e) {
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
@ -118,12 +113,12 @@ public class Opsu extends StateBasedGame {
|
||||||
Options.parseOptions();
|
Options.parseOptions();
|
||||||
|
|
||||||
// only allow a single instance
|
// only allow a single instance
|
||||||
/*try {
|
try {
|
||||||
SERVER_SOCKET = new ServerSocket(Options.getPort());
|
SERVER_SOCKET = new ServerSocket(Options.getPort());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
ErrorHandler.error(String.format("Another program is already running on port %d.", Options.getPort()), e, false);
|
ErrorHandler.error(String.format("Another program is already running on port %d.", Options.getPort()), e, false);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
// set path for lwjgl natives - NOT NEEDED if using JarSplice
|
// set path for lwjgl natives - NOT NEEDED if using JarSplice
|
||||||
File nativeDir = new File("./target/natives/");
|
File nativeDir = new File("./target/natives/");
|
||||||
|
|
|
@ -297,6 +297,9 @@ public class OsuHitObject {
|
||||||
*/
|
*/
|
||||||
public boolean isNewCombo() { return (type & TYPE_NEWCOMBO) > 0; }
|
public boolean isNewCombo() { return (type & TYPE_NEWCOMBO) > 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of extra skips on the combo colours
|
||||||
|
*/
|
||||||
public int getComboSkip() {
|
public int getComboSkip() {
|
||||||
return (type >> 4);
|
return (type >> 4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,12 +139,11 @@ public class OsuParser {
|
||||||
private static OsuFile parseFile(File file, File dir, ArrayList<OsuFile> osuFiles, boolean parseObjects) {
|
private static OsuFile parseFile(File file, File dir, ArrayList<OsuFile> osuFiles, boolean parseObjects) {
|
||||||
OsuFile osu = new OsuFile(file);
|
OsuFile osu = new OsuFile(file);
|
||||||
|
|
||||||
String version ="";
|
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
||||||
|
|
||||||
// initialize timing point list
|
// initialize timing point list
|
||||||
osu.timingPoints = new ArrayList<OsuTimingPoint>();
|
osu.timingPoints = new ArrayList<OsuTimingPoint>();
|
||||||
|
|
||||||
version = in.readLine();
|
|
||||||
String line = in.readLine();
|
String line = in.readLine();
|
||||||
String tokens[] = null;
|
String tokens[] = null;
|
||||||
while (line != null) {
|
while (line != null) {
|
||||||
|
@ -492,8 +491,6 @@ public class OsuParser {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//System.out.println("Dead: "+line+" "+file);
|
|
||||||
|
|
||||||
line = in.readLine();
|
line = in.readLine();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -503,10 +500,8 @@ public class OsuParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no custom colors, use the default color scheme
|
// if no custom colors, use the default color scheme
|
||||||
if (osu.combo == null){
|
if (osu.combo == null)
|
||||||
System.out.println("Default Combo "+version+" "+file+" "+osu.combo);
|
|
||||||
osu.combo = Utils.DEFAULT_COMBO;
|
osu.combo = Utils.DEFAULT_COMBO;
|
||||||
}
|
|
||||||
|
|
||||||
// parse hit objects now?
|
// parse hit objects now?
|
||||||
if (parseObjects)
|
if (parseObjects)
|
||||||
|
@ -531,7 +526,6 @@ public class OsuParser {
|
||||||
+ osu.hitObjectSlider + osu.hitObjectSpinner)];
|
+ osu.hitObjectSlider + osu.hitObjectSpinner)];
|
||||||
|
|
||||||
try (BufferedReader in = new BufferedReader(new FileReader(osu.getFile()))) {
|
try (BufferedReader in = new BufferedReader(new FileReader(osu.getFile()))) {
|
||||||
String version = in.readLine();
|
|
||||||
String line = in.readLine();
|
String line = in.readLine();
|
||||||
while (line != null) {
|
while (line != null) {
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
|
@ -553,22 +547,16 @@ public class OsuParser {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
while ((line = in.readLine()) != null && objectIndex < osu.objects.length) {
|
while ((line = in.readLine()) != null && objectIndex < osu.objects.length) {
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
if (!isValidLine(line)){
|
if (!isValidLine(line))
|
||||||
System.out.println("Not Valid :"+line);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (line.charAt(0) == '[')
|
if (line.charAt(0) == '[')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// lines must have at minimum 5 parameters
|
// lines must have at minimum 5 parameters
|
||||||
int tokenCount = line.length() - line.replace(",", "").length();
|
int tokenCount = line.length() - line.replace(",", "").length();
|
||||||
if (tokenCount < 4){
|
if (tokenCount < 4)
|
||||||
System.out.println("(tokenCount < 4 :"+line);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// create a new OsuHitObject for each line
|
// create a new OsuHitObject for each line
|
||||||
OsuHitObject hitObject = new OsuHitObject(line);
|
OsuHitObject hitObject = new OsuHitObject(line);
|
||||||
|
|
|
@ -181,8 +181,7 @@ public class OptionsMenu extends BasicGameState {
|
||||||
float tabX = (width / 50) + (tabImage.getWidth() / 2f);
|
float tabX = (width / 50) + (tabImage.getWidth() / 2f);
|
||||||
float tabY = 15 + Utils.FONT_XLARGE.getLineHeight() + (tabImage.getHeight() / 2f);
|
float tabY = 15 + Utils.FONT_XLARGE.getLineHeight() + (tabImage.getHeight() / 2f);
|
||||||
int tabOffset = Math.min(tabImage.getWidth(),
|
int tabOffset = Math.min(tabImage.getWidth(),
|
||||||
//((width - subtextWidth - tabImage.getWidth()) / 2) / OptionTab.SIZE);
|
(width/2) / OptionTab.SIZE);
|
||||||
(width/3) / OptionTab.SIZE);
|
|
||||||
for (OptionTab tab : OptionTab.values())
|
for (OptionTab tab : OptionTab.values())
|
||||||
tab.button = new MenuButton(tabImage, tabX + (tab.ordinal() * tabOffset), tabY);
|
tab.button = new MenuButton(tabImage, tabX + (tab.ordinal() * tabOffset), tabY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, Slick2D
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* - Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
* - Neither the name of the Slick2D nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.newdawn.slick;
|
package org.newdawn.slick;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user